如何判断我的上下文是否仍然有效?

Max*_*oat 12 java android

我现在正处理一个相当常见的情况 - 通过网络下载一些数据,然后更新视图以显示它.显然,我想在后台进行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

如果您ContextActivity,您可以检查它是否正在完成或已完成该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)


Kur*_*aum 6

你真正想要使用的是AsyncTaskLoader.这些是我在Android API中最喜欢的课程.我一直都在使用它们,它们就像这样解决了问题.您不必担心何时停止下载或类似的事情.所有线程逻辑都会为您处理,包括告诉线程在活动已关闭时停止.只需说出你想在loadInBackground()方法中做什么.请注意,如果您正在为低于3.0的API进行开发,您仍然可以通过Android支持包访问所有加载器.

  • 关于线程的这个陈述实际上是不精确的,除非你告诉他们在你的加载器中这样做,否则它们不会被停止甚至中断.默认情况下真正发生的事情是,任务结果的监听器在重置时只是从加载器中删除.这就是为什么在任务完成后你不会在你的片段或活动中得到回调,但它不会被取消. (2认同)

Mal*_*olm 2

如果使用匿名类,它们将具有对外部类的内部引用,因此不会因为其他引用被清除而突然变得不可访问。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)