How to stop AsyncFacebookRunner or stop a request in general?

三世轮回 提交于 2020-01-05 20:24:00

问题


I have an AsyncFacebookRunner that uploads an image to Facebook. I want to create a cancel button that will stop the download.

How can one achieve that?

EDIT:

This is how I use it:

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);

回答1:


You can always extend the AsyncFacebookRunner class and override the request method.
Something like this:

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();
    }
}

It hasn't been tested, but should give you the general idea.


Edit

Now that I think about it, this makes little sense, since you want to use the AsyncFacebookRunner to make multiple requests and the cancel will cancel the last request only.

I would suggest returning the thread and then have the ability to interupt it somewhere else, but you can't change the signature of the method like this and creating a new method won't make it possible to use other request methods defined in the AsyncFacebookRunner class.

Instead you can do something like:

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();
        }
    }
}

You'll need to generate an id somehow for the request, can be something simple like:

String.valueOf(System.currentTimeMillis());



回答2:


You can do something like this:

AsyncFacebookRunner fbRunner;

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

Calling this will also not invoke onPostExecute(Object) so you need to take note of this

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




回答3:


This may not be an elegant solution but you may be able to interrupt the thread the AsyncFacebookRunner is using, handle the resulting exception and gracefully cancel the comms.

Alternatively would you consider forking from the repository and adding your own cancel method to the code?

EDIT

Look at how AsyncTask is implemented in the google source repository. Essentially you need to be able to call a method from any thread that sets a cancelled flag, this would normally be a

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;
}

As you cancel the task your method would set this to true and you would check it at regular intervals from your AsyncFacebookRunner thread.



来源:https://stackoverflow.com/questions/10984531/how-to-stop-asyncfacebookrunner-or-stop-a-request-in-general

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!