Как остановить AsyncFacebookRunner или вообще остановить запрос?
У меня есть AsyncFacebookRunner
который загружает изображение в Facebook. Я хочу создать кнопку отмены, которая остановит загрузку.
Как можно этого достичь?
РЕДАКТИРОВАТЬ:
Вот как я это использую:
byte[] data = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
data = baos.toByteArray();
Bundle params = new Bundle();
params.putByteArray("picture", data);
AsyncFacebookRunner mAsyncRunner = new AsyncFacebookRunner(facebook);
mAsyncRunner.request("me/photos", params, "POST",
new PhotoUploadListener(dialog), null);
3 ответа
Вы всегда можете продлить AsyncFacebookRunner
класс и переопределить request
метод.
Что-то вроде этого:
public class CancelableAsyncFacebookRunner extends AsyncFacebookRunner {
private Thread requestThread;
public AsyncFacebookRunner(Facebook fb) {
super(fb);
}
@Override
public void request(final String graphPath,
final Bundle parameters,
final String httpMethod,
final RequestListener listener,
final Object state) {
this.requestThread = new Thread() {
@Override
public void run() {
try {
String resp = fb.request(graphPath, parameters, httpMethod);
listener.onComplete(resp, state);
} catch (FileNotFoundException e) {
listener.onFileNotFoundException(e, state);
} catch (MalformedURLException e) {
listener.onMalformedURLException(e, state);
} catch (IOException e) {
listener.onIOException(e, state);
}
}
};
}
public void cancel() {
this.requestThread.interrupt();
}
}
Это не было проверено, но должно дать вам общее представление.
редактировать
Теперь, когда я думаю об этом, это не имеет большого смысла, так как вы хотите использовать AsyncFacebookRunner
сделать несколько запросов и cancel
отменит только последний запрос.
Я бы предложил вернуть поток, а затем иметь возможность перехватить его где-то еще, но вы не можете изменить сигнатуру метода, как этот, и создание нового метода не позволит использовать другие request
методы, определенные в AsyncFacebookRunner
учебный класс.
Вместо этого вы можете сделать что-то вроде:
public class CancelableAsyncFacebookRunner extends AsyncFacebookRunner {
private Hashtable<String, Thread> requestThreads;
public AsyncFacebookRunner(Facebook fb) {
super(fb);
this.requestThreads = new Hashtable<String, Thread>();
}
@Override
public void request(final String id,
final String graphPath,
final Bundle parameters,
final String httpMethod,
final RequestListener listener,
final Object state) {
Thread thread = new Thread() {
@Override
public void run() {
try {
String resp = fb.request(graphPath, parameters, httpMethod);
requestThreads.remove(id);
listener.onComplete(resp, state);
} catch (FileNotFoundException e) {
requestThreads.remove(id);
listener.onFileNotFoundException(e, state);
} catch (MalformedURLException e) {
requestThreads.remove(id);
listener.onMalformedURLException(e, state);
} catch (IOException e) {
requestThreads.remove(id);
listener.onIOException(e, state);
}
}
});
this.requestThreads.put(id, thread);
thread.start();
}
public void cancel(String id) {
if (this.requestThreads.containsKey(id) {
this.requestThreads.get(id).interrupt();
}
}
}
Вам нужно как-то сгенерировать идентификатор для запроса, может быть что-то простое, например:
String.valueOf(System.currentTimeMillis());
Вы можете сделать что-то вроде этого:
AsyncFacebookRunner fbRunner;
@Override
public void onClick(View v){
fbRunner.cancel(true);
}
Вызов этого также не вызовет onPostExecute(Object), поэтому вы должны принять это к сведению
http://developer.android.com/reference/android/os/AsyncTask.html)
Это может быть не элегантным решением, но вы можете прервать поток AsyncFacebookRunner
использует, обработайте полученное исключение и корректно отмените связь.
В качестве альтернативы вы могли бы рассмотреть возможность разветвления из репозитория и добавления собственного метода отмены в код?
РЕДАКТИРОВАТЬ
Посмотри как AsyncTask
реализовано в репозитории исходного кода Google. По сути, вы должны иметь возможность вызывать метод из любого потока, который устанавливает отмененный флаг, обычно это
private volatile boolean cancelled = false;
// volatile ensures you always get up to date value when checking across threads
public void cancel() {
cancelled = true;
}
public boolean isCancelled() {
return cancelled;
}
Когда вы отменяете задачу, ваш метод установит для нее значение true, и вы будете регулярно проверять его AsyncFacebookRunner
нить.