我想使用WeakReference
方法不使用AsyncTask
泄漏内存。我在线和Stackoverflow上找到了示例,但它们只在onPostExecute
中获得了引用,我不确定如何在所有3种UI方法中正确使用它。
我目前的方法是这样的,但我不知道如果我可以摆脱一些冗余。为什么我不能在构造函数中调用activityReference.get()
,然后只检查每个UI方法中的null?为什么在使用get
之前在线调用WeakReference
?
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 = 1; i < integers[0]; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
publishProgress((i * 100) / integers[0]);
}
return "Finished";
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
MainActivity activity = activityReference.get();
if (activity == null || activity.isFinishing()) {
return;
}
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();
}
}
答案 0 :(得分:1)
您可以在构造函数中初始化它并在所有方法中使用它。
private static class ExampleAsyncTask extends AsyncTask<Integer, Integer, String>
{
private WeakReference<MainActivity> activityReference;
MainActivity activity;
ExampleAsyncTask(MainActivity context)
{
activityReference = new WeakReference<>(context);
activity = activityReference.get();
}
@Override
protected void onPreExecute()
{
super.onPreExecute();
if (activity == null || activity.isFinishing())
{
return;
}
activity.progressBar.setVisibility(View.VISIBLE);
}
@Override
protected String doInBackground(Integer... integers)
{
if (activity == null)
return null;
for (int i = 1; i < integers[0]; i++)
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
publishProgress((i * 100) / integers[0]);
}
return "Finished";
}
@Override
protected void onProgressUpdate(Integer... values)
{
super.onProgressUpdate(values);
if (activity == null || activity.isFinishing())
{
return;
}
activity.progressBar.setProgress(values[0]);
}
@Override
protected void onPostExecute(String s)
{
super.onPostExecute(s);
if (activity == null || activity.isFinishing())
{
return;
}
activity.progressBar.setProgress(0);
activity.progressBar.setVisibility(View.INVISIBLE);
Toast.makeText(activity, s, Toast.LENGTH_SHORT).show();
}
}
答案 1 :(得分:0)
在这里使用弱引用的最正确,最明显的方法是不这样做。相反,您应在活动被销毁时取消任务。这样可以防止内存泄漏,并停止无用的异步计算。
public final class SomeActivity extends Activity {
private AsyncTask<?, ?, ?> runningTask;
private void startTaskPlease() {
if (runningTask != null) runningTask.cancel(true);
runningTask = new ExampleAsyncTask(this);
runningTask.execute();
}
@Override protected void onDestroy() {
super.onDestroy();
if (runningTask != null) runningTask.cancel(true);
}
}
现在,您的AsyncTask#doInBackground
应该是中断友好的,但是UI部分不应该介意弱引用和取消。
public final class ExampleAsyncTask extends AsyncTask<whatever> {
private final SomeActivity activity; // now this is OK! Thanks to cancellation
public ExampleAsyncTask(SomeActivity activity) {
this.activity = activity;
}
}