我现在正处理一个相当常见的情况 - 通过网络下载一些数据,然后更新视图以显示它.显然,我想在后台进行Web下载,然后在主UI线程上更新视图.现在看看我的代码,我有点担心我的Activity和它的UI元素在我更新它们之前被杀掉了.这是我心中的本质:
Thread update = new Thread() {
public void run() {
final Data newData = requestData();
if (newData != null) {
post(new Runnable() {
public void run() {
Toast.makeText(MyClass.this, "I'll do things here that depend on my context and views being valid", Toast.LENGTH_SHORT).show();
}
});
}
}
};
update.start();
Run Code Online (Sandbox Code Playgroud)
似乎有可能在我下载数据时,活动可能会被破坏.那么会发生什么?我的线程会继续执行吗?我最终会尝试访问死对象吗?
通常我是通过AsycTask来做的,但这次工作看起来很简单,只是内联线程启动线程的东西.我会通过使用AsyncTask来改善目标吗?
Jes*_*erB 22
如果您Context是Activity,您可以检查它是否正在完成或已完成该isFinishing()方法:
if ( context instanceof Activity ) {
Activity activity = (Activity)context;
if ( activity.isFinishing() ) {
return;
}
}
Toast.makeText(context, "I'll do things here that depend on my context and views being valid", Toast.LENGTH_SHORT).show();
Run Code Online (Sandbox Code Playgroud)
你真正想要使用的是AsyncTaskLoader.这些是我在Android API中最喜欢的课程.我一直都在使用它们,它们就像这样解决了问题.您不必担心何时停止下载或类似的事情.所有线程逻辑都会为您处理,包括告诉线程在活动已关闭时停止.只需说出你想在loadInBackground()方法中做什么.请注意,如果您正在为低于3.0的API进行开发,您仍然可以通过Android支持包访问所有加载器.
如果使用匿名类,它们将具有对外部类的内部引用,因此不会因为其他引用被清除而突然变得不可访问。AsyncTask实际上并没有改变任何东西,它使用类似的机制来通知结果。
您可以使用loader,它们被设计为与活动生命周期同步。它们仅从 Android 3.0 开始可用,但您可以使用支持包在任何 1.6 或更高版本的设备上使用它们。
还有一个更简单的解决方案,您可以只使用一个布尔字段来指示活动是否已经消失。您应该设置此字段onPause()(或者每当您认为不再需要通知时)并在显示 toast 时检查它。您甚至不必使用同步,因为该字段仅限于主线程,因此绝对安全。顺便说一句,如果您在 in 之外的其他位置更改此字段onDestroy(),请不要忘记添加一条语句,将您的字段重置回对应的方法中。
public class MyActivity extends Activity {
private boolean activityDestroyed = false;
@Override
protected void onDestroy() {
activityDestroyed = true;
}
private void updateData() {
new Thread() {
@Override
public void run() {
final Data newData = requestData();
if (newData == null) return;
runOnUiThread(new Runnable() {
public void run() {
if (activityDestroyed) return;
Toast.makeText(MyActivity.this, "Blah",
Toast.LENGTH_SHORT).show();
}
});
}
}.start();
}
}
Run Code Online (Sandbox Code Playgroud)