16

私のアプリは、バックグラウンドで外部ハードウェアと同期しているServiceに依存しています。このサービスはメインスレッドで動作するため、IntentServiceを使用して非同期で大量の作業を行います。ここでは、制御フローを説明するためのコードのminimalized例です。Androidサービスは、IntentService用のResultReceiverを拡張し、CREATORを実装する方法は?

public class MyService extends Service { 
    private final Handler handler = new Handler(); 

    void someMethodDoesCallBarAsynchronously(){ 
    Intent i = new Intent(this, MyIntentService.class); 
    i.putAction(ACTION_FOO); 
    i.putExtra(EXTRA_RECEIVER, new MyResultReceiver(handler)); 
    startService(toGetScannerStatus); 
    } 

    void receivedFooResult(String bar){ 
    //... 
    } 

    public class MyResultReceiver extends ResultReceiver{ 

    public MyResultReceiver(Handler handler){ 
     super(handler); 
    } 

    @Override 
    protected void onReceiveResult(int resultCode, Bundle resultData) { 
     super.onReceiveResult(resultCode, resultData); 

     switch(resultCode){ 
     case RESULT_CODE_FOO: 
      receivedFooResult(resultData.getString(FOO_RESULT)); 
     break; 
     } 
    } 
    } 
} 

public class MyIntentService extends IntentService { 

    public MyIntentService(){super("MyIntentService");} 

    @Override 
    protected void onHandleIntent(Intent intent) { 
    switch (intent.getAction()) { 
     case ACTION_FOO: 
     ResultReceiver receiver = intent.getParcelableExtra(EXTRA_RECEIVER); 
     Bundle bundle = new Bundle() 
     bundle.putString(FOO_RESULT, foo()); 
     receiver.send(RESULT_CODE_FOO, b); 
     break; 
    } 
} 

、半年や一部の更新後に、AndroidのメーカーはMyResultReceiverがParcelableを実装していますが、CREATORフィールドを提供していないと文句を言い。問題1、MyResultReceiverは内部クラスなので、私はそれを自分のクラスに入れなければなりません。 MyServiceへの参照を保持する必要があるため、staticにできません。それでもまだ簡単です:

public class MyService extends Service { 
    private final Handler handler = new Handler(); 

    void someMethodDoesCallBarAsynchronously(){ 
    Intent i = new Intent(this, MyIntentService.class); 
    i.putAction(ACTION_FOO); 
    i.putExtra(EXTRA_RECEIVER, new MyResultReceiver(this, handler)); 
    startService(toGetScannerStatus); 
    } 

    void receivedFooResult(String bar){ 
    //... 
    } 
} 

public class MyResultReceiver extends ResultReceiver{ 
    private final MyService myService; 

    public MyResultReceiver(MyService s, Handler handler){ 
    super(handler); 
    this.myService = myService; 
    } 

    @Override 
    protected void onReceiveResult(int resultCode, Bundle resultData) { 
    super.onReceiveResult(resultCode, resultData); 

    switch(resultCode){ 
     case RESULT_CODE_FOO: 
     myService.receivedFooResult(resultData.getString(FOO_RESULT)); 
     break; 
    } 
    } 
} 

ここで私はpublic staticフィールドを追加できます。しかし、どのようにCREATORを正しく実装するのですか?

public class MyResultReceiver extends ResultReceiver { 

    public static final Parcelable.Creator<MyResultReceiver> CREATOR 
    = new Parcelable.Creator<MyResultReceiver>() { 
     public MyResultReceiver[] newArray(int size) { 
      return new MyResultReceiver[size]; 
     } 
     public MyResultReceiver createFromParcel(Parcel in) { 
      // ??? 
     } 
     }; 

あなたがしたい場合:なぜこれが必要なのか?それは何のために使われますか?

+0

なぜですか? 'MyIntentService'は何のために必要ですか? 'MyService'の中の' HandlerThread'で '大仕事 'をしないのはなぜですか? 'ResultReceiver'、' CREATOR'などの必要はありません( 'IntentService'を見てみると、' HandlerThread'だけが表示されます) – pskink

+0

なぜですか?これが最初の方法だったので、私はすべてのものが私がそれらにしたい方法で動作するようにしました。これは、大規模で、テストされ、生産的で、簡単に変更できない作業アプリケーションの既存の設計です。 (上のスニペットはコントロールフローを示すためのものです)。AndroidフレームワークはIntentServiceクラスとResultReceiverを提供します。だから問題は、それらを賢明な方法で使用することです。私はそれを理解していると思っていましたが、上記の新しい要件は適合しませんでした。サービスがIntentServiceに作業をロードし、ResultsReceiverを使用して結果を受け取る場合、設計はどのように意図されていますか? – Paramaeleon

+0

'@SuppressLint(" ParcelCreator ")クラスを試してみてください。MyResultReceiverはResultReceiver {...を拡張しますが、単純に2つのサービスを除いて単純化されたアーキテクチャを検討します。 – pskink

答えて

29

あなたの現在のアーキテクチャが複雑すぎ私見です:あなたは簡単にService 1ではなく、それはあなた次第であることを行うことができ、それはあなたの問題に来るとき:あなたはあり得たものとして任意のCREATORを作成する必要はありません糸くずの警告は、ちょうどこのようSuppressLintアノテーションを追加します。

@SuppressLint("ParcelCreator") 
public class MyResultReceiver extends ResultReceiver { 
+0

甘い、ありがとう!! – mur7ay

関連する問題