OkHttp(B) - 要求処理解析

簡単な紹介OkHttp前回の記事のAPIを使用するのは簡単です、あなたは、データを取得するためにOkHttpClientとRequestオブジェクトを作成することで、リモート要求への接続を確立することができます。この記事では、それが特定の要求プロセスを実行する方法をされますかどうかを確認するために、ソースコードの観点から、さらに要求プロセスの詳細な分析を行いOkHttpます。

リクエストメソッド


要求プロセス

OkHttp要求は二つの方法、すなわち、同期および非同期を提供します。実際には、唯一の違いは、2つの方法で、非同期モードを実行するスレッドプールに私たちの要求であり、その具体的な根本的な要求の実現メカニズムが同じであるということです。ここでは明確な思考を維持するためにフォローアップのコード解析プロセスを見るためには、要求プロセスについて話します。

私たちの要求が開始さOkHttpClientにオブジェクトを介してあり、このオブジェクトは、ユーザーの設定情報と、いくつかのコンテキスト情報を保存し、クラスエントリです。コールは、特定のカテゴリを呼び出すユーザーが開始した要求に抽象化することができますインターフェイスRealCallこのオブジェクトされている、Requsetは、特定の要求がそんなに上の情報、IP、ポートとを要求するアドレスが含まれています。

クライアントOkHttpClientは、第1のユーザが、同期モードまたは非同期モードに基づいて選択されるRealCallオブジェクトを作成し、異なる処理を実行するために、呼要求を開始します。同期モードならば、それは要求を実行するスレッドプールに、非同期である場合、最終的に通って直接実行されますインターセプターのチェーン特定処理要求を完了し、応答を取得します。インターセプタチェーンがOkHttpフレームワークのコアであり、私はここであなたはそれが特定のオブジェクトをすることができ実行するための要求として理解置くことができ、後に詳細に説明します。。これは、図の要求のプロセスフローであるグラフによって記述されます。

ここでは、2つの異なる方法でコードの綿密な外観は、実行を達成するための方法です

同期要求

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url("http://www.baidu.com").build();
Response response = client.newCall(request).execute()
复制代码

OkHpptClient 入口 [発信方法を話して:

  1. 実行新規コールは、呼び出し元のオブジェクトRealCallのための特定の要求を作成します
  @Override public Call newCall(Request request) {
    //创建一个具体的请求调用对象RealCall
    return new RealCall(this, request, false /* for web socket */);
  }

复制代码
  1. メソッドのexcuteにより特定の要求の実現をRealCall
@Override public Response execute() throws IOException {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    try {
      //将当前的请求加入runningSyncCalls队列
      client.dispatcher().executed(this);
      //执行请求获取响应
      Response result = getResponseWithInterceptorChain();
      if (result == null) throw new IOException("Canceled");
      return result;
    } finally {
      client.dispatcher().finished(this);
    }
  }
复制代码

キュー内の要求の実行前に要求するため、呼処理状態管理と追跡プロセスと呼ばれる現在のコールrunningSyncCallsに追加されます、RealCall 3つのキューがあります。

  • readyAsyncCalls
    复制代码
    非同期リクエストキューが非同期要求の数が上限に達したときに用意され、これはその後の処理するキューに要求を保存します
  • runningAsyncCalls
    复制代码
    非同期リクエストキューは、現在、現在実行中の要求を格納、実行します
  • runningSyncCalls
    复制代码
    同期要求キューは、現在処理されています
  1. コール完了リクエストインターセプタチェーン処理
    Response result = getResponseWithInterceptorChain();
    复制代码

全体フレームOkHttpの上記コードコア処理ヘッドに応じて、リトライ要求処理など、特定の要求を要求するプロセスを完了するために、内部インターセプタインターセプタチェーンの一連によって達成されたものの、処理ロジック本体への応答インチ ここで私たちは、あなたが私たちの要求は、インターセプタチェーンでの応答を要求し得ることであることを知って、それを説明する展開されません。以上の処理タイミングチャートを以下に示します。

非同期リクエスト

同期要求を実行するためのコールコールオブジェクトメソッドをExcute、エンキュー(コールバックresponseCallback)を呼び出し、コールバックインターフェースレスポンス、成功または失敗した操作を実行するための要求に対する応答を渡す必要が非同期要求を実行します。

  @Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      //标志状态
      executed = true;
    }
    captureCallStackTrace();
    //将请求加入队列,并通过线程池来执行
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }
复制代码
  1. オブジェクトによってキューに入れられたディスパッチ要求は、要求キューが追加されます
      synchronized void enqueue(AsyncCall call) {
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);
      executorService().execute(call);
    } else {
      //如果已达到当前最大的处理请求数,则排队等待
      readyAsyncCalls.add(call);
    }
  }
