1

もともと下位バージョン(2.3)を対象としたAndroid用のアプリケーションを作成しました。概念実証を機能させた後、Android4で機能させようとしました。そのときに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

postExecuteコメントを入れた場所(メソッド内)でUIにアクセスできる必要があります

さらに、コードの見栄えを良くするために、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

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 に答える
0

次のようにrefreshメソッドで内部クラスを作成します

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 に答える