Воссоздать активность, передав жестко закодированное нулевое состояние

Я делаю игру-головоломку, и каждый раз, когда пользователь завершает головоломку, появляется кнопка воссоздания, которая просто вызывает метод 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);
}
Другие вопросы по тегам