问题
Tl;dr How to know when an IntentService has finished downloading upon returning to the Activity which listens to its result using a BroadcastReceiver?
I'm moving to implementing data downloading to IntentServices, and notifying when the task has finished using BroadcastReceivers.
I generally start the service in my Activity:
IntentFilter intentFilter = DownloadDataService.startDownloadData(this);
getLocalBroadcastManager().registerReceiver(mBroadcastReceiver, intentFilter);
The part that starts the Service:
/**
* Starts the service and returns an IntentFilter to subscribe a BroadcastReceiver on.
* When the task has finished, a broadcast for returned IntentFilter is sent,
* containing downloaded data.
*/
public static IntentFilter startDownloadData(final Context context) {
Intent intent = new Intent(context, DownloadDataService.class);
intent.setAction(ACTION_DOWNLOAD_DATA);
context.startService(intent);
return new IntentFilter(ACTION_DOWNLOAD_DATA);
}
And of course, onHandleIntent(Intent) (simplified):
@Override
protected void onHandleIntent(final Intent intent){
Data data = downloadData();
Intent intent = new Intent(ACTION_DOWNLOAD_DATA);
intent.putExtra(DATA, data);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
This all works well, and I can keep states in my Activity to know for example after an orientation change whether I was waiting for a download data result:
@Override
public void onResume(){
super.onResume();
if (mState == State.DOWNLOADING) {
Log.v(TAG, "Registering receiver for existing download data");
IntentFilter intentFilter = DownloadDataService.getIntentFilter();
getLocalBroadcastManager().registerReceiver(mBroadcastReceiver, intentFilter);
}
}
Great, now I can also handle orientation changes. Only one problem left:
Activitystarts theDownloadDataService- User moves away from the
Activity DownloadDataServicebroadcasts its done message (which is not received by theActivitydue tounregisterReceiverinonStop())- User moves back into the
Activity Activitystill thinks it's waiting for theDownloadDataService, and does nothing.
How can I compensate for this?
Note that I do not have any persistence like databases for storing the downloaded data. The Activity retrieves the data from the broadcasted Intent.
Note #2: There is this answer to the question of how to know whether a Service is running. Although this might work, it is explicitly stated that that method is for debugging or implementing service management type user interfaces.
回答1:
use sendStickyBroadcast to send a sticky broadcast. This broadcast is held by the system.
回答2:
I wasn't really convinced by using SharedPreferences, static variables and other 'hacky' solutions.
I did find however that you can supply a ResultReceiver - which is parcelable - which you can use to notify your task is finished. It receives a Handler to specify the thread the result is handled on.
The advantage of this, is that you can save the ResultReceiver during onSaveInstanceState. Using some clever tricks you can certainly make this work. I have created an experimental library which facilitates this tactic: https://github.com/nhaarman/Ergo
来源:https://stackoverflow.com/questions/23363027/downloading-data-using-intentservice-lifecycle-changes