Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to determine if a given request is running?

I'm looking at retrofit for my networking layer. Is there any way to tell if a particular async request is running at any given moment?

For example, I'd like to know if a request is running so that I can update the user interface at various times. I could do this myself by keeping variables around to track state, but wondering if there's something already in the library for this.

like image 431
user3203425 Avatar asked Mar 05 '14 02:03

user3203425


People also ask

How do I know if a post request is successful?

If you pick up the result from when you post you can then check the status code: result = Session. post(SubmitURL, data=PostData) if result. status_code == requests.

What is if request method == post?

The result of request. method == "POST" is a boolean value - True if the current request from a user was performed using the HTTP "POST" method, of False otherwise (usually that means HTTP "GET", but there are also other methods).


2 Answers

Here is what I would normally do when needing a way to keep track of running requests:

  • First, using retrofit, as soon as you make the request, you can do the following:
  • Use EventBus library to post an event to your activity or fragment. Now, this can be done inside onSuccess() method of your Callback or onError() method of the same.
  • In your activity or fragment's onEvent(EventClassName event) method, you can simply check a variable like [isRunning] from your event to make sure that if the event is still running, you update the UI accordingly and if not, do what you need to do respectively.
  • When the request is completed, obviously isRunning will be false and you can then update the UI as expected by the user.
  • I am recommending EventBus here simply because it is much easier to decouple your application code with it; you can send different events that notify the activity of the different statuses of your requests and then update your UI that way.

You can find EventBus here

I hope this helps!

like image 65
Eenvincible Avatar answered Sep 18 '22 19:09

Eenvincible


What I personally ended up doing in this case was that I was running the example with Retrofit, Android Priority Jobqueue (from yigit's fork) and Otto eventbus.

public enum SingletonBus {
    INSTANCE;

    private Bus bus;

    private Handler handler = new Handler(Looper.getMainLooper());

    private SingletonBus() {
        this.bus = new Bus(ThreadEnforcer.ANY);
    }

    public <T> void postToSameThread(final T event) {
        bus.post(event);
    }

    public <T> void postToMainThread(final T event) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                bus.post(event);
            }
        });
    }

    public <T> void register(T subscriber) {
        bus.register(subscriber);
    }

    public <T> void unregister(T subscriber) {
        bus.unregister(subscriber);
    }
}

public interface Interactor {
    void injectWith(PresenterComponent presenterComponent);
}

public interface SendCertificateRequestInteractor
        extends Interactor {
    interface Listener {
        void onSuccessfulEvent(SuccessfulEvent e);

        void onFailureEvent(FailureEvent e);
    }

    class SuccessfulEvent
            extends EventResult<CertificateBO> {
        public SuccessfulEvent(CertificateBO certificateBO) {
            super(certificateBO);
        }
    }

    class FailureEvent
            extends EventResult<Throwable> {
        public FailureEvent(Throwable throwable) {
            super(throwable);
        }
    }

    void sendCertificateRequest(String username, String password);
}

Pay attention to the Job here:

public class SendCertificateRequestInteractorImpl
        implements SendCertificateRequestInteractor {
    private Presenter presenter;

    private boolean isInjected = false;

    @Inject
    public JobManager jobManager;

    public SendCertificateRequestInteractorImpl(Presenter presenter) {
        this.presenter = presenter;
    }

    @Override
    public void sendCertificateRequest(String username, String password) {
        if(!isInjected) {
            injectWith(presenter.getPresenterComponent());
            isInjected = true;
        }
        InteractorJob interactorJob = new InteractorJob(presenter, username, password);
        long jobId = jobManager.addJob(interactorJob); //this is where you can get your jobId for querying the status of the task if you want
    }

    @Override
    public void injectWith(PresenterComponent presenterComponent) {
        presenterComponent.inject(this);
    }

    public static class InteractorJob
            extends Job {
        private final static int PRIORITY = 1;
        private final static String TAG = InteractorJob.class.getSimpleName();

        private String username;
        private String password;

        @Inject
        public MyService myService;

        public InteractorJob(Presenter presenter, String username, String password) {
            super(new Params(PRIORITY).requireNetwork());
            presenter.getPresenterComponent().inject(this);
            this.username = username;
            this.password = password;
        }

        @Override
        public void onAdded() {
            // Job has been saved to disk.
            // This is a good place to dispatch a UI event to indicate the job will eventually run.
            // In this example, it would be good to update the UI with the newly posted tweet.
        }

        @Override
        public void onRun()
                throws Throwable {
            String certificate = myService.getCertificate(username, password);
            SingletonBus.INSTANCE.postToMainThread(new SuccessfulEvent(certificate));
        }

        @Override
        protected void onCancel() {
            // Job has exceeded retry attempts or shouldReRunOnThrowable() has returned false.
            Log.e(TAG, "Cancelled job.");
        }

        @Override
        protected boolean shouldReRunOnThrowable(Throwable throwable) {
            // An error occurred in onRun.
            // Return value determines whether this job should retry running (true) or abort (false).
            Log.e(TAG, "Failed to execute job.", throwable);
            SingletonBus.INSTANCE.postToMainThread(new FailureEvent(throwable));
            return false;
        }
    }
}

And then

@Subscribe
@Override
public void onSuccessfulEvent(SendCertificateRequestInteractor.SuccessfulEvent e) {
    String certificate = e.getResult();
    //do things
}

@Subscribe
@Override
public void onFailureEvent(SendCertificateRequestInteractor.FailureEvent e) {
    Throwable throwable = e.getResult(); 
    //handle error
}

More about android priority jobqueue here.

This way, technically the async handling is referred to the job queue, while Retrofit itself is using the synchronous interface. It works well as long as you don't need to access the headers of the response. Although to be fair, I was also keeping track of whether the job was running with a boolean instead of the job manager and the id as well..

Also, I haven't figured out how to use dependency injection properly with persisted jobs; nor do I really know how they intended to make that work. Of course, it'd work if it was using the application scoped component rather than a supplied presenter scoped one, but that is irrelevant.

You'll probably need to customize this solution to your own scenario, and use only what you actually need.

like image 26
EpicPandaForce Avatar answered Sep 20 '22 19:09

EpicPandaForce