web-dev-qa-db-ja.com

Android:AsyncTaskが別のクラスにある場合、AsyncTaskからUIを更新する方法は?

私は内部のクラスが嫌いです。

「短命」のAsyncTaskを起動するメインアクティビティがあります。

AsyncTaskは個別のファイル内であり、メインアクティビティの内部クラスではありません

メインのアクティビティからtextViewを更新する非同期タスクが必要です。

AsyncTaskが内部クラスの場合、onProgressUpdateからTextViewを更新できることを知っています

しかし、外部の独立した非同期タスクからはどうでしょうか?

更新:これは動作しているように見えます:

Acitivtyでは、タスクを呼び出します

backgroundTask = new BackgroundTask(this);
backgroundTask.execute();

コンストラクターで

public BackgroundTask(Activity myContext)
{
    debug = (TextView) myContext.findViewById(R.id.debugText);
}

debugはAsyncTaskのプライベートフィールドでした。

だからonProgressUpdate私はできる

debug.append(text);

あなたのすべての提案をありがとう

36
realtebo

[〜#〜] edit [〜#〜]WeakReferenceを使用するように回答を編集しました


AsyncTaskは常にActivityとは別のクラスですが、アクティビティクラスファイルとは異なるファイルにあると思われるため、アクティビティの内部クラスであることのメリットはありません。アクティビティコンテキストを非同期タスク(つまり、コンストラクター)の引数として渡すだけです

_class MyAsyncTask extends AsyncTask<URL, Integer, Long> {

    WeakReference<Activity> mWeakActivity;

    public MyAsyncTask(Activity activity) {
       mWeakActivity = new WeakReference<Activity>(activity);
    }

 ...
_

必要なときに使用します(doInBackground()中に使用しないでください)。つまり、通常は

_int id = findViewById(...)
_

asyncTaskでは、つまり.

_Activity activity = mWeakActivity.get();
if (activity != null) {
   int id = activity.findViewById(...);
}
_

ActivitydoInBackground()の進行中に削除できることに注意してください(したがって、返される参照はnullになります)が、WeakReferenceを使用することにより、 GCがそれを収集(およびメモリリーク)するのを防ぎ、Activityがなくなると、通常、その状態を更新しようとしても意味がありません(それでも、ロジックに応じて、内部状態の変更やDBの更新などの操作を行い、UIに触れることもできます)スキップする必要があります)。

37
Marcin Orlowski

インターフェイスの使用1)インターフェイスを1つ作成します

public interface OnDataSendToActivity {
    public void sendData(String str);
}

2)アクティビティに実装する

public class MainActivity extends Activity implements OnDataSendToActivity{

     @Override
     protected void onCreate(Bundle savedInstanceState) {
          new AsyncTest(this).execute(new String[]{"AnyData"}); // start your task
     }

     @Override
     public void sendData(String str) {
         // TODO Auto-generated method stub

     }

}

3)AsyncTask(Activity activity){}でコンストラクタを作成します。AsyncTaskファイルにインターフェイスを登録し、以下のようにインターフェイスメソッドを呼び出します。

public class AsyncTest extends AsyncTask<String, Integer, String> {

    OnDataSendToActivity dataSendToActivity;
    public AsyncTest(Activity activity){
        dataSendToActivity = (OnDataSendToActivity)activity;
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        dataSendToActivity.sendData(result);
    }

}

ここで、OnPostExecuteはAsyncTaskによって実行されたすべてのタスクの後に呼び出し、doInBackground(){return "";}によって返されるパラメーターとして「結果」を取得します。

While "dataSendToActivity.sendData(result);"アクティビティのオーバーライドされたメソッド「public void sendData(String str){}」を呼び出します。

覚えておくべきエッジケース:thisを渡すようにしてください。つまり、現在のアクティビティのコンテキストをAsyncTaskに渡し、アクティビティの別のインスタンスを作成しないでください。そうしないと、Activity新しいものが作成されます。

21
Ams

テキストビューを更新するためにコンテキストを渡すアクティビティクラスで静的関数を作成し、AsynkTaskクラスでこの関数を呼び出して更新します。

Activityクラス内:public static void updateTextView(){

//ここにコード}

AynckTaskクラスでこの関数を呼び出します。

4
pyus13

コンテキスト(アクティビティなど)をコンストラクターでAsyncTaskに渡し、onSuccessまたはonProgressUpdateでコンテキストに必要なものを呼び出します。

3
Manfred Moser

この種のシナリオのために、AsyncTaskの小さな拡張機能を作成しました。 AsyncTaskを別のクラスに保持することができますが、タスクの完了への便利なアクセスも提供します。

public abstract class ListenableAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result>{

    @Override
    protected final void onPostExecute(Result result) {
        notifyListenerOnPostExecute(result);
    }

    private AsyncTaskListener<Result> mListener;
    public interface AsyncTaskListener<Result>{
        public void onPostExecute(Result result);
    }
    public void listenWith(AsyncTaskListener<Result> l){
        mListener = l;
    }
    private void notifyListenerOnPostExecute(Result result){
        if(mListener != null)
            mListener.onPostExecute(result);
    }

}

したがって、最初にAsyncTaskの代わりにListenableAsyncTaskを拡張します。次に、UIコードで具体的なインスタンスを作成し、listenWith(...)を設定します。

3
newbyca

質問は既に回答されていますが、どうすればそれを行うべきかを投稿しています。

メインアクティビティクラス

  public class MainActivity extends Activity implements OnClickListener
    {

        TextView Ctemp;

        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Ctemp = (TextView) findViewById(R.id.Ctemp);
            doConv = (Button) findViewById(R.id.doConv);
            doConv.setOnClickListener(this);
        }

        @Override
        public void onClick(View arg0) // The conversion to do
        {
            new asyncConvert(this).execute();
        }
    }

現在非同期クラスにあります

public class asyncConvert extends AsyncTask<Void, Void, String>
{
    SoapPrimitive response = null;
    Context context;

    public asyncConvert(Context callerclass)
    {
        contextGUI = callerclass;
    }
.
.
.
.
protected void onPostExecute(String result)
    {
        ((MainActivity) contextGUI).Ctemp.setText(result); // changing TextView
    }
}
2
Sujal Mandal
    /**
     * Background Async Task to Load all product by making HTTP Request
     * */
     public  static class updateTExtviewAsyncTask extends AsyncTask<String, String, String> {

        Context context;
        ProgressDialog pDialog;
        String id, name;

        String state_id;

        //--- Constructor for getting network id from asking method

        public  updateTExtviewAsyncTask(Context context,String id,String city) 
        {
            context   = context;
            state_id  = id;
            city_name = city;
        }       
        /* *
         * Before starting background thread Show Progress Dialog
         * */
        @Override
        protected void onPreExecute() 
        {
            super.onPreExecute();
            pDialog = ProgressDialog.show(context, "","Please wait...", true, true);
            pDialog.show();

        }

        /**
         * getting All products from url
         * */
        protected String doInBackground(String... args) 
        {
            return null;
        }

        /**
         * After completing background task Dismiss the progress dialog
         * **/
            protected void onPostExecute(String file_url)  {

                     YourClass.UpdateTextViewData("Textview data");
        }
    }

//このコードをアクティビティクラス内に配置し、textview staticの更新も宣言します

    public static void  UpdateTextViewData(String tvData) 
{
   tv.setText(tvData);
}
1
Lucky Rana