在 activity 中使用嵌套的 AsycTask 时,处理程序引用将在 onDestroy 之后保留
When using nested AsycTask in activity will handler reference remain after onDestroy
我有示例代码,它非常简单地完成一些繁重的工作并向处理程序发送消息以更新 UIThread。我关心的是我传递给构造函数的处理程序引用。如果我的 activity 在 asncTask 仍为 运行 时被销毁,处理程序引用是否会为空?
public class SomeActivity extends Activity
{
private static final int UPDATE_BUTTON_TEXT = 1;
private static final SomeActivity me = null;
private static Handler handler = new Handler() {
public void handleMessage(Message msg) {
if (me == null) return;
switch (msg.what) {
case UPDATE_BUTTON_TEXT:
Button btn = (Button) me.findViewById(R.id.someButton);
btn.setText((String) msg.obj);
}
}
};
private View.OnClickListener onClickListener = new View.OnClickListener() {
public void onClick(View view) {
new SomeLongRunningTask().execute();
}
};
private static class SomeLongRunningTask extends AsyncTask<Void, Void, Boolean> {
private Handler handler;
public SomeLongRunningTask(Handler handler) {
this.handler = handler;
}
@Override
protected Boolean doInBackground(Void... voids) {
try {
Thread.sleep(30000); // replace with some background logic
} catch (InterruptedException e) {}
return true;
}
@Override
protected void onPostExecute(Boolean aBoolean) {
//can the handler be null here if activity is destroyed ????
Message msg = handler.obtainMessage(UPDATE_BUTTON_TEXT);
msg.obj = "success"
handler.sendMessage(msg);
}
}
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final Button someButton = (Button) findViewById(R.id.someButton);
someButton.setOnClickListener(onClickListener);
}
@Override
protected void onStart() {
super.onStart();
me = this;
}
@Override
protected void onStop() {
me = null;
super.onStop();
}
}
是的,处理程序的引用将保留在内存中,直到它的引用计数 > 0。
我认为您应该使用 AsyncTask().onProgressUpdate 来更新 UI 上的进度,这正是您想要做的。
编辑
如果你在 onPostExecute 中更新 ui 那么你不需要使用 onProgressUpdate(抱歉)。
只需使用接口作为回调函数,如下所示:
private interface Callback {
void updateUI(String value);
}
private static class SomeLongRunningTask extends AsyncTask<Void, String, Boolean> {
private Callback mCallback;
public SomeLongRunningTask(Callback callback) {
mCallback = callback;
}
@Override
protected void onPostExecute(Boolean aBoolean) {
mCallback.updateUI("success");
}
}
// somewhere else...
Callback callback = new Callback() {
@Override
public void updateUI(String value) {
Button btn = (Button) me.findViewById(R.id.someButton);
btn.setText((String) msg.obj);
}
};
new SomeLongRunningTask(callback).execute();
另外,将处理程序实例作为静态变量似乎也不对。它将持续到 class 被卸载。
通常,每当我编写 AsyncTask
子类时,我都会使用这样的模式:
private WeakReference<Callback> mCallbackRef;
public MyAsyncTask(Callback callback) {
mCallbackRef = new WeakReference<>(callback);
}
@Override
protected void onPostExecute(Boolean aBoolean) {
if (mCallbackRef != null) {
Callback callback = mCallbackRef.get();
if (callback != null) {
callback.updateUI("success");
}
}
}
我有示例代码,它非常简单地完成一些繁重的工作并向处理程序发送消息以更新 UIThread。我关心的是我传递给构造函数的处理程序引用。如果我的 activity 在 asncTask 仍为 运行 时被销毁,处理程序引用是否会为空?
public class SomeActivity extends Activity
{
private static final int UPDATE_BUTTON_TEXT = 1;
private static final SomeActivity me = null;
private static Handler handler = new Handler() {
public void handleMessage(Message msg) {
if (me == null) return;
switch (msg.what) {
case UPDATE_BUTTON_TEXT:
Button btn = (Button) me.findViewById(R.id.someButton);
btn.setText((String) msg.obj);
}
}
};
private View.OnClickListener onClickListener = new View.OnClickListener() {
public void onClick(View view) {
new SomeLongRunningTask().execute();
}
};
private static class SomeLongRunningTask extends AsyncTask<Void, Void, Boolean> {
private Handler handler;
public SomeLongRunningTask(Handler handler) {
this.handler = handler;
}
@Override
protected Boolean doInBackground(Void... voids) {
try {
Thread.sleep(30000); // replace with some background logic
} catch (InterruptedException e) {}
return true;
}
@Override
protected void onPostExecute(Boolean aBoolean) {
//can the handler be null here if activity is destroyed ????
Message msg = handler.obtainMessage(UPDATE_BUTTON_TEXT);
msg.obj = "success"
handler.sendMessage(msg);
}
}
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final Button someButton = (Button) findViewById(R.id.someButton);
someButton.setOnClickListener(onClickListener);
}
@Override
protected void onStart() {
super.onStart();
me = this;
}
@Override
protected void onStop() {
me = null;
super.onStop();
}
}
是的,处理程序的引用将保留在内存中,直到它的引用计数 > 0。
我认为您应该使用 AsyncTask().onProgressUpdate 来更新 UI 上的进度,这正是您想要做的。
编辑
如果你在 onPostExecute 中更新 ui 那么你不需要使用 onProgressUpdate(抱歉)。
只需使用接口作为回调函数,如下所示:
private interface Callback {
void updateUI(String value);
}
private static class SomeLongRunningTask extends AsyncTask<Void, String, Boolean> {
private Callback mCallback;
public SomeLongRunningTask(Callback callback) {
mCallback = callback;
}
@Override
protected void onPostExecute(Boolean aBoolean) {
mCallback.updateUI("success");
}
}
// somewhere else...
Callback callback = new Callback() {
@Override
public void updateUI(String value) {
Button btn = (Button) me.findViewById(R.id.someButton);
btn.setText((String) msg.obj);
}
};
new SomeLongRunningTask(callback).execute();
另外,将处理程序实例作为静态变量似乎也不对。它将持续到 class 被卸载。
通常,每当我编写 AsyncTask
子类时,我都会使用这样的模式:
private WeakReference<Callback> mCallbackRef;
public MyAsyncTask(Callback callback) {
mCallbackRef = new WeakReference<>(callback);
}
@Override
protected void onPostExecute(Boolean aBoolean) {
if (mCallbackRef != null) {
Callback callback = mCallbackRef.get();
if (callback != null) {
callback.updateUI("success");
}
}
}