1

我为最初针对较低版本(2.3)的Android制作了一个应用程序。在我的概念验证工作之后,我试图让它在 Android 4 上工作。那时我得到了 NetworkOnMainThread 异常。

经过一番研究,我很快找到了 AsyncTask,听起来很棒。问题是,我很难绕开它。例如,这是我的原始代码:

public void Refresh(Context c)
{
    SummaryModel model = MobileController.FetchSummary(c);

    TextView txtCurrentWeight = (TextView)findViewById(R.id.txtCurrentWeight);
    TextView txtWeightChange = (TextView)findViewById(R.id.txtWeightChange);
    TextView txtAvgPerWeek = (TextView)findViewById(R.id.txtAvgPerWeek);

    if(model.ErrorMessage == "")
    {
        txtCurrentWeight.setText(model.CurrentWeight);
        txtWeightChange.setText(model.WeightChange);
        txtAvgPerWeek.setText(model.Average);
    }
    else
    {
        Toast.makeText(c, model.ErrorMessage, Toast.LENGTH_LONG).show();

        txtCurrentWeight.setText("");
        txtWeightChange.setText("");
        txtAvgPerWeek.setText("");
    }
}

我创建了一个这样的 AsychTask:

public class WebMethodTask extends AsyncTask<Object, Integer, Object> {
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
    }

    @Override
    protected void onPostExecute(Object result) {
        super.onPostExecute(result);

        SummaryModel model = (SummaryModel)result;
        // Can't seem to access UI items here??

    }

    @Override
    protected Object doInBackground(Object... params) {

        Context c = (Context)params[0];
        return MobileController.FetchSummary(c);
    }
}

如何从 onPostExecute 方法访问 UI 项?或者,我对如何使用 AsyncTask 有错误的想法?

谢谢!

4

4 回答 4

2

您应该能够访问您放置评论的UI(在postExecute方法中)

此外,我建议对 AsyncTask 使用更专业的类,以便您的代码看起来更好:

public class WebMethodTask extends AsyncTask<Object, Integer, SummaryModel> {

    private Activity source;
    public WebMethodTask(Activity activity) {
        this.source=activity;
        }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
    }

    @Override
    protected void onPostExecute(SummaryModel model) {
        super.onPostExecute(model );

        TextView txtCurrentWeight = (TextView)source.findViewById(R.id.txtCurrentWeight);
        TextView txtWeightChange = (TextView)source.findViewById(R.id.txtWeightChange);
        TextView txtAvgPerWeek = (TextView)source.findViewById(R.id.txtAvgPerWeek);

        if(model.ErrorMessage.length()==0)
        {
            txtCurrentWeight.setText(model.CurrentWeight);
            txtWeightChange.setText(model.WeightChange);
            txtAvgPerWeek.setText(model.Average);
        }
        else
        {
            Toast.makeText(c, model.ErrorMessage, Toast.LENGTH_LONG).show();

            txtCurrentWeight.setText("");
            txtWeightChange.setText("");
            txtAvgPerWeek.setText("");
        }

    }

    @Override
    protected SummaryModel doInBackground(Context ... params) {
        Context c = params[0];
        return MobileController.FetchSummary(c);
    }
}

编辑:添加了对您的活动的引用,以考虑您的最后评论。


但是,如果您的 acynctask 可能很长,那么保留对​​活动的引用可能不是一个好主意。

创建一个将接受某些displayModel(CummaryModel)方法的侦听器类将是一个更好的设计,如果活动同时没有暂停/停止,其职责是调用 setText 方法......

于 2013-01-28T15:19:56.173 回答
0

在刷新方法中创建一个内部类

enter code herepublic void Refresh(Context c)

{ SummaryModel 模型 = MobileController.FetchSummary(c);

TextView txtCurrentWeight = (TextView)findViewById(R.id.txtCurrentWeight);
TextView txtWeightChange = (TextView)findViewById(R.id.txtWeightChange);
TextView txtAvgPerWeek = (TextView)findViewById(R.id.txtAvgPerWeek);

if(model.ErrorMessage == "")
{
    txtCurrentWeight.setText(model.CurrentWeight);
    txtWeightChange.setText(model.WeightChange);
    txtAvgPerWeek.setText(model.Average);
}
else
{
    Toast.makeText(c, model.ErrorMessage, Toast.LENGTH_LONG).show();

    txtCurrentWeight.setText("");
    txtWeightChange.setText("");
    txtAvgPerWeek.setText("");
}
class WebMethodTask extends AsyncTask<Object, Integer, Object> {
@Override
protected void onPreExecute() {
    super.onPreExecute();
}

@Override
protected void onProgressUpdate(Integer... values) {
    super.onProgressUpdate(values);
}

@Override
protected void onPostExecute(Object result) {
    super.onPostExecute(result);

    SummaryModel model = (SummaryModel)result;
    // Can't seem to access UI items here??

}

@Override
protected Object doInBackground(Object... params) {

    Context c = (Context)params[0];
    return MobileController.FetchSummary(c);
}

}

}

于 2013-01-28T15:55:54.387 回答
0

使用 WebMethodTask#onPostExecute 方法中加载的模型数据填充 ui 项。

于 2013-01-28T15:13:07.097 回答
0

您需要参考您的 UI 控件。将 UI 控件的引用传递给 ASyncTask 时,您将产生问题。假设以下场景:

  1. 显示活动(活动实例 1)
  2. 以 te 活动作为参考调用异步任务。
  3. 旋转您的设备(默认情况下,设备旋转将创建一个新活动)->(活动实例 2)
  4. 当同步任务完成时,活动实例 1 用于显示结果。但是,该活动不再存在,导致异常。

结论是 ASyncTask 不应该用于网络活动相关的后台任务。

幸运的是,有一个解决方案:RoboSpice。RoboSpice 使用了另一种方法。查看https://github.com/octo-online/robospice/wiki/Understand-the-basics-of-RoboSpice-in-30-seconds以获得很好的解释。更多信息:https ://github.com/octo-online/robospice

于 2013-01-28T15:35:18.630 回答