Есть ли способ прервать AsyncTaskLoader
's loadInBackground()
нить, когда я звоню cancelLoad()
? Я считаю, что AsyncTask.cancel()
делает это, но переменные задачи являются частными и недоступны.Как прервать фоновый поток AsyncTaskLoader?
ответ
Использование stopLoading()
или abandon()
или reset()
для этого
Статья: https://plus.google.com/117981280628062796190/posts/8b9RmQvxudb
Я проверил доступные методы, и, кажется, никто на самом деле не прерывает поток, который работает в фоновом режиме.
Рассматривая код, кажется, что AsyncTask используется под капотом. Я пробовал найти «дыру», которую я мог бы использовать для прерывания asyncTask, но я не мог найти (если только вы не прекрасны с отражением). Я думаю, вы могли бы создать свой собственный загрузчик, который будет иметь эту функциональность.
Я думаю, вы можете изменить код по своему усмотрению. Может быть, добавьте «forceCancel», который будет проверять значение asyncTask, и если он не является нулевым, назовите «cancel (true)» на нем. Вот код, который я посмотрел на:
AsyncTaskLoader.java
package android.support.v4.content;
import android.content.Context;
import android.os.Handler;
import android.os.SystemClock;
import android.support.v4.util.TimeUtils;
import android.util.Log;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.concurrent.CountDownLatch;
/**
* Static library support version of the framework's {@link android.content.AsyncTaskLoader}.
* Used to write apps that run on platforms prior to Android 3.0. When running
* on Android 3.0 or above, this implementation is still used; it does not try
* to switch to the framework's implementation. See the framework SDK
* documentation for a class overview.
*/
public abstract class AsyncTaskLoader<D> extends Loader<D> {
static final String TAG = "AsyncTaskLoader";
static final boolean DEBUG = false;
final class LoadTask extends ModernAsyncTask<Void, Void, D> implements Runnable {
D result;
boolean waiting;
private CountDownLatch done = new CountDownLatch(1);
/* Runs on a worker thread */
@Override
protected D doInBackground(Void... params) {
if (DEBUG) Log.v(TAG, this + " >>> doInBackground");
result = AsyncTaskLoader.this.onLoadInBackground();
if (DEBUG) Log.v(TAG, this + " <<< doInBackground");
return result;
}
/* Runs on the UI thread */
@Override
protected void onPostExecute(D data) {
if (DEBUG) Log.v(TAG, this + " onPostExecute");
try {
AsyncTaskLoader.this.dispatchOnLoadComplete(this, data);
} finally {
done.countDown();
}
}
@Override
protected void onCancelled() {
if (DEBUG) Log.v(TAG, this + " onCancelled");
try {
AsyncTaskLoader.this.dispatchOnCancelled(this, result);
} finally {
done.countDown();
}
}
@Override
public void run() {
waiting = false;
AsyncTaskLoader.this.executePendingTask();
}
}
volatile LoadTask mTask;
volatile LoadTask mCancellingTask;
long mUpdateThrottle;
long mLastLoadCompleteTime = -10000;
Handler mHandler;
public AsyncTaskLoader(Context context) {
super(context);
}
/**
* Set amount to throttle updates by. This is the minimum time from
* when the last {@link #onLoadInBackground()} call has completed until
* a new load is scheduled.
*
* @param delayMS Amount of delay, in milliseconds.
*/
public void setUpdateThrottle(long delayMS) {
mUpdateThrottle = delayMS;
if (delayMS != 0) {
mHandler = new Handler();
}
}
@Override
protected void onForceLoad() {
super.onForceLoad();
cancelLoad();
mTask = new LoadTask();
if (DEBUG) Log.v(TAG, "Preparing load: mTask=" + mTask);
executePendingTask();
}
/**
* Attempt to cancel the current load task. See {@link android.os.AsyncTask#cancel(boolean)}
* for more info. Must be called on the main thread of the process.
*
* <p>Cancelling is not an immediate operation, since the load is performed
* in a background thread. If there is currently a load in progress, this
* method requests that the load be cancelled, and notes this is the case;
* once the background thread has completed its work its remaining state
* will be cleared. If another load request comes in during this time,
* it will be held until the cancelled load is complete.
*
* @return Returns <tt>false</tt> if the task could not be cancelled,
* typically because it has already completed normally, or
* because {@link #startLoading()} hasn't been called; returns
* <tt>true</tt> otherwise.
*/
public boolean cancelLoad() {
if (DEBUG) Log.v(TAG, "cancelLoad: mTask=" + mTask);
if (mTask != null) {
if (mCancellingTask != null) {
// There was a pending task already waiting for a previous
// one being canceled; just drop it.
if (DEBUG) Log.v(TAG,
"cancelLoad: still waiting for cancelled task; dropping next");
if (mTask.waiting) {
mTask.waiting = false;
mHandler.removeCallbacks(mTask);
}
mTask = null;
return false;
} else if (mTask.waiting) {
// There is a task, but it is waiting for the time it should
// execute. We can just toss it.
if (DEBUG) Log.v(TAG, "cancelLoad: task is waiting, dropping it");
mTask.waiting = false;
mHandler.removeCallbacks(mTask);
mTask = null;
return false;
} else {
boolean cancelled = mTask.cancel(false);
if (DEBUG) Log.v(TAG, "cancelLoad: cancelled=" + cancelled);
if (cancelled) {
mCancellingTask = mTask;
}
mTask = null;
return cancelled;
}
}
return false;
}
/**
* Called if the task was canceled before it was completed. Gives the class a chance
* to properly dispose of the result.
*/
public void onCanceled(D data) {
}
void executePendingTask() {
if (mCancellingTask == null && mTask != null) {
if (mTask.waiting) {
mTask.waiting = false;
mHandler.removeCallbacks(mTask);
}
if (mUpdateThrottle > 0) {
long now = SystemClock.uptimeMillis();
if (now < (mLastLoadCompleteTime+mUpdateThrottle)) {
// Not yet time to do another load.
if (DEBUG) Log.v(TAG, "Waiting until "
+ (mLastLoadCompleteTime+mUpdateThrottle)
+ " to execute: " + mTask);
mTask.waiting = true;
mHandler.postAtTime(mTask, mLastLoadCompleteTime+mUpdateThrottle);
return;
}
}
if (DEBUG) Log.v(TAG, "Executing: " + mTask);
mTask.executeOnExecutor(ModernAsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
}
}
void dispatchOnCancelled(LoadTask task, D data) {
onCanceled(data);
if (mCancellingTask == task) {
if (DEBUG) Log.v(TAG, "Cancelled task is now canceled!");
rollbackContentChanged();
mLastLoadCompleteTime = SystemClock.uptimeMillis();
mCancellingTask = null;
executePendingTask();
}
}
void dispatchOnLoadComplete(LoadTask task, D data) {
if (mTask != task) {
if (DEBUG) Log.v(TAG, "Load complete of old task, trying to cancel");
dispatchOnCancelled(task, data);
} else {
if (isAbandoned()) {
// This cursor has been abandoned; just cancel the new data.
onCanceled(data);
} else {
commitContentChanged();
mLastLoadCompleteTime = SystemClock.uptimeMillis();
mTask = null;
if (DEBUG) Log.v(TAG, "Delivering result");
deliverResult(data);
}
}
}
/**
*/
public abstract D loadInBackground();
/**
* Called on a worker thread to perform the actual load. Implementations should not deliver the
* result directly, but should return them from this method, which will eventually end up
* calling {@link #deliverResult} on the UI thread. If implementations need to process
* the results on the UI thread they may override {@link #deliverResult} and do so
* there.
*
* @return Implementations must return the result of their load operation.
*/
protected D onLoadInBackground() {
return loadInBackground();
}
/**
* Locks the current thread until the loader completes the current load
* operation. Returns immediately if there is no load operation running.
* Should not be called from the UI thread: calling it from the UI
* thread would cause a deadlock.
* <p>
* Use for testing only. <b>Never</b> call this from a UI thread.
*
* @hide
*/
public void waitForLoader() {
LoadTask task = mTask;
if (task != null) {
try {
task.done.await();
} catch (InterruptedException e) {
// Ignore
}
}
}
@Override
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
super.dump(prefix, fd, writer, args);
if (mTask != null) {
writer.print(prefix); writer.print("mTask="); writer.print(mTask);
writer.print(" waiting="); writer.println(mTask.waiting);
}
if (mCancellingTask != null) {
writer.print(prefix); writer.print("mCancellingTask="); writer.print(mCancellingTask);
writer.print(" waiting="); writer.println(mCancellingTask.waiting);
}
if (mUpdateThrottle != 0) {
writer.print(prefix); writer.print("mUpdateThrottle=");
TimeUtils.formatDuration(mUpdateThrottle, writer);
writer.print(" mLastLoadCompleteTime=");
TimeUtils.formatDuration(mLastLoadCompleteTime,
SystemClock.uptimeMillis(), writer);
writer.println();
}
}
}
Это относительно просто добавить эту функциональность, это Gist его:
public abstract class InterruptibleAsyncTaskLoader<D> extends AsyncTaskLoader<D> {
private volatile Thread thread;
public InterruptibleAsyncTaskLoader(Context context) {
super(context);
}
public boolean isLoadInBackgroundRunning() {
return thread != null;
}
@Override
public void cancelLoadInBackground() {
Thread t = thread;
if (t != null) t.interrupt();
}
@Override
public final D loadInBackground() {
try {
thread = Thread.currentThread();
return doLoadInBackground();
} catch (InterruptedException e) {
OperationCanceledException oce = new OperationCanceledException(e.toString());
oce.initCause(e);
throw oce;
} finally {
Thread.interrupted();
thread = null;
}
}
public abstract D doLoadInBackground() throws InterruptedException;
}
- 1. Как прервать фоновый поток, блокирующий IO?
- 2. Как прервать или остановить фоновый процесс?
- 3. Как прервать поток исполнителей
- 4. Как создать фоновый поток
- 5. Как создать фоновый поток?
- 6. Как прервать связанный поток IO
- 7. Как поддерживать постоянный фоновый поток?
- 8. Как убить/остановить фоновый поток?
- 9. Фоновый поток Windows 8?
- 10. Как прервать поток, запущенный внутри другой функции?
- 11. Как прервать поток, созданный внутри метода?
- 12. Как прервать поток onBackPressed без сбоев?
- 13. Как прервать поток при прослушивании кнопок
- 14. Как прервать поток с учетом объекта Future?
- 15. Как прервать другой поток с монитора Thread
- 16. Как прервать() поток, заданный его объектом ThreadInfo?
- 17. Как прервать поток, выполняющий соединение блокирующего сокета?
- 18. Как мы можем прервать основной поток
- 19. Как прервать поток, который использует AcceptTcpClient() внутри?
- 20. Как прервать поток, который запускает неуправляемый код
- 21. Как возобновить или прервать спящий поток
- 22. Как прервать ожидающий поток C++ 0x?
- 23. Как прервать стандартный поток ввода для другого
- 24. Как прервать поток последовательности в OpenWhisk?
- 25. фоновый поток в приложении asp.net
- 26. Сделать фоновый поток в единстве3d
- 27. Сохранение ссылки на фоновый поток в Grails?
- 28. .net Наблюдаемый 'ObserveOn' фоновый поток
- 29. фоновый поток с использованием Task.Run
- 30. Когда Asp.net завершает фоновый поток?
это не скажем, для любого из них, что он прервет поток. –