在AsyncTask中更新UI

时间:2011-05-09 18:31:39

标签: android android-asynctask

嘿 因此,在环顾四周之后似乎共识是通过使用publishProgress()将更新UI以进行更长时间的计算。我似乎很难实现这个,但是当我运行这段代码时,我得到了一个ANR。你能帮我理解为什么吗?

这是我的代码: http://pastebin.com/zQNhkDJ9

http://pastebin.com/HcNZtAsx

2 个答案:

答案 0 :(得分:1)

您的问题可能是您的doInBackground函数只是调用publishProgress。你的所有工作都在publishProgress中完成,它在UI线程上运行,所以你仍然会以这种方式获得ANR。你需要在doInBackground中进行繁重的工作,然后在完成处理后你可以更新UI线程。

答案 1 :(得分:0)

您需要使AsyncTask成为静态内部类,并且它具有一个属性,该属性是对Activity的引用。然后,您可以直接调用Activity上的方法 - 就像UIupdate()一样。

您必须注意的一个问题是,您现在必须非常小心地在任何onPause回调中清除对Activity的引用,否则您将设置循环引用,这将导致内存泄漏。

我的模式是拥有另一个基本的Java对象,通常是Activity中的另一个私有静态类,我称之为“StateHolder”,它是我处理AsyncTask东西的网关,比如初始化它并清除它(设置为NULL)并在轮换更改期间取消正在进行的任何任务。在“onRetainNonConfigurationInstance”的回调中,您可以使用StateHolder作为编组对象。

这是一些粗略的代码:

私有静态类GetConnectionsStatusTask扩展AsyncTask {     私人BoothActivity mActivity;     私人例外mReason;

public GetConnectionsStatusTask(BoothActivity activity) {
    super();
    mActivity = activity;
}

public void setActivity(BoothActivity activity) {
    mActivity = activity;
}

@Override
protected void onPreExecute() {
    if(mActivity != null) {
        mActivity.startProgressBar("Loading", "Please wait");
    }
}

@Override
protected Connections doInBackground(Void... values) {
    try {
        App app = (App)mActivity.getApplication();
        return(app.getApp().userConnections());
    }catch(Exception e) {
        mReason = e;
        return(null);
    }
}

@Override
protected void onPostExecute(Connections status) {
    super.onPostExecute(status);
    if(mActivity != null) {
        mActivity.completedConnectionsStatusCheck(status, mReason);
    }
}       
 }

私有静态类StateHolder {       private GetConnectionsStatusTask connectionsTask;

public void cancelTasks() {
        if (connectionsTask != null) {
            connectionsTask.setActivity(null);
            connectionsTask.cancel(true);
            connectionsTask = null;
        }
}
    public void setActivityForTasks(BoothActivity activity) {
        if (connectionsTask != null) {
            connectionsTask.setActivity(activity);
        }
}

    public void startConnections(BoothActivity activity) {
        if(mIsConnectionsChecking == false) {
            mIsConnectionsChecking = true;
            connectionsTask = new GetConnectionsStatusTask(activity);
            connectionsTask.execute();              
        }
    }
  }

然后在onPause我有类似的代码:

        if(mStateHolder != null) {
            mStateHolder.cancelTasks();
        }

在onCreate中你可以像这样重新充气你的StateHolder:

    Object retained = getLastNonConfigurationInstance();
    if(retained != null && retained instanceof StateHolder) {
        mStateHolder = (StateHolder) retained;
        mStateHolder.setActivityForTasks(this);
     } else {
       mStateHolder = new StateHolder();
     }

这也将使用当前活动重新初始化StateHolder,以便您可以重新建立任何UI小部件,例如进度条更新等。

使用此模式,您实际上可以运行异步任务并通过进度条重新初始化来处理轮换更改。