Android异步任务如何检查活动是否仍在运行

19

我在我的应用程序中使用了 AsyncTasks,以便延迟下载并更新UI。

目前我的AsyncTasks只是简单地更新UI:

protected void onProgressUpdate(String... values) {
        super.onProgressUpdate(values);
        gender.setText(values[0]);
}

我遇到的问题是如何检查呈现性别 TextView 的活动是否仍然可用?如果不可用,我的应用程序将会崩溃。


如果(null==gender && gender.isShown() ),则不确定可以尝试。 - Dheeresh Singh
8个回答

26

你可以在activity的onDestroy()方法中取消你的异步任务(asynctask)。

@Override
protected void onDestroy() {
    asynctask.cancel(true);
    super.onDestroy();
}

在执行更改时,您需要检查您的异步任务是否已被取消(活动已销毁)。

protected void onProgressUpdate(String... values) {
    super.onProgressUpdate(values);
    if(!isCancelled()) {
         gender.setText(values[0]);
    }
}

不错。但是不能保证ondestroy每次都会被调用。(参考下面的链接)。你如何应对这个问题? https://dev59.com/PG855IYBdhLWcg3wQx5L#4449988 - Ajji

9

我遇到了类似的问题——基本上是在用户销毁片段后,在异步任务中出现了NPE。在Stack Overflow上研究了这个问题之后,我采用了以下解决方案:

volatile boolean running;

public void onActivityCreated (Bundle savedInstanceState) {

    super.onActivityCreated(savedInstanceState);

    running=true;
    ...
    }


public void onDestroy() {
    super.onDestroy();

    running=false;
    ...
}

然后,在我的异步代码中,我会定期检查"是否在运行"。我已经进行了压力测试,现在无法"破坏"我的活动。这个方法非常完美,相比于我在SO上看到的一些解决方案更简单。


2
这很简单,而且非常有意义 :) 如果有人在考虑使用volatile关键字,请阅读此文:https://dev59.com/C3VD5IYBdhLWcg3wDXF3#107040 - Mohit Singh

4

尝试

if (!isFinishing()) {
    gender.setText(values[0]);
}

2

检查活动是否正在运行

 if (!isFinishing()) {
  // Do whatever you want to do
}

1

虽然我从未遇到过这种情况,但我会尝试回答你的问题。

在你的情况下,你需要验证传递给 AsyncTaskContext

你可以执行验证操作。

if(null!=mContext)  //Activity still exist!!
{
  gender.setText(values[0]);
}
else //Activity is destroyed
{
   //Take appropriate action!!
}  

如果活动在您到达此语句时被销毁,优势就在于您的Context将自动变为null,这样您就可以处理该场景。


2
这样做不起作用。因为您保留了对活动的硬引用,它将不会被置空。它将变得无效,但异步任务将继续保持对活动的引用。 - uthark

1
作为Android 开发者培训的一部分建议,在任务完成后在需要更新的 UI 元素上保持 WeakReference,并在使用之前检查该引用是否为 null。这不仅有助于检查 UI 是否仍然存在,而且还不会阻止垃圾回收器回收 UI 元素。

1
我会坚持建议你,如果你的Activity没有运行,为什么不取消AsyncTask呢?这将是更好和可行的解决方案。如果你的应用程序正在运行,比如你从一个Activity转移到另一个Activity,那么它不会出现错误(据我所知)。
但是,我会坚持建议在你的Activity没有运行时取消AsyncTask,你可以检查AsyncTask是否正在运行。
if(task != null && task.equals(AsyncTask.Status.RUNNING))
task.cancel(true);

0

不应该

if (gender) {
   gender.setText(values[0]);
}

够了吗?


你是在问(gender==null)吗?即使如此,仅仅这样还不够有时候。 - Dheeresh Singh
1
不,这还不够。活动可能已经完成,但性别仍然可能是非空的,尝试引用它将失败,因为视图/窗口不再处于活动状态。 - Thinkisto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接