[英]How to end android service after ASyncTask it spun off completes?
我有一個Downloader Service,它可以下載要從我的數據庫運行的下載列表。
然后,它創建一個ASyncTask,它將在后台線程中運行下載。
一切都很好,但是問題是我目前還沒有辦法告訴服務下載程序已完成。 我必須以某種方式通過ASyncTask的onPostExecute函數(在UIThread上運行)向服務發送消息。
我不能簡單地遠程關閉該服務,因為當ASyncTask完成時,該服務還有一些工作要做。
我已經考慮過從服務中注冊一個偵聽器,並在onPostExecute中對其進行調用,但是我認為這將導致諸如在Task完成之前關閉服務之類的問題或某些線程鎖定問題。
如何從ASyncTask向下載器服務發送消息(如廣播意圖)?
編輯
這是一些讓我感到困惑的代碼。
DownloadService.java(重要位):
public class DownloadService extends Service implements OnProgressListener {
/** The Downloads. */
private List<Download> mDownloads = new ArrayList<Download>(10);
private DownloadTask mDownloadTask;
/** The Intent receiver that handles broadcasts. */
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent) {
DebugLog.i(TAG, "onRecieve" +intent.toString());
handleCommand(intent);
}
};
/* (non-Javadoc)
* @see android.app.Service#onCreate()
*/
@Override
public void onCreate() {
DebugLog.i(TAG, "onCreate");
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
IntentFilter commandFilter = new IntentFilter();
commandFilter.addAction(ACTION_PAUSE_DOWNLOADS);
commandFilter.addAction(ACTION_START_DOWNLOADS);
registerReceiver(mIntentReceiver, commandFilter);
}
/* (non-Javadoc)
* @see android.app.Service#onDestroy()
*/
@Override
public void onDestroy(){
DebugLog.i(TAG, "onDestroy");
//Make sure all downloads are saved and stopped
pauseAllDownloads();
//unregister command receiver
unregisterReceiver(mIntentReceiver);
//cancel notifications
closeNotification();
}
/* (non-Javadoc)
* @see android.app.Service#onStartCommand(android.content.Intent, int, int)
*/a
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
handleCommand(intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
/**
* Handle command sent via intent.
* <strong>Warning, this function shouldn't do any heavy lifting.
* This will be run in UI thread and should spin off ASyncTasks to do work.</strong>
*
* @param intent the intent
*/
private void handleCommand(Intent intent) {
if(intent != null){
String action = intent.getAction();
Uri data = intent.getData();
if(action.equals(ACTION_START_DOWNLOADS))
{
updateDownloads();//Fetch list of downloads to do from database
startDownloads();//run downloads
}else if(action.equals(ACTION_PAUSE_DOWNLOADS)){
pauseAllDownloads();
}
}
}
/**
* Start all downloads currently in list (in order).
*/
private void startDownloads()
{
pauseAllDownloads();//make sure we don't have a download task running
mDownloadTask = new DownloadTask();
mDownloadTask.setOnProgressListener(this);
Download[] downloads = new Download[mDownloads.size()];
for(int i = 0; i<mDownloads.size(); i++)
{
Download d = mDownloads.get(i);
if(d.getStatus() != Download.COMPLETE)
{
downloads[i] = mDownloads.get(i);
}
}
//must be called on UI thread
mDownloadTask.execute(downloads);
}
/**
* Pause downloads.
*/
private void pauseAllDownloads()
{
if(mDownloadTask == null)
{
//Done. Nothing is downloading.
return;
}
//Cancel download task first so that it doesn't start downloading next
if(mDownloadTask.cancel(true))
{
//Task has been canceled. Pause the active download.
Download activeDownload = mDownloadTask.getActiveDownload();
if(activeDownload != null)
{
activeDownload.pause();
}
}else
{
if(mDownloadTask.getStatus() == AsyncTask.Status.FINISHED)
{
DebugLog.w(TAG, "Download Task Already Finished");
}else{
//Task could not be stopped
DebugLog.w(TAG, "Download Task Could Not Be Stopped");
}
}
}
@Override
public void onProgress(Download download) {
//download progress is reported here from DownloadTask
}
}
下載任務:
/**
* The Class DownloadTask.
*/
public class DownloadTask extends AsyncTask<Download, Download, Void> {
/** The On progress listener. */
private OnProgressListener mOnProgressListener;
/**
* The listener interface for receiving onProgress events.
* The class that is interested in processing a onProgress
* event implements this interface and registers it with the component.
*
*/
public static interface OnProgressListener
{
/**
* On progress update.
*
* @param download the download
*/
public void onProgress(Download download);
}
private Download mCurrent;
/**
* Sets the on progress listener.
*
* @param listener the new on progress listener
*/
public void setOnProgressListener(OnProgressListener listener)
{
mOnProgressListener = listener;
}
/**
* Gets the active download.
*
* @return the active download
*/
public Download getActiveDownload()
{
return mCurrent;
}
/* (non-Javadoc)
* @see android.os.AsyncTask#doInBackground(Params[])
*/
@Override
protected Void doInBackground(Download... params) {
int count = params.length;
for (int i = 0; i < count; i++) {
mCurrent = params[i];
if(mCurrent == null)
{
continue;
}
mCurrent.setDownloadProgressListener(new Download.OnDownloadProgressListener() {
@Override
public void onDownloadProgress(Download download, int bytesDownloaded,
int bytesTotal) {
publishProgress(download);
}
});
mCurrent.setOnStatusChangedListener(new Download.OnStatusChangedListener() {
@Override
public void onStatusChanged(Download download, int status) {
publishProgress(download);
}
});
mCurrent.download();
//publishProgress(mCurrent); redundant call
if(this.isCancelled())
break;
}
return null;
}
/* (non-Javadoc)
* @see android.os.AsyncTask#onPostExecute(java.lang.Object)
*/
public void onPostExecute(Void v)
{
//TODO notify completion.
}
/* (non-Javadoc)
* @see android.os.AsyncTask#onProgressUpdate(Progress[])
*/
@Override
protected void onProgressUpdate(Download... progress) {
if(mOnProgressListener != null)
{
for(Download d:progress)
{
mOnProgressListener.onProgress(d);
}
}
}
}
我有一個Downloader Service,它可以下載要從我的數據庫運行的下載列表。 然后,它創建一個ASyncTask,它將在后台線程中運行下載。
考慮到IntentService
已經為您提供了一個后台線程,為什么不使用它呢? 這是一個示例項目,演示使用IntentService
進行下載。
我目前無法告訴服務下載程序已完成。
從onPostExecute()
調用stopSelf()
onPostExecute()
。 更好的是,使用IntentService
,它將在沒有更多工作要做時自動關閉。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.