复制代码

; 2つの結合同時要求の最大数の各ホスト1、同時要求の合計最大数:最初の要求された制限、要求は、2つを含む、上限か否かを判断します。二つは達していない場合、上限は、処理のためにスレッドプールに直接添加されます。のは、スレッドプールを作成するためのコードを見てみましょう

  public synchronized ExecutorService executorService() {
    if (executorService == null) {
      executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
          new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
    }
    return executorService;
  }
复制代码

ここではそこにはコアスレッドプールのスレッドは要求がないときのリソースを消費しているアイドルスレッドが、Integer.MAX_VALUEでのスレッドの最大数は存在しません、ではない、それはいつもの規範の競合の一部です。しかし、前の要求の上限はちょうどそれが、実際には、これが作成できるスレッドの最大数の最大数を制限したので、心配しないことを覚えておいてください。

  1. リクエストが上限に達していない場合は、呼び出し元のスレッドプールは、要求を実行します
    executorService().execute(call)
复制代码

実行asyncCallの実装クラスに対応する呼び出しは、実際に、それはRunable()インターフェース、execute()メソッドでこのロジックの特定の目的のための要求を継承します

    @Override protected void execute() {
      boolean signalledCallback = false;
      try {
        //执行请求,返回响应
        Response response = getResponseWithInterceptorChain();
        if (retryAndFollowUpInterceptor.isCanceled()) {
          signalledCallback = true;
          responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
        } else {
          signalledCallback = true;
          responseCallback.onResponse(RealCall.this, response);
        }
      } catch (IOException e) {
        if (signalledCallback) {
          // Do not signal the callback twice!
          Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
        } else {
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        //完成请求处理,从runningSyncCalls队列中移除当前请求对象,从readyAsyncCalls中出队请求,加入runningSyncCalls,并调用线程池执行
        client.dispatcher().finished(this);
      }
    }
  }
复制代码

詳細な実行要求と同様に、同期要求、コールが処理されるインターセプタチェーン

Response response = getResponseWithInterceptorChain();
复制代码
  1. 要求が上限に達した場合、追加のキューは、要求は、第1工程の前にキューに入る要求は、前述の説明を参照して、言われています

  2. 各要求の後、待ちキューから順次スレッドプールに行っデキュー。最後に実行されたプロセス方法ASyncalCallオブジェクト、最後にメソッド本体では、メソッド呼び出しの仕上げは、待ちキューと要求の実行から削除します

  private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
    int runningCallsCount;
    Runnable idleCallback;
    synchronized (this) {
      if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
      //从等待队列中出队请求到运行队列,调用线程池执行
      if (promoteCalls) promoteCalls();
      runningCallsCount = runningCallsCount();
      idleCallback = this.idleCallback;
    }
复制代码

特定のpromoteCalls方法で参照してください、それは待ちキューから取り出した要求ロジックを完了し、要求を実行します

  private void promoteCalls() {
    if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
    if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.

    for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
      //从等待队列中取出一个请求
      AsyncCall call = i.next();

      if (runningCallsForHost(call) < maxRequestsPerHost) {
        i.remove();
        //加入运行队列
        runningAsyncCalls.add(call);
        //执行请求
        executorService().execute(call);
      }

      if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
    }
  }
复制代码

概要

我々はそれが非常に簡単で見ることができます行われた分析にリクエストを要求し、非同期のための同期プロセスが、特定のプロセスの実行要求を達成する方法である、それはインターセプタ処理チェーンに対処する方法で、これはフレームワークであり、コア部分、我々は上の焦点を当てます、次のページでは、特定の分析を持っていません。

おすすめ

転載: juejin.im/post/5d463fb0e51d4561e62370db