如何确定给定的请求是否正在运行?

时间:2014-03-05 02:28:48

标签: android retrofit asyncsocket

我正在寻找我的网络层的改造。有没有办法告诉特定的异步请求是否在任何特定时刻运行?

例如,我想知道请求是否正在运行,以便我可以在不同时间更新用户界面。我可以通过保持变量跟踪状态来自己做这件事,但想知道库中是否已存在某些东西。

2 个答案:

答案 0 :(得分:3)

以下是我在需要一种方法来跟踪正在运行的请求时通常会做的事情:

  • 首先,使用改造,只要您提出请求,就可以执行以下操作:
  • 使用 EventBus 库将事件发布到您的活动或片段。现在,这可以在你的Callback的onSuccess()方法或者onError()方法中完成。
  • 在您的活动或片段的 onEvent(EventClassName事件)方法中,您只需从事件中检查[isRunning]之类的变量,以确保如果事件仍在运行,您相应地更新UI,如果没有,请分别执行您需要执行的操作。
  • 当请求完成后,显然isRunning将为false,然后您可以按照用户的预期更新UI。
  • 我在这里推荐EventBus只是因为将应用程序代码与它分离起来要容易得多;您可以发送不同的事件,通知活动您的请求的不同状态,然后以这种方式更新您的UI。

您可以找到EventBus here

我希望这有帮助!

答案 1 :(得分:2)

我个人在这种情况下最终做的是我使用Retrofit,Android Priority Jobqueue(来自yigit' s)和Otto事件总线运行示例。

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

请注意Job此处:

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

然后

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

有关android priority jobqueue here.

的更多信息

这种方式,从技术上讲,异步处理是指作业队列,而Retrofit本身则使用同步接口。只要您不需要访问响应的标题,它就能正常运行。虽然公平,但 还会跟踪作业是否使用布尔值而不是作业管理器和id来运行。

另外,我还没有弄清楚如何正确使用依赖注入与持久作业;我也不知道他们打算如何做到这一点。当然,如果它使用应用程序作用域组件而不是提供的演示者作用域组件,它就可以工作,但这是无关紧要的。

您可能需要根据自己的方案自定义此解决方案,并仅使用您实际需要的内容。