我想在我的Async任务中使用一个Weak引用来不泄漏内存。通过我可以看到的日志语句,如果我把活动留在后退按钮上,我从get
方法返回的活动引用确实为空。但是,当我旋转设备时,我得到了一个工作引用,这意味着我泄漏了内存。知道为什么会发生这种情况吗?
更新:在旋转设备并打开其他应用程序后,我一离开活动,它就开始显示null。是不是因为我的活动很简单,系统就没有必要进行清理?
public class MainActivity extends AppCompatActivity {
private ProgressBar progressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = findViewById(R.id.progress_bar);
}
public void startAsyncTask(View v) {
ExampleAsyncTask exampleAsyncTask = new ExampleAsyncTask(this);
exampleAsyncTask.execute(210);
}
private static class ExampleAsyncTask extends AsyncTask<Integer, Integer, String> {
private WeakReference<MainActivity> activityReference;
ExampleAsyncTask(MainActivity context) {
activityReference = new WeakReference<>(context);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
MainActivity activity = activityReference.get();
if (activity == null || activity.isFinishing()) {
return;
}
activity.progressBar.setVisibility(View.VISIBLE);
}
@Override
protected String doInBackground(Integer... integers) {
for (int i = 0; i < integers[0]; i++) {
publishProgress((i * 100) / integers[0]);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "Finished";
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
MainActivity activity = activityReference.get();
if (activity == null || activity.isFinishing()) {
Log.i("activity", "activity = null");
return;
} else
Log.i("activity", "activity not null");
activity.progressBar.setProgress(values[0]);
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
MainActivity activity = activityReference.get();
if (activity == null || activity.isFinishing()) {
return;
}
activity.progressBar.setProgress(0);
activity.progressBar.setVisibility(View.INVISIBLE);
Toast.makeText(activity, s, Toast.LENGTH_SHORT).show();
}
}
}
当活动被销毁时,活动对象应该可以进行垃圾收集。这意味着,接下来的一些GC事件将释放活动持有的内存。
您正在做一个假设,即GC必须在执行方向更改后立即发生,这是不正确的。WeakReference
确保的是,当GC下次试图清除内存时,它不会成为保存对象的理由。活动对象迟早会被GC清除,但它不会像您预期的那样立即发生。
你可以使用系统。gc()
将启动同步gc事件,但不建议在正常情况下依赖此方法。
System.gc();
MainActivity activity = activityReference.get();
// now `activity` should be null
在一些请求中,我们会做一些日志的推送、用户数据的统计等和返回给终端数据无关的操作。而这些操作,即使你用异步非阻塞的方式,在终端看来,也是会影响速度的。这个和我们的原则:终端请求,需要用最快的速度返回给终端,是冲突的。 这时候,最理想的是,获取完给终端返回的数据后,就断开连接,后面的日志和统计等动作,在断开连接后,后台继续完成即可。 怎么做到呢?我们先看其中的一种方法: local response
我正在运行以下代码,试图删除不存在的“尖叫”: 控制台日志显示以下内容: 我希望函数在404响应时停止执行,但似乎块都是在block之外执行的。为什么会这样?
我在一个活动中有一个列表视图,在自定义适配器中有一个信息图标。当用户点击该信息按钮时,下一个活动将打开,当用户点击更新按钮时,在下一个活动中标记出勤率后,第二个活动应该完成,第一个活动列表视图应该更新。 我成功地做了什么:我已经成功地标记了出席情况并更改了listview的颜色,但我在关闭第二个活动并重新启动第一个活动后这样做了。通过这种方式,由于再次开始活动,listview会得到更新。 我无法
在我的应用程序中,当我从后台回来时,我的活动会自动接近,并且它总是显示以前的活动。示例:我用活动A启动应用程序 }
下面是一个简单对话框的示例代码: 下面是一些活动代码: 代码与您所看到的引用大致相同。问题是,一旦您改变了方向,当显示对话框时,它就停止了预期的工作-->由于活动生命周期的原因,活动和对话框都被重新构建,并且对话框现在没有对重新构建的新活动的正确引用。 致以最诚挚的问候