16

Мое приложение полагается на Service, который находится в синхронизации с внешним оборудованием в фоновом режиме. Поскольку сервис работает на главной линии , он выполняет любую тяжелую работу асинхронно с использованием IntentService. Вот minimalized пример кода для объяснения потока управления:Служба Android расширяет ResultReceiver для IntentService, как реализовать 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 Studio жалуется, что MyResultReceiverреализует Parcelable, но не обеспечивает поле CREATOR. Проблема одна, MyResultReceiver - это внутренний класс, поэтому я должен поместить его в собственный класс. Я не могу сделать это static, потому что он должен содержать ссылку на MyService. Это все еще довольно просто:

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; 
    } 
    } 
} 

Теперь я могу добавить публичное статическое поле. Но как правильно использовать 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»? почему бы не сделать «тяжелую работу» в «HandlerThread» внутри 'MyService'? нет необходимости в 'ResultReceiver',' CREATOR' и т. д. (если вы посмотрите на «IntentService», вы увидите, что в нем нет ничего, кроме 'HandlerThread') – pskink

+0

Почему? Поскольку это был первый способ, я получил все, чтобы работать так, как я хочу. Это существующий дизайн рабочего приложения, который является большим, проверенным и производительным, и его нельзя легко изменить. (Выше фрагмента показывается только поток управления.) Ракурс Android обеспечивает класс IntentService и ResultReceiver. Поэтому вопрос заключается в том, как использовать их разумным образом. Я думал, что понял это, см. Выше, но новое требование не подходит. Итак, как дизайн предназначен, если служба хочет загрузить работу в IntentService и получать результаты, хотя они имеют результат? – Paramaeleon

+0

try '@SuppressLint (« ParcelCreator ») класс MyResultReceiver расширяет ResultReceiver {...', но серьезно рассматривает упрощенную архитектуру (без двух сервисов) – pskink

ответ

29

текущая архитектура является слишком сложным IMHO: вы можете легко сделать это в один Service, но это до вас, когда речь идет о вашей проблеме: вам не нужно, чтобы создать какой-либо CREATOR как то, что вы получили это lint warning, просто добавьте аннотацию SuppressLint следующим образом:

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

Сладкий, спасибо! – mur7ay

Смежные вопросы