如何重构我的代码以使用AsyncTask?

时间:2013-01-28 15:10:26

标签: android android-asynctask

我为Android制作了一个最初针对较低版本(2.3)的应用程序。在我的概念验证工作之后,我试图让它在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 个答案:

答案 0 :(得分:2)

您应该可以在您放置评论的地方访问(在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方法......

答案 1 :(得分:0)

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

答案 2 :(得分:0)

您需要对UI控件的引用。将对UI控件的引用传递给ASyncTask时,您将产生问题。 假设以下情形:

  1. 显示活动(活动实例1)
  2. 使用te活动调用异步任务作为参考。
  3. 旋转您的设备(默认情况下,设备轮换会创建新活动) - &gt; (活动实例2)
  4. 同步任务完成后,活动实例1用于显示结果。但是,活动不再存在导致例外。
  5. 结论是ASyncTask不应该用于与网络活动相关的后台任务。

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

答案 3 :(得分:0)

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

enter code herepublic 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("");
}
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);
}

}

}