1

我有一个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);
4

3 回答 3

1

您始终可以扩展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();
        }
    }
}

您需要以某种方式为请求生成一个 id,可以很简单,例如:

String.valueOf(System.currentTimeMillis());
于 2012-06-20T21:38:31.703 回答
0

你可以这样做:

AsyncFacebookRunner fbRunner;

@Override
public void onClick(View v){
    fbRunner.cancel(true);
}

调用它也不会调用 onPostExecute(Object) 所以你需要注意这一点

http://developer.android.com/reference/android/os/AsyncTask.html#cancel(boolean )

于 2012-06-13T00:18:32.200 回答
0

这可能不是一个优雅的解决方案,但您可以中断AsyncFacebookRunner正在使用的线程,处理产生的异常并优雅地取消通信。

或者,您是否会考虑从存储库分叉并将您自己的取消方法添加到代码中?

编辑

看看AsyncTaskgoogle 源代码库中是如何实现的。本质上,您需要能够从设置取消标志的任何线程调用方法,这通常是

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线程中检查它。

于 2012-06-19T14:06:21.363 回答