Как избежать некоторых пользовательских представлений, замораживающих поток пользовательского интерфейса?
У меня есть 9 пользовательских представлений (расширяя класс View для каждого из них) в одном из моих игровых окон, которые вызывают зависание в моем потоке пользовательского интерфейса. Когда я нажимаю кнопку "Play", приложение зависает (при надувании макета в "onCreateView"). "Я использую фрагменты), пока не сгенерировано окно игры, что-то очень-очень уродливое.
Я пытаюсь сделать это в отдельном потоке, но все проблемы, Android не позволяет мне создавать новые представления из основного потока (UI).
Я пробовал так много вещей, но я не могу получить это, может кто-нибудь сказать мне, как этого добиться? большое спасибо
2 ответа
Для очень интенсивного рисования процессора вы можете использовать.
http://developer.android.com/reference/android/view/SurfaceView.html
Одна из целей этого класса - предоставить поверхность, на которой вторичный поток может рендериться на экран.
Я решил это, вручную надувая макет в AsyncTask. Я вызываю AsyncTask из "Окна воспроизведения", где я показываю представление "загрузки", а в "onPostExecute" я создаю "Окно игры" (фрагмент) и заменяю его.
Немного фиктивного кода (PlayFragment - предыдущий экран GameFragment):
"Нажатие кнопки воспроизведения" (PlayFragment):
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_play:
Bundle bundle = new Bundle();
bundle.putSerializable(ARG_SELECTED_GAME, selectedGame);
rlLoadingGame.setVisibility(View.VISIBLE);
GameFragment gameFragment = GameFragment.newInstance(selectedGame);
gameFragment.loadGame(activity, bundle);
break;
}
}
метод loadGame (GameFragment):
public void loadGame(Activity activity, Bundle bundle) {
this.activity = activity;
if (bundle != null) {
currentGame = (Game) bundle.getSerializable(ARG_SELECTED_GAME);
}
new GenerateGame(bundle).execute();
}
GenerateGame AsyncTask (GameFragment):
class GenerateGame extends AsyncTask<Void, Void>, View> {
private Bundle bundle;
public GenerateGame(Bundle bundle) {
this.bundle = bundle;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
// do your stuff
}
@Override
protected View doInBackground(Void... params) {
View child = activity.getLayoutInflater().inflate(R.layout.game_fragment_layout, null);
// do all your heavy load stuff
return child;
}
@Override
protected void onPostExecute(View layout) {
super.onPostExecute(layout);
// initialize and set all UI elements
replaceFragment(layout, bundle);
}
}
метод replaceFragment (GameFragment):
private void replaceFragment(View newView, Bundle bundle) {
fragmentLayout = newView;
// call to fragment manager replace/add or required method passing this as Fragment to replace and the bundle if needed
}
onCreateView (GameFragment):
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (fragmentLayout != null) {
return fragmentLayout;
} else {
return null;
}
}
Это первый подход, поэтому он может быть подвергнут рефакторингу, и многие вещи можно сделать лучше, но это зависит от вас.