Воссоздать активность, передав жестко закодированное нулевое состояние
Я делаю игру-головоломку, и каждый раз, когда пользователь завершает головоломку, появляется кнопка воссоздания, которая просто вызывает метод refreshate() для перезапуска активности головоломки.
Я переопределяю onSaveInstanceState, потому что хочу сохранить изображение, выбранное для головоломки, и 4 фрагмента в случае изменения ориентации экрана.
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable("originalBM", originalBm);
outState.putParcelable("bm1", bm1);
outState.putParcelable("bm2", bm2);
outState.putParcelable("bm3", bm3);
outState.putParcelable("bm4", bm4);
}
Таким образом, когда пользователь нажимает кнопку воссоздания, вызывается метод refreshate(), который также вызывает метод onSaveInstanceState по умолчанию, потому что именно так работает Android, и пользователю придется снова и снова играть в пазл с тем же изображением.
Я не хочу реализовывать тот же код, который у меня есть в моем методе onCreate, чтобы выбрать новое случайное изображение, потому что это вызывает утечки памяти, и мое приложение вылетает после 10-12 повторных попыток.
Я просто хочу, чтобы это возобновило деятельность чистой и свежей!
Вместо того, чтобы использовать restate() внутри моего метода refreshatePuzzle, я также попробовал это
Intent intent = getIntent();
finish();
startActivity(intent);
Но это снова вызывает сбой моего приложения после 10-12 повторных попыток. Это также вызывает утечки памяти.
Итак, я считаю, что лучший способ сделать это - пропустить Override saveInstanceState, когда вызывается моя restatePuzzle (если это возможно), или передать пустой Bundle, когда вызывается onSaveInstanceState.
Есть ли способ реализовать какое-либо из этих решений выше?
Любая помощь будет высоко оценен.
Спасибо всем заранее.
РЕДАКТИРОВАТЬ:
Полный код моего класса
package kidsbook.jok.kidsbook;
public class Puzzle extends AppCompatActivity {
private String[] puzzleIMGS;
private String randomPuzzleIMG;
private int corrects = 0, tries = 0;
private ImageView part1, part2, part3, part4;
private TextView piece1, piece2, piece3, piece4;
private Button againButton;
private Bitmap bm1, bm2, bm3, bm4, originalBm;
private Intent i;
private MediaPlayer mp = new MediaPlayer();
private List<Bitmap> parts = new ArrayList<>();
private boolean recreatePuzzle = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_puzzle);
mp = MediaPlayer.create(getApplicationContext(), R.raw.pop);
//Select random image
puzzleIMGS = getResources().getStringArray(R.array.all_animal_imgs);
randomPuzzleIMG = puzzleIMGS[new Random().nextInt(puzzleIMGS.length)];
//Get all elements
againButton = (Button) findViewById(R.id.againPuzzleButton);
part1 = (ImageView) findViewById(R.id.part1);
part2 = (ImageView) findViewById(R.id.part2);
part3 = (ImageView) findViewById(R.id.part3);
part4 = (ImageView) findViewById(R.id.part4);
piece1 = (TextView) findViewById(R.id.piece1);
piece2 = (TextView) findViewById(R.id.piece2);
piece3 = (TextView) findViewById(R.id.piece3);
piece4 = (TextView) findViewById(R.id.piece4);
part1.setOnTouchListener(new MyTouchListener());
part2.setOnTouchListener(new MyTouchListener());
part3.setOnTouchListener(new MyTouchListener());
part4.setOnTouchListener(new MyTouchListener());
piece1.setOnDragListener(new MyDragListener());
piece2.setOnDragListener(new MyDragListener());
piece3.setOnDragListener(new MyDragListener());
piece4.setOnDragListener(new MyDragListener());
if(savedInstanceState!=null) {
Log.i("debug","inside saved instance");
//Convert randomly selected resource image to bitmap
originalBm = savedInstanceState.getParcelable("originalBM");
bm1 = savedInstanceState.getParcelable("bm1");
bm2 = savedInstanceState.getParcelable("bm2");
bm3 = savedInstanceState.getParcelable("bm3");
bm4 = savedInstanceState.getParcelable("bm4");
} else {
Log.i("debug","inside null instance");
//Convert randomly selected resource image to bitmap
originalBm = BitmapFactory.decodeResource(getResources(), getImageId(this, randomPuzzleIMG));
//Split bitmap to 4 parts
bm1 = Bitmap.createBitmap(originalBm, 0, 0, (originalBm.getWidth() / 2), (originalBm.getHeight() / 2));
bm2 = Bitmap.createBitmap(originalBm, (originalBm.getWidth() / 2), 0, (originalBm.getWidth() / 2), (originalBm.getHeight() / 2));
bm3 = Bitmap.createBitmap(originalBm, 0, (originalBm.getHeight() / 2), (originalBm.getWidth() / 2), (originalBm.getHeight() / 2));
bm4 = Bitmap.createBitmap(originalBm, (originalBm.getWidth() / 2), (originalBm.getHeight() / 2), (originalBm.getWidth() / 2), (originalBm.getHeight() / 2));
}
//Make the background transparent
piece1.setBackgroundDrawable(new BitmapDrawable(getResources(), bm1));
piece1.setAlpha(0.2f);
piece2.setBackgroundDrawable(new BitmapDrawable(getResources(), bm2));
piece2.setAlpha(0.2f);
piece3.setBackgroundDrawable(new BitmapDrawable(getResources(), bm3));
piece3.setAlpha(0.2f);
piece4.setBackgroundDrawable(new BitmapDrawable(getResources(), bm4));
piece4.setAlpha(0.2f);
//Place parts in an array
parts.add(bm1);
parts.add(bm2);
parts.add(bm3);
parts.add(bm4);
//Shuffle the array
Collections.shuffle(parts);
//Assign the correct piece tag to each part
for(int i=0;i<4;i++){
if(i==1) {
part1.setImageBitmap(parts.get(i));
if (parts.get(i).equals(bm1)){
part1.setTag("piece1");
} else if (parts.get(i).equals(bm2)){
part1.setTag("piece2");
} else if (parts.get(i).equals(bm3)){
part1.setTag("piece3");
} else {
part1.setTag("piece4");
}
} else if(i==2){
part2.setImageBitmap(parts.get(i));
if (parts.get(i).equals(bm1)){
part2.setTag("piece1");
} else if (parts.get(i).equals(bm2)){
part2.setTag("piece2");
} else if (parts.get(i).equals(bm3)){
part2.setTag("piece3");
} else {
part2.setTag("piece4");
}
} else if(i==3){
part3.setImageBitmap(parts.get(i));
if (parts.get(i).equals(bm1)){
part3.setTag("piece1");
} else if (parts.get(i).equals(bm2)){
part3.setTag("piece2");
} else if (parts.get(i).equals(bm3)){
part3.setTag("piece3");
} else {
part3.setTag("piece4");
}
} else {
part4.setImageBitmap(parts.get(i));
if (parts.get(i).equals(bm1)){
part4.setTag("piece1");
} else if (parts.get(i).equals(bm2)){
part4.setTag("piece2");
} else if (parts.get(i).equals(bm3)){
part4.setTag("piece3");
} else {
part4.setTag("piece4");
}
}
}
}
private static int getImageId(Context context, String imageName) {
return context.getResources().getIdentifier("drawable/" + imageName, null, context.getPackageName());
}
private final class MyTouchListener implements View.OnTouchListener {
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
ClipData data = ClipData.newPlainText("", "");
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
view.startDrag(data, shadowBuilder, view, 0);
return true;
} else {
return false;
}
}
}
class MyDragListener implements View.OnDragListener {
@Override
public boolean onDrag(View v, DragEvent event) {
int action = event.getAction();
switch (action) {
case DragEvent.ACTION_DRAG_STARTED:
// do nothing
break;
case DragEvent.ACTION_DRAG_ENTERED:
break;
case DragEvent.ACTION_DRAG_EXITED:
break;
case DragEvent.ACTION_DROP:
// Dropped, reassign View to ViewGroup
View view = (View) event.getLocalState();
ViewGroup owner = (ViewGroup) view.getParent();
if(view.getTag().equals(v.getTag())){
if(view.getTag().equals("piece1")){
owner.removeView(view);
useMediaPlayer();
piece1.setBackgroundDrawable(new BitmapDrawable(getResources(), bm1));
piece1.setAlpha(0.9f);
corrects++;
} else if (view.getTag().equals("piece2")){
owner.removeView(view);
useMediaPlayer();
piece2.setBackgroundDrawable(new BitmapDrawable(getResources(), bm2));
piece2.setAlpha(0.9f);
corrects++;
} else if (view.getTag().equals("piece3")){
owner.removeView(view);
useMediaPlayer();
piece3.setBackgroundDrawable(new BitmapDrawable(getResources(), bm3));
piece3.setAlpha(0.9f);
corrects++;
} else if (view.getTag().equals("piece4")) {
owner.removeView(view);
useMediaPlayer();
piece4.setBackgroundDrawable(new BitmapDrawable(getResources(), bm4));
piece4.setAlpha(0.9f);
corrects++;
}
}
tries++;
if(corrects==4){
finish();
}
break;
case DragEvent.ACTION_DRAG_ENDED:
break;
default:
break;
}
return true;
}
}
public void useMediaPlayer(){
mp.start();
}
public void againPuzzle(View v){
recreatePuzzle = true;
recreate();
}
public void finish(){
againButton.setVisibility(View.VISIBLE);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable("originalBM", originalBm);
outState.putParcelable("bm1", bm1);
outState.putParcelable("bm2", bm2);
outState.putParcelable("bm3", bm3);
outState.putParcelable("bm4", bm4);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_games, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item){
switch(item.getItemId()){
case android.R.id.home:
i = new Intent(this, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
return true;
case R.id.menu_about:
i = new Intent(this, About.class);
startActivity(i);
return true;
case R.id.menu_help:
i = new Intent(this, Help.class);
startActivity(i);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onBackPressed() {
i = new Intent(this, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
}
}
2 ответа
Как насчет того, чтобы начать то же действие, а затем завершить предыдущее? лайк:
Intent intent=new Intent(this, MainActivity.class)
startActivity(intent);
finish();
Использование Finish поможет вам избежать утечки памяти, как это делает oncreate().
Второй вариант: переместите код, выбирающий головоломку, в новый метод (например, selectNewPuzzle()), затем вызовите этот метод в onCreated и при необходимости выберите новую головоломку.
Третий вариант: использовать глобальный логический тип с именем "canSaveInstance", который имеет значение true, когда onCreate завершается. Инкапсулируйте строки, сохраняющие состояние экземпляра, в операторе if, проверяющем это логическое значение, и, когда вам нужно пересоздать, установите эту переменную false, пересоздайте как обычно (чтобы данные не сохранялись, новая головоломка была запущена), а затем снова подтвердите ее (для обработки конфигурации изменения). Вам нужно быть осторожным при воссоздании действия: if(saveinstancestate!= Null) должно стать "if(saveinstancestate!= Null && canSaveInstance) (потому что в противном случае вы можете попытаться загрузить данные, которые не были сохранены ранее).
Последний вариант: (но я не совсем понимаю, как это сделать), чтобы пользователь не запускал несколько раз пазл, а затем "запускал" новый (более старый, я думаю, будет переопределен). Возможно, вам придется провести еще несколько исследований, чтобы сделать это. Поскольку другие варианты проще, я не буду искать документацию, помогающую сделать это.
Итак, я наконец-то нашел решение. Чего мне не хватало, так это освободить растровую память моей деятельности, и это стало причиной утечки памяти. Итак, в конце концов, метод restate() выглядит так
public void againPuzzle(View v){
originalBm.recycle();
bm1.recycle();
bm2.recycle();
bm3.recycle();
bm4.recycle();
originalBm = null;
bm1 = null;
bm2 = null;
bm3 = null;
bm4 = null;
Intent intent = getIntent();
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
finish();
startActivity(intent);
}