Служба Android расширяет ResultReceiver для IntentService, как реализовать CREATOR?

Мое приложение использует Service, который синхронизируется с внешним оборудованием в фоновом режиме. Поскольку служба работает в основном потоке, она выполняет всю тяжелую работу асинхронно, используя IntentService. Вот минимизированный пример кода для объяснения потока управления:

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) {
          // ???
        }
      };

Если вы хотите: Зачем это нужно? Для чего он будет использоваться?


person Matthias Ronge    schedule 24.11.2015    source источник
comment
Почему? зачем тебе MyIntentService? почему бы не сделать heavy work в HandlerThread внутри MyService? нет необходимости в ResultReceiver, CREATOR и т. д. (если вы посмотрите на IntentService, вы увидите, что внутри нет ничего, кроме HandlerThread)   -  person pskink    schedule 24.11.2015
comment
Почему? Потому что это был первый способ заставить все работать так, как я хочу. Это существующий дизайн рабочего приложения, который является большим, протестированным и производительным, и его нельзя легко изменить. (Вышеприведенный фрагмент предназначен только для демонстрации потока управления.) Платформа Android предоставляет класс IntentService и ResultReceiver. Так что вопрос в том, как их разумно использовать. Я думал, что понял это, см. выше, но новое требование не вписывается в него. Так как же задуман дизайн, если служба хочет загрузить работу в IntentService и получать результаты через ResultsReceiver?   -  person Matthias Ronge    schedule 24.11.2015
comment
попробуйте @SuppressLint("ParcelCreator") class MyResultReceiver extends ResultReceiver {..., но серьезно рассмотрите упрощенную архитектуру (без двух служб)   -  person pskink    schedule 24.11.2015
comment
@psklink, возможно, вы сделаете это ответом?   -  person Matthias Ronge    schedule 25.11.2015


Ответы (1)


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

@SuppressLint("ParcelCreator")
public class MyResultReceiver extends ResultReceiver {
person pskink    schedule 25.11.2015