Meine App basiert auf einer Service
, die im Hintergrund mit externer Hardware synchron bleibt. Da der Dienst auf dem Haupt Thread ausgeführt wird, führt er jede schwere Arbeit asynchron mit einem IntentService aus. Hier ist ein minimalized Beispiel für den Code des Steuerablauf zu erklären:Android Service erweitert ResultReceiver für IntentService, um CREATOR zu implementieren?
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;
}
}
Jetzt, nach einem halben Jahr und einige Updates, Android Studio beklagt, dass MyResultReceiver
implementiert Parcel aber bietet kein CREATOR Feld. Problem 1, MyResultReceiver ist eine innere Klasse, also muss ich sie in eine eigene Klasse setzen. Ich kann es nicht static
machen, weil es einen Verweis auf MyService enthalten muss. Das ist immer noch ganz einfach:
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;
}
}
}
Jetzt kann ich ein öffentliches statisches Feld hinzufügen. Aber wie CREATOR richtig zu implementieren?
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) {
// ???
}
};
Wenn Sie wollen: Warum ist das notwendig? Wofür wird es verwendet?
warum? Wozu brauchst du 'MyIntentService'? Warum nicht eine 'schwere Arbeit' in' HandlerThread' in 'MyService' machen? keine Notwendigkeit für 'ResultReceiver', 'CREATOR' usw. (wenn Sie in' IntentService' schauen, sehen Sie, dass es nur 'HandlerThread' enthält) – pskink
Warum? Weil das der erste Weg war, wie ich alle Dinge so arbeiten ließ, wie ich es wollte. Dies ist das existierende Design der Arbeitsanwendung, das groß, getestet und produktiv ist und nicht einfach geändert werden kann. (Der obige Code dient nur dazu, den Kontrollfluss zu demonstrieren.) Android Framework bietet IntentService-Klasse und ResultReceiver. Die Frage ist also, wie man sie sinnvoll einsetzen kann. Ich dachte, ich hätte es verstanden, siehe oben, aber die neue Anforderung passt nicht hinein. Wie soll das Design also aussehen, wenn ein Service Arbeit in einen IntentService laden will und Ergebnisse durch einen ResultsReceiver erhalten soll? – Paramaeleon
try '@SuppressLint (" ParcelCreator ") Klasse MyResultReceiver erweitert ResultReceiver {...' aber ernsthaft in Betracht ziehen vereinfachte Architektur (ohne zwei Dienste) – pskink