我正在制作一个益智游戏,每次用户完成拼图时,都会出现一个重新创建按钮,它只是调用 recreate() 方法来重新启动拼图活动。
我覆盖 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);
}
因此,当用户单击重新创建按钮时,将调用 recreate() 方法,默认情况下该方法也会调用 onSaveInstanceState,因为这就是 android 的工作方式,用户将不得不一次又一次地用相同的图像玩拼图。
我不想在我的 onCreate 方法上实现相同的代码来选择一个新的随机图像,因为这会导致内存泄漏并且我的应用程序在 10-12 重新创建后崩溃。
我只是希望它以全新的方式重新启动活动!
除了在我的 recreatePuzzle 方法中使用 recreate() 之外,我还尝试了这个
Intent intent = getIntent();
finish();
startActivity(intent);
但这再次导致我的应用程序在 10-12 重新创建后崩溃。它也导致内存泄漏。
因此,我相信最好的方法是在调用我的 recreatePuzzle 时跳过 saveInstanceState 的覆盖(如果可能的话),或者在调用 onSaveInstanceState 时传递一个空 Bundle。
有没有办法实现上述任何这些解决方案?
任何帮助将不胜感激。
谢谢大家。
编辑:
我班级的完整代码
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);
}
}