gpt4 book ai didi

java - Activity 完成运行后无法在 Android 应用程序中释放内存

转载 作者:行者123 更新时间:2023-11-29 04:47:21 25 4
gpt4 key购买 nike

我最近做了一个游戏。当我接近完成它时,我开始在开始新 Activity 时遇到 OutOfMemory 问题。在 Android Studio 中检查内存监视器后,我注意到我的 Activity 在完成后仍保留在内存中。如何释放更多内存?

编辑:

我发现了另一个线程,其中提到它可能只是调试器在内存中持有死 Activity 。我尝试在没有调试器的情况下运行我的应用程序,但在我用完内存之前我仍然只能打开和退出一个记分板 Activity 和两个游戏,因为 Activity 在退出后仍在内存中。我进行了跟踪,调用了 finish()onDestroy()

目前,根据 AS 中的内存监视器,我的 MainMenu Activity 使用了大约 90 MB 并分配了 100。当我开始游戏时它跳到 165 使用,然后从游戏返回并开始新游戏显示使用 230ish。之后开始更多游戏,内存使用量保持在 230ish,但如果我打开记分板,它会崩溃,因为它需要大约 60mb,只有 20mb 可用,分配超过 256mb 会使应用程序崩溃。如果我先打开记分牌,然后玩 2 场比赛,也会发生同样的事情。这些数字比我希望的要高,我正在研究减少每个 Activity 的 ram 使用量的方法,但我现在主要关心的是在 Activity 完成后释放 ram。

程序流程相当简单,Activity A 是主菜单,它可以启动 Activity B 及以上。除 A 外,其他 Activity 均无法启动新 Activity 。 B 和 up 之间没有通信发生,都是由 A 发起并返回 intents 给 A。

由于项目有点大,我不能真正发布所有代码,但这里是我如何从 A 启动 ScoreboardActivity 并在我的记分板类中从 B 返回 Intent 。 (由于我尝试删除引用, Activity 有点臃肿)

从 Activity A 开始:如果用户单击 ID 为 3 的按钮,则启动记分板:

if ( id == 3) {
scoreboardIntent = new Intent(getApplicationContext(), ScoreBoard.class);
startActivityForResult(scoreboardIntent, 0);
}

此处 A 从记分牌接收结果。 A 确实没有充分的理由获得结果,但我添加了这个以查看是否可以在 onResult() 回调中释放内存,所有其他 Activity 都需要返回结果虽然)

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (data.hasExtra("resultpage")) {
scoreboardIntent = null;
return;
}

这是记分牌的类文件:

public class ScoreBoard extends AppCompatActivity implements AdapterView.OnItemClickListener, View.OnClickListener {
ScoreAdapter adapter;
Firebase myFirebase;
DataSnapshot scoreSnapshot;
DataSnapshot noviceSnapshot;
DataSnapshot expertSnapshot;
String difficulty = "novice";
ArrayList<Score> scores = new ArrayList<Score>();
ArrayList<Score> noviceScores = new ArrayList<Score>();
ArrayList<Score> expertScores = new ArrayList<Score>();
ListView listView;
int clicked = 0;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.scoreboard_layout);
myFirebase = new Firebase(myFirebaseUri);
getScoresFromFirebase();
listView = (ListView) findViewById(R.id.scoreboardlist);
RadioButton b1 = (RadioButton)findViewById(R.id.button1);
RadioButton b2 = (RadioButton)findViewById(R.id.button2);
b1.setOnClickListener(this);
b2.setOnClickListener(this);
scores = noviceScores;
listView.setOnItemClickListener(this);
adapter = null;
listView.setAdapter(null);
adapter = new ScoreAdapter(this, R.layout.scoreboard_item, scores);
listView.setAdapter(adapter);

adapter.setNotifyOnChange(true);

}

private DataSnapshot getScoresFromFirebase() {
...
}

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {}

@Override
public void onBackPressed() {
Intent returnIntent = new Intent();
returnIntent.putExtra("resultpage",0);
setResult(Activity.RESULT_OK,returnIntent);
//For the heck of it I decided to null out everything I could
adapter.clear();
adapter = null;
myFirebase = null;
scoreSnapshot = null;
noviceSnapshot = null;
expertSnapshot = null;
difficulty = null;
scores = null;
noviceScores = null;
expertScores = null;
listView = null;
getIntent().setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
finish();
super.finish();
}

@Override
public void onClick(View v) {
if (v.getId() == clicked) return;
clicked = v.getId();
//Show topscores for easy mode
if (v.getId() == R.id.button1) {

scores = noviceScores;
adapter = null;
listView.setAdapter(null);
adapter = new ScoreAdapter(this, R.layout.scoreboard_item, scores);
listView.setAdapter(adapter);
Animation anim = AnimationUtils.loadAnimation(
this, android.R.anim.slide_in_left
);
anim.setDuration(350);
listView.startAnimation(anim);

}
//show topscores for hard mode
if (v.getId() == R.id.button2) {
scores = expertScores;
adapter = null;
listView.setAdapter(null);
adapter = new ScoreAdapter(this, R.layout.scoreboard_item, scores);
listView.setAdapter(adapter);
}
}

}

最佳答案

这里有几件事需要考虑。首先,好好看看 life-cycle 的一项 Activity 。

现在,如果您想让 GC 在 Activity 上运行,请调用 finish() 会做到这一点。所以,现在控件将转到 onDestroy()。 .

根据文档,该 Activity 被销毁并且其所有资源都排队等待垃圾回收,因为对该 Activity 的引用变得不可访问。因此, Activity 使用的所有内存都将在下一个 GC 周期中释放。

要查看是否确实发生了这种情况,请将其添加到 onDestroy() Activity 方法:Runtime.getRuntime().gc() .

现在,要从堆栈中删除之前的 Activity ,我将避免重复这些很好的答案, StackOverflow Post_1 StackOverflow Post_2 .

关于java - Activity 完成运行后无法在 Android 应用程序中释放内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36656638/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com