14

ネットワーク層の改良を検討しています。特定の非同期リクエストが特定の時点で実行されているかどうかを確認する方法はありますか?

たとえば、さまざまなタイミングでユーザー インターフェイスを更新できるように、リクエストが実行されているかどうかを知りたいとします。状態を追跡するために変数を保持することでこれを自分で行うことができますが、これのためにライブラリに既に何かがあるかどうか疑問に思っています。

4

2 に答える 2

3

実行中のリクエストを追跡する方法が必要な場合、通常は次のようにします。

  • まず、レトロフィットを使用すると、リクエストを行うとすぐに次のことができます。
  • EventBusライブラリを使用して、イベントをアクティビティまたはフラグメントに投稿します。これは、Callback の onSuccess() メソッドまたは同じ onError() メソッド内で実行できます。
  • アクティビティまたはフラグメントのonEvent(EventClassName event)メソッドでは、イベントから [isRunning] などの変数をチェックして、イベントがまだ実行されている場合はそれに応じて UI を更新し、そうでない場合は必要なことを行うことができます。それぞれ行います。
  • リクエストが完了すると、明らかに isRunning は false になり、ユーザーが期待するように UI を更新できます。
  • ここで EventBus をお勧めするのは、単純に、アプリケーション コードを EventBus と分離する方がはるかに簡単だからです。リクエストのさまざまなステータスのアクティビティを通知するさまざまなイベントを送信し、その方法で UI を更新できます。

ここでEventBusを見つけることができます

これが役立つことを願っています!

于 2015-06-12T14:11:37.953 に答える
2

この場合、私が個人的に行ったことは、Retrofit、Android Priority Jobqueue (yigit のフォークから)、および 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);
}

ここに注意して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 こちら。

このように、技術的には非同期処理はジョブ キューを参照し、Retrofit 自体は同期インターフェイスを使用しています。応答のヘッダーにアクセスする必要がない限り、これはうまく機能します。公平を期すために、ジョブマネージャーとIDの代わりにブール値でジョブが実行されているかどうかも追跡していました..

また、永続化されたジョブで依存性注入を適切に使用する方法もわかりません。また、彼らがどのようにそれを機能させるつもりだったのか、私には本当にわかりません。もちろん、提供されたプレゼンター スコープのコンポーネントではなく、アプリケーション スコープのコンポーネントを使用していれば機能しますが、それは関係ありません。

おそらく、このソリューションを独自のシナリオに合わせてカスタマイズし、実際に必要なものだけを使用する必要があります。

于 2015-06-12T14:33:41.323 に答える