該解決方案是這樣的:
所有類產卵AsyncTask
s表示可能會相互干擾獲得自己Executor
像這樣的(做出精心爲你喜歡使用線程池等):
private Executor serviceExecutor = new Executor() {
public void execute(Runnable command) {
new Thread(command).start();
}
};
正如指出的VinceFR可以通過調用它像這樣運行在一個給定的Executor
的AsyncTask
(其中是,你會經常傳遞給任務的參數):
task.executeOnExecutor(serviceExecutor, payload);
但是,這會打破向後兼容薑餅和更早。另外,如果你想支持Honeycomb,你需要確保這個調用發生在UI線程上。果凍豆將自動照顧這一點。
現在更棘手的部分:保持服務運行在自己的線程上。 Android中的許多事情似乎比它需要的更困難(或者我在這裏缺少一些信息)。您不能使用IntentService
,因爲在第一次AsyncTask
接管時會自動關閉,並且讓onHandleIntent
回調完成。
您需要設置在服務自己的線程和事件循環:
public class AsyncService extends Service {
private static final String TAG = AsyncService.class.getSimpleName();
private class LooperThread extends Thread {
public Handler threadHandler = null;
public void run() {
Looper.prepare();
this.threadHandler = new Handler();
Looper.loop();
}
}
private LooperThread serviceThread = null;
private Handler serviceThreadHandler = null;
@Override
// This happens on the UI thread
public void onCreate() {
super.onCreate();
}
@Override
// This happens on the UI thread
public int onStartCommand(Intent intent, int flags, int startId) {
this.serviceThread = new LooperThread();
this.serviceThread.start();
while(this.serviceThread.threadHandler == null) {
Log.d(TAG, "Waiting for service thread to start...");
}
this.serviceThreadHandler = this.serviceThread.threadHandler;
this.serviceThreadHandler.post(new Runnable() {
@Override
public void run() {
doTheFirstThingOnTheServiceThread();
}
});
return Service.START_STICKY;
}
// doTheFirstThingOnTheServiceThread
}
不,你需要確保每個時間AsyncTask
返回到UI線程,你在你的服務線程結束,而不是:
// This happens on the serviceThread
private void doTheFirstThingOnTheServiceThread() {
// do some stuff
// here we can reuse a class that performs some work on an AsyncTask
ExistingClassWithAsyncOperation someUsefullObject = new ExistingClassWithAsyncOperation();
// the existing class performs some work on an AsyncTask and reports back via an observer interface
someUsefullObject.setOnOperationCompleteListener(new OnOperationCompleteListener() {
@Override
// This happens on the UI thread (due to an ``AsyncTask`` in someUsefullObject ending)
public void onOperationComplete() {
serviceThreadHandler.post(new Runnable() {
@Override
public void run() {
doTheSecondThingOnTheServiceThread();
}
});
}
}
someUsefulObject.performOperation();
}
// This happens on the serviceThread
private void doTheSecondThingOnTheServiceThread() {
// continue working on the serviceThread
}
所以,這對我的作品。我很高興看到這個更簡單的解決方案。請注意,該解決方案需要服務知道將由UI線程上的ExistingClassWithAsyncOperation
回調。我不特別喜歡這種依賴性,但現在不知道如何做得更好。但是,我不必重寫很多使用AsyncTask
執行異步操作的現有類。
https://github.com/octo-online/robospice。替代asynctask – Raghunandan 2013-03-15 08:15:10
謝謝,我在文檔中挖了一點點。 RoboSplice似乎也會在UI線程中回調您。此外,該框架不會允許輕鬆遷移。但是,對於任何新代碼來說,這似乎是一個非常好的方法。 – Chris 2013-03-15 08:29:36
供參考:如果您使用'executeOnExecutor'而不是'execute'(函數doc [here] [1]),任何實例的doInBackground將不會共享相同的線程 [1]:http://developer.android.com /reference/android/os/AsyncTask.html#executeOnExeoror%28java.util.concurrent.Executor,%20Params...%29 – VinceFR 2013-03-15 08:47:21