4

これはどうしたらいいかわからないものです。基本的に、バックグラウンドで通常どおりビジネスを行うASyncTaskクラスがあります。終わったら何かしたいのですが。さて、先に進んで「onPostExecute()を使用してください」と言う前に、落とし穴があります。実行する必要のあるメソッドは、Taskクラスではなく、アクティビティにあります。

私の見方では、2つの選択肢があります。

A:

    CustomTask task = new CustomTask();
    task.execute(passedParams);
            //when(task.execute is finished)
            {
                doX();
            }

とてもシンプルで、アクティビティとアクティビティのgetStatus()を常にポーリングしなくても、タスクがいつ完了したかを確認できるので、この方法で実行できることを願っています。私はこれが幸運になるとは思いませんが、誰かがそれを行う方法を持っているなら、それは素晴らしいことです

B:

アクティビティをパラメータとしてASyncTaskに渡します。これは厄介で、私はそれを使用することに満足していませんが、それとオブジェクト参照を除いて、それが機能するかどうかはわかりません

    CustomTask task = new CustomTask();
    task.execute(passedParams,MyActivity);

次に、タスクonPostExecuteで、MyActivity.doX();を呼び出すことができます。


C:

3番目の方法は、asynctaskをアクティビティ自体のプライベートクラスにすることですが、私は本当にそれを分離したいと思っています。再利用性とそうでないもの– </ p>

これについて何か考えはありますか?

要約すると、task.executeが終了した後にdoX()を実行する必要があります。どんなアイデアでもありがたいです。


D:

わかりました、私はここでロールになっていることを知っています。私は新しい解決策を考え続けています。どこからでも呼び出すことができるクラスメソッドまたは静的メソッド。

public class ProfileSettings extends Activity
{
      public static void doX()
      {
          //Logic...
      }
}

AsyncTaskから

MyActivity.doX();
4

4 に答える 4

6

オプションBは機能するはずであり、時には良いオプションですが、私はこれに匿名クラスを使用することがあります。あなたがあなたの活動からそれを呼ぶとき:

CustomTask task = new CustomTask() {
    @Override
    protected void onPostExecute(Long result) {
        super.onPostExecute(result);
        MyActivity.this.doX();
    }
}.execute();
于 2012-04-11T23:20:19.620 に答える
3

オプションA:

Android APIには、この目的のための組み込み関数がすでに用意されていますAsyncTask.get()

CustomTask task = new CustomTask();
task.execute(passedParams);
Result result = task.get(); // <- Block UI thread and waiting for AsyncTask finish.
this.doX(result);

ご覧のとおり、これはUIスレッドをブロックし、ANR例外を引き起こす可能性があるため、悪い習慣です。これにより、AsyncTaskの利点が実際に犠牲になり、UIスレッドと同期して実行されるようになります。


オプションBおよびC

onPostExecute()メソッドでdoX()メソッドを呼び出すことにより、どちらも正しい方法です。

AsyncTaskは、その名前が示すように、UIスレッドと非同期でバックグラウンドスレッドを実行し、バックグラウンドスレッドが終了すると、UIスレッドでonPostExecuteメソッドが呼び出されます。プロジェクトのビルド時にonPostExecuteメソッドが呼び出されたとき(つまり、doInBackgroundメソッドが終了したとき)を正確に知る方法はありません。これはアプリの実行時に決定されるため、onPostExecuteメソッドがUIスレッドで呼び出されることが保証されていることだけがわかっています。将来のある時点で、言い換えれば、プロジェクトのビルド時にコードを書くとき、doInBackgroundがいつ終了し、コードの実行がonPostExecuteメソッドの外部のUIスレッドにジャンプするかを正確に知ることはできません(Optionなどのコードで待機メカニズムを実装しない限り) A)。したがって、onPostExecuteメソッドの目的は、doInBackgroundメソッドが終了した後にすべてを処理することです。

オプションBとCの違いは、AsyncTaskを内部クラスとして実装するか別のクラスとして実装するかです。これは、StackOverflowで何度も確認され、議論されてきました。ほとんどの人は、再利用可能性などの理由でそれらを分離するのが良いと考えています。私の観点からは、私はそれに同意しません。Javaプログラミング言語には、いくつかの特別なコーディング状況に適合する内部クラス構文を提供する理由があります。OOPの観点からコードのリファクタリングについて話すときは、コードレベルでActivityクラスから内部クラスを単純に取り除くのではなく、問題の抽象化レベルから考えてください。例でわかるように、AsyncTaskをActivityから分離することにより、実際のメリットは得られませんが、問題を解決するためにコードの複雑さが増します(クラス間でアクティビティコンテキスト参照を渡す必要があります)。

本当の問題は、AsyncTask内部クラスの実装をActivityから分離する必要があるかどうかだと思います。より良いOOPコードリファクタリング(再利用性、テスト容易性など)については、このStackOverflowの質問で私の答えをチェックして、ビジネスレイヤーをアプリケーションUIレイヤーから適切に分離する方法を確認してください。

于 2012-04-12T00:33:05.597 に答える
1

私はこの機能をインターフェースで実装することができました:

http://howcanisolve.com/38646/android-java-equivalent-of-ios-block-callbacks

public interface ICallbacks { 
public void onResponse(JSONObject response);
public void onError(VolleyError error);
}

次に、ルーチンコードに、コールバックの新しいインスタンスを配置します。

public static void getPassagesForFirebaseUser(FirebaseUser user,
Context context, ICallbacks events) { 
  //here code and call ICallbacks methods
  if(result){ events.onResponse(response); }
  if(error){ events.onError(err); }
}

最終的には、次のコマンドでメソッドを呼び出すことができます。

getPassagesForFirebaseUser(user, context, new ICallbacks(){
  @Override
  public void onResponse(JSONObject response){
      //Success !!!
  }
  @Override
  public void onError(VolleyError response){
      //Error !!!
  }
});
于 2017-02-27T17:15:01.833 に答える
0

オプションBの方が一般的に安全です。しかし、それでも、注意する必要があります。(クラスだけでなく)自分のインスタンスをに保存する必要があります。また、タスクの実行中にが破棄された場合(ユーザーが[戻る]ボタンを押した場合はどうなりますか?)、タスクがデッドでメソッドを呼び出そうとしないように、これをタスクに通知する必要があります。ActivityASyncTaskActivityActivity

そして、Activity(たとえば、画面の回転後に)復活した場合はActivity、実行中のタスクに新しいものを再アタッチする必要があります。

これらのことは厄介です。

于 2012-04-11T23:15:51.983 に答える