精华内容
下载资源
问答
  • OkHttp请求

    2018-12-07 11:08:49
    okhttp请求有同步请求,也有异步请求。异步请求的使用场景更为广阔。 同步请求 public class OkHttp { public static void main(String[] args) throws Exception { //创建一个OkHttpClient对象 int time...

    okhttp的请求有同步请求,也有异步请求。异步请求的使用场景更为广阔。

    同步请求

    public class OkHttp {
    
    
        public static void main(String[] args) throws Exception {
    
            //创建一个OkHttpClient对象
            int timeout = 10 * 1000;
            OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    .retryOnConnectionFailure(true)
                    .connectTimeout(timeout, TimeUnit.MILLISECONDS)
                    .readTimeout(timeout, TimeUnit.MILLISECONDS)
                    .writeTimeout(timeout, TimeUnit.MILLISECONDS)
                    .build();
    
            String url = "测试接口地址";
            Map<String,Object> headersMap = new HashMap<>();
            headersMap.put("Content-Type","application/json");
            Map<String ,Object> bodyMap = new HashMap<>();
            bodyMap.put("username", "xiaoming");
            bodyMap.put("password", "123");
    
    
            //构建请求体
            RequestBody requestBody = RequestBody.create(null,JSON.toJSONString(bodyMap));
            //构建请求头
            Headers.Builder headerBuilder = new Headers.Builder();
            headersMap.forEach((key,value)-> headerBuilder.add(key,value.toString()));
            Headers headers = headerBuilder.build();
    
            //创建请求
            Request request = new Request.Builder()
                    .url(url)
                    .headers(headers)
                    .post(requestBody)
                    .build();
    
            Response response = okHttpClient.newCall(request).execute();
            if (response.isSuccessful()) {
                try {
                    assert response.body() != null;
                    String responseBody = response.body().string();
                    System.out.println(responseBody);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    异步请求

    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONArray;
    import com.alibaba.fastjson.JSONObject;
    
    import com.sun.deploy.net.URLEncoder;
    import okhttp3.*;
    import org.hibernate.validator.internal.metadata.aggregated.rule.OverridingMethodMustNotAlterParameterConstraints;
    
    import java.io.IOException;
    import java.text.MessageFormat;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.concurrent.TimeUnit;
    
    public class OkHttp {
    
    
        public static void main(String[] args) throws Exception {
    
            //创建一个OkHttpClient对象
            int timeout = 10 * 1000;
            OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    .retryOnConnectionFailure(true)
                    .connectTimeout(timeout, TimeUnit.MILLISECONDS)
                    .readTimeout(timeout, TimeUnit.MILLISECONDS)
                    .writeTimeout(timeout, TimeUnit.MILLISECONDS)
                    .build();
    
            String url = "http://wzy.f5tv.com:8081/admin/query2";
            Map<String,Object> headersMap = new HashMap<>();
            headersMap.put("Content-Type","application/json");
            Map<String ,Object> bodyMap = new HashMap<>();
            bodyMap.put("username", "xiaoming");
            bodyMap.put("password", "123");
    
    
            //构建请求体
            RequestBody requestBody = RequestBody.create(null,JSON.toJSONString(bodyMap));
            //构建请求头
            Headers.Builder headerBuilder = new Headers.Builder();
            headersMap.forEach((key,value)-> headerBuilder.add(key,value.toString()));
            Headers headers = headerBuilder.build();
    
            //创建请求
            Request request = new Request.Builder()
                    .url(url)
                    .headers(headers)
                    .post(requestBody)
                    .build();
    
            Call call = okHttpClient.newCall(request);
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    System.out.println("请求失败");
                }
    
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    if (response.isSuccessful()) {
                        System.out.println(response.body().string());
                    }
                    System.out.println("请求成功");
                }
            });
        }
    }

     

    展开全文
  • okhttp请求json数据

    2017-09-10 20:47:56
    我们需要二次封装下okhttp请求: public class OkHttpUtils { //声明OkHttpClient引用 private OkHttpClient client; //私有化构造方法 private OkHttpUtils(){ //创建client对象只在创建OkHttpUi

    布局文件:

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipe"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"></android.support.v7.widget.RecyclerView>
    </android.support.v4.widget.SwipeRefreshLayout>
    

    我们需要二次封装下okhttp请求:

    public class OkHttpUtils {
    
            //声明OkHttpClient引用
            private OkHttpClient client;
    
            //私有化构造方法
            private OkHttpUtils(){
                //创建client对象只在创建OkHttpUitls对象时创建一次
                client = new OkHttpClient();
            }
            //声明静态OkHttpUtils引用
            private static OkHttpUtils utils;
            //单例设计模式让外部始终获得的是一个OkHttpUtils对象
            public static OkHttpUtils getInstance() {
                //双重判断加上同步锁可以解决线程安全问题
                if(utils==null){
                    synchronized (OkHttpUtils.class){
                        if(utils==null){
    
                            //一旦判断没有创建过此类的对象就创建一次并返回
                            utils = new OkHttpUtils();
    
                            return utils;
                        }
                    }
                }
                return utils;
            }
            //定义一个callback接口并定义范型(适用于任意类的返回对象)用于接口回调
            public interface CallBack<T>{
                //定义回调方法
                void getData(T t);
            }
    
            //创建万能的数据请求类,形参为四个activity对象,网址url,和得到数据的bean类为范型的class对象,实现接口的类对象
            public <T extends Object>void getBeanOfOk(final Activity activity, String url, final Class<T> clazz, final CallBack<T> callback){
    
                //创建request请求对象,设置其方式get,网址url
                Request request = new Request.Builder().get().url(url).build();
    
                //通过client的newCall方法传入request,并调用enqueue求求数据
                client.newCall(request).enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                    }
                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        //通过返回的response对象的body()和string()方法得到获取的json字符串
                        String json = response.body().string();
                        //通过Gson解析得到解析后任意类对象
                        final T t  = new Gson().fromJson(json,clazz);
                        //由于子线程中不能更新UI所以我们用activity对象调用方法回到主线程
                        activity.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                if(t!=null){
                                    //并用过接口回调传回数据
                                    callback.getData(t);
                                }
                            }
                        });
                    }
                });
            }
    }
    
    然后就是在MainActivity中调用它请求接口:
    private void loadData() {
    
        //通过类名直接调用静态方法获取单例对象再调用getBeanOfOK()方法传入参数通过接口回调获取数据
        OkHttpUtils.getInstance().getBeanOfOk(this, url + page, Data.class,
                new OkHttpUtils.CallBack<Data>() {
                    @Override
                    public void getData(Data testBean) {
    
                        Log.i("===", "getData: " + testBean.toString());
                        if (testBean != null) {
                            //如果不为空用本地list接收
                            list.addAll(testBean.getData());
                            //数据一旦回调成功初始化数据源和适配器
                            initAdapter();
                        }
                    }
                });
    }
    然后是在MainActivity中new适配器的方法:
    //设置适配器
    public void initAdapter() {
        adapter = new RecyclerAdapter(list, this);
        recyclerView.setAdapter(adapter);
        adapter.setOnItemonclicklinear(new OnItemonclicklinear() {
            @Override
            public void onClickListener(View v, int position) {
                Data.DataBean bean = list.get(position);
                Toast.makeText(MainActivity.this, bean.getUserName(), Toast.LENGTH_SHORT).show();
            }
        });
    }
    然后在MainActivity中设置上拉加载下拉刷新:
    private void initData() {
        //上拉刷新
        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                page ++;
                loadData();
                adapter.notifyDataSetChanged();
                swipeRefreshLayout.setRefreshing(false);
            }
        });
        //下拉加载
        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
                if (lastVisibleItemPosition==list.size()-1){
                    page++;
                    loadData();
                    adapter.notifyDataSetChanged();
                }
            }
        });
    
    }
    然后是适配器:
    public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
        private List<Data.DataBean> list;
        private Context context;
        private OnItemonclicklinear onItemonclicklinear;
    
        public void setOnItemonclicklinear(OnItemonclicklinear onItemonclicklinear) {
            this.onItemonclicklinear = onItemonclicklinear;
    
        }
    
        public RecyclerAdapter(List<Data.DataBean> list, Context context) {
            this.list = list;
            this.context = context;
        }
    
        //加载布局。
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = null;
            RecyclerView.ViewHolder viewHolder = null;
            view = LayoutInflater.from(context).inflate(R.layout.item, null);
            viewHolder = new myViewHolder(view);
            return viewHolder;
        }
        //赋值
        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
            Data.DataBean bean=list.get(position);
    //        name, occupation, age, introduction;
            final myViewHolder myViewHolder= (myViewHolder) holder;
            myViewHolder.occupation.setText(bean.getOccupation());
            myViewHolder.age.setText(bean.getUserAge()+"岁");
            myViewHolder.introduction.setText(bean.getIntroduction());
            myViewHolder.name.setText(bean.getUserName());
            Glide.with(context).load(bean.getUserImg()).into(myViewHolder.imageView);
            //监听事件回调
            myViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    onItemonclicklinear.onClickListener(myViewHolder.itemView,position);
                    ObjectAnimator animator=ObjectAnimator.ofFloat(myViewHolder.itemView,"alpha",0.0f,1.0f).setDuration(1000);
                    animator.start();
                }
            });
        }
    
        @Override
        public int getItemCount() {
            return list != null ? list.size() : 0;
        }
    
        static class myViewHolder extends RecyclerView.ViewHolder {
            TextView name, occupation, age, introduction;
            ImageView imageView;
    
            public myViewHolder(View itemView) {
                super(itemView);
                name = (TextView) itemView.findViewById(R.id.name);
                age = (TextView) itemView.findViewById(R.id.age);
                occupation = (TextView) itemView.findViewById(R.id.occupation);
                introduction = (TextView) itemView.findViewById(R.id.introduction);
                imageView = (ImageView) itemView.findViewById(R.id.iamge);
            }
        }
    }
    
    在适配器里的OnItemonclicklinear需要创建一个类:
    public interface OnItemonclicklinear {
        void onClickListener(View v,int position);
    }
    
    还有在MainActivity中初始化数据
    //初始化数据
    private void initView() {
        recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
        swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe);
        //线性布局管理及设置
        linearLayoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(linearLayoutManager);
        recyclerView.addItemDecoration(new ItemDecration(this));
        initData();
    
    }
    初始化ItemDecration类
    public class ItemDecration extends RecyclerView.ItemDecoration {
        private int with;
        private Context context;
    
        public ItemDecration(Context context) {
            this.context = context;
            DisplayMetrics displayMetrics = new DisplayMetrics();
            ((Activity) context).getWindow().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
            with = displayMetrics.widthPixels;
        }
    
        @Override
        public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
            super.onDraw(c, parent, state);
            Paint paint = new Paint();
            paint.setColor(Color.RED);
            int childCount = parent.getChildCount();
            for (int i = 0; i < childCount; i++) {
                View view = parent.getChildAt(i);
                int bottom=view.getBottom();
                c.drawLine(0,bottom,with,bottom,paint);
            }
        }
    }
    

     
    

    展开全文
  • Android OkHttp请求流程

    2020-12-02 14:48:51
    一、基本使用 ... *用途:OkHttp使用举例 */ public void TestOkHttp() { //设置超时的时间 OkHttpClient.Builder builder = new OkHttpClient.Builder() .connectTimeout(15, TimeUnit.SECONDS) .

     一、基本使用

    /*
         *作者:赵星海
         *时间:2020/12/2 11:12
         *用途:OkHttp使用举例
         */
        public void TestOkHttp() {
            //设置超时的时间
            OkHttpClient.Builder builder = new OkHttpClient.Builder()
                    .connectTimeout(15, TimeUnit.SECONDS)
                    .writeTimeout(20, TimeUnit.SECONDS)
                    .readTimeout(20, TimeUnit.SECONDS)
                    .addInterceptor(new Interceptor() { //添加拦截器
                        @Override
                        public Response intercept(Chain chain) throws IOException {
                            return null;
                        }
                    })
                    .retryOnConnectionFailure(true);// 失败重连
    
            OkHttpClient okHttpClient = builder.build();
            //------------------------------------------------
            RequestBody body = new FormBody.Builder()
                    .add("name", "")
                    .add("sex", "").build();
            Request request = new Request.Builder()
                    .post(body) //设置请求模式get/post 等
                    .url("https://www.baidu.com/")
                    .build();
            //----------------------------------------------
            Call call = okHttpClient.newCall(request);
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    //失败
                }
    
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    //子线程 成功
                }
            });
            //===========================================================
            //链式调用:
            new OkHttpClient.Builder().build()
                    .newCall(new Request.Builder()
                            .post(new FormBody.Builder().add("name", "").build())
                            .url("https://www.baidu.com/")
                            .build()).enqueue(new Callback() {
    
                @Override
                public void onFailure(Call call, IOException e) {
    
                }
    
                @Override
                public void onResponse(Call call, Response response) throws IOException {
    
                }
            });
    
        }

     二、请求流程

    j

    图片来源于网络

    结合上面的使用举例代码,咱们来依次看一下源码:

    1.new OkHttpClient.Builder():

    源码:下同

        public Builder() {
          dispatcher = new Dispatcher();//任务调度器
          protocols = DEFAULT_PROTOCOLS;//支持的协议
          connectionSpecs = DEFAULT_CONNECTION_SPECS;
          eventListenerFactory = EventListener.factory(EventListener.NONE);//事件监听器
          proxySelector = ProxySelector.getDefault();
          cookieJar = CookieJar.NO_COOKIES;
          socketFactory = SocketFactory.getDefault();
          hostnameVerifier = OkHostnameVerifier.INSTANCE;
          certificatePinner = CertificatePinner.DEFAULT;
          proxyAuthenticator = Authenticator.NONE;
          authenticator = Authenticator.NONE;
          connectionPool = new ConnectionPool();//连接池
          dns = Dns.SYSTEM;
          followSslRedirects = true;
          followRedirects = true;
          retryOnConnectionFailure = true;
          connectTimeout = 10_000;//超时时间
          readTimeout = 10_000;
          writeTimeout = 10_000;
          pingInterval = 0;
        }

    //----------------三个队列-----------------------------------------

    Dispatcher任务调度器,它定义了三个双向任务队列:准备执行的异步请求队列 readyAsyncCalls、正在运行的异步请求队列 runningAsyncCalls、正在运行的同步请求队列 runningSyncCalls。

    //---------------一个线程池------------------------------------------

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

    任务调度器中的executorService线程池 ,与Android中的CachedThreadPool非常类似,这种类型的线程池,适用于大量的耗时较短的异步任务。

    关于线程池的参数和介绍可以看这里:https://blog.csdn.net/qq_39731011/article/details/107913058

    //----------------将任务添加到任务队列的判断-------------------

    private int maxRequests = 64;
    private int maxRequestsPerHost = 5;
    synchronized void enqueue(AsyncCall call) {
        if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
          runningAsyncCalls.add(call);
          executorService().execute(call);   //@CSDN深海呐
        } else {
          readyAsyncCalls.add(call);
        }
      }

    任务调度器中的enqueue方法:当正在进行的异步请求数小于64 并且同一个Host的请求小于5 才会放入运行队列,否则放入准备队列。

    异步请求的 Call 不是原始的 Call,而是被包装为AsyncCall。

        final class AsyncCall extends NamedRunnable {
        private final Callback responseCallback;
    
        AsyncCall(Callback responseCallback) {
          super("OkHttp %s", redactedUrl());
          this.responseCallback = responseCallback;
        }
        ...
        @Override protected void execute() {
          boolean signalledCallback = false;
          try {
            // 调用 getResponseWithInterceptorChain
            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 {
            client.dispatcher().finished(this);
          }
        }
      }

    AsyncCall继承自NamedRunnable,它其实就是一个为线程设置了名字的 Runnable,在其 Run 中调用execute,所以AsyncCall 的主要逻辑都写在 execute中。

    可以看到最终还是调用了getResponseWithInterceptorChain方法,所以后续执行网络请求的逻辑是一样的。

    在获得 response 之后,就可以调用 responseCallback 返回最终的信息。

    finished

    在上面的代码中,finally 里面执行了 client.dispatcher().finished(this),在同步请求 RealCall#execute() 中也有类似的一行代码。

    finished 的作用是让 Dispatcher 从队列中移除已完成的 Call,对于异步请求还会从 readyAsyncCalls 中取出等待中的请求提交给线程池。

    下面是具体代码:

     /** Used by {@code AsyncCall#run} to signal completion. */
      void finished(AsyncCall call) {
        finished(runningAsyncCalls, call, true);
      }
    
      /** Used by {@code Call#execute} to signal completion. */
      void finished(RealCall call) {
        finished(runningSyncCalls, call, false);
      }
      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;
        }
    
        if (runningCallsCount == 0 && idleCallback != null) {
          idleCallback.run();
        }
      }
        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();
          // 找到一个等待队列中的 Call,符合连接数要求时加入 runningAsyncCalls 并提交给线程池执行。
          if (runningCallsForHost(call) < maxRequestsPerHost) {
            i.remove();
            runningAsyncCalls.add(call);
            executorService().execute(call);
          }
    
          if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
        }
      }

    有两个重载的 finished 方法均调用了另一个 pirvate 的 finished,区别在于这个 finished 的最后一个参数 promoteCalls

    对于同步请求(参数为 RealCallpromoteCalls 为 false,而异步请求(参数为 AsyncCallpromoteCalls 为 true

    pirvate 的 finished 主要是从队列中移除 Call,异步请求会执行 promoteCallspromoteCalls 里面主要是从 readyAsyncCalls 取出一个 Call,

    如果满足最大连接数的要求,则把这个 Call 加入 runningAsyncCalls 并提交给线程池执行。

    通过 runningAsyncCalls 和 readyAsyncCalls,Dispatcher 实现了异步请求的调度执行。

    这里比较巧妙的方式是在 finally 中去执行 readyAsyncCalls 中的请求,避免了 wait/notity 的方式,避免了代码的复杂性。

    //----------------拦截器---Interceptor-----------------------------------------

    getResponseWithInterceptorChain 的代码如下:

    Response getResponseWithInterceptorChain() throws IOException {
       // Build a full stack of interceptors.
       List<Interceptor> interceptors = new ArrayList<>();
       interceptors.addAll(client.interceptors());
       interceptors.add(retryAndFollowUpInterceptor);
       interceptors.add(new BridgeInterceptor(client.cookieJar()));
       interceptors.add(new CacheInterceptor(client.internalCache()));
       interceptors.add(new ConnectInterceptor(client));
       if (!forWebSocket) {
         interceptors.addAll(client.networkInterceptors());
       }
       interceptors.add(new CallServerInterceptor(forWebSocket));
    
       Interceptor.Chain chain = new RealInterceptorChain(
           interceptors, null, null, null, 0, originalRequest);
       return chain.proceed(originalRequest);
     }

    可以看到,其中创建了一个 List 用于添加 Interceptor。首先添加的是 client 中的 interceptors,

    也就是在创建 OkHttpClient 对象时自定义的 interceptors,然后依次添加 retryAndFollowUpInterceptor(重试及重定向)、

    BridgeInterceptor(请求参数的添加)、CacheInterceptor(缓存)、ConnectInterceptor(开始连接)、

    用户自定义的 networkinterceptors 及 CallServerInterceptor(发送参数并读取响应)。

    从这里可以知道,OkHttp 默认添加了好几个 interceptor 用于完成不同的功能。

    在研究各个 interceptor 之前,需要考虑一下如何让这些拦截器一个接着一个的执行?

    继续看上面的代码,在添加了各种 interceptors 之后,创建了一个 RealInterceptorChain 对象。

    (它的构造函数需要的参数很多,并且这些参数涉及到连接池、请求数据的发送等。

    由于这篇文章主要分析 OkHttp 的基本流程,所以暂时略过这部分)RealInterceptorChain 是接口 Chain 的实现类,

    Chain 是  的意思,其作用是把各个 Interceptor 串起来依次执行。在获得了 RealInterceptorChain 之后调用其 proceed 方法,

    看名字就能知道是让 Request 请求继续执行。

    下面具体分析 RealInterceptorChain,它有如下的成员变量:

      private final List<Interceptor> interceptors;  // 拦截器
      private final StreamAllocation streamAllocation; // 流管理器
      private final HttpCodec httpCodec; // http流,发送请求数据并读取响应数据
      private final RealConnection connection;  // scoket的连接
      private final int index; // 当前拦截器的索引
      private final Request request; // 当前的请求
      private int calls; // chain 的 proceed 调用次数的记录

    其中 streamAllocationhttpCodec 和 connection 都与 socket 连接有关,后续文章再分析。看一下 proceed 方法:

      public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
          RealConnection connection) throws IOException {
        if (index >= interceptors.size()) throw new AssertionError();
    
        calls++;
    
        // If we already have a stream, confirm that the incoming request will use it.
        // 如果已经有了一个流,确保即将到来的 request 是用它
        if (this.httpCodec != null && !this.connection.supportsUrl(request.url())) {
          throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
              + " must retain the same host and port");
        }
    
        // If we already have a stream, confirm that this is the only call to chain.proceed().
        // 如果已经有了一个流,确保这是对 call 唯一的调用
        if (this.httpCodec != null && calls > 1) {
          throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
              + " must call proceed() exactly once");
        }
    
    
        // Call the next interceptor in the chain.         
        RealInterceptorChain next = new RealInterceptorChain(
            interceptors, streamAllocation, httpCodec, connection, index + 1, request);                           // (1)
        Interceptor interceptor = interceptors.get(index); // (2)
        Response response = interceptor.intercept(next);   // (3)
    
        // Confirm that the next interceptor made its required call to chain.proceed().                                 
        if (httpCodec != null && index + 1 < interceptors.size() && next.calls != 1) {
          throw new IllegalStateException("network interceptor " + interceptor
              + " must call proceed() exactly once");
        }
    
        // Confirm that the intercepted response isn't null.
        if (response == null) {
          throw new NullPointerException("interceptor " + interceptor + " returned null");
        }
    
        return response;
      }

    刚开始做了一些连接方面的判断,需要关注的是标了(1)、(2)、(3)的几行,主要做了以下操作:

    1. 创建新的 RealInterceptorChain,其中 index 加1用于标识当前的拦截器
    2. 通过 index 获取当前的拦截器
    3. 调用下一个拦截器的 intercept 方法,并把上面生成的新的 RealInterceptorChain 对象 next 传进去

    由之前的 getResponseWithInterceptorChain 方法可以知道,当前 RealInterceptorChain 的 interceptors 的第一个是 RetryAndFollowUpInterceptor

    下面是其 intercept 的代码:

        @Override public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
    
        streamAllocation = new StreamAllocation(
            client.connectionPool(), createAddress(request.url()), callStackTrace);
    
        int followUpCount = 0;
        Response priorResponse = null;
        while (true) {
          if (canceled) {
            streamAllocation.release();
            throw new IOException("Canceled");
          }
    
          Response response = null;
          boolean releaseConnection = true;
          try {
            // 调用 chain 的 proceed
            response = ((RealInterceptorChain) chain).proceed(request, streamAllocation, null, null);
            releaseConnection = false;
          } catch (RouteException e) {
            ... // 省略部分代码,主要是错误重试以及重定向
        }
      }

    这个 Interceptor 主要用于出错重试以及重定向的逻辑,其中省略了部分代码。

    在这个方法当中要关注的是再次调用了 chain 的 proceed 方法,这里的 chain 是之前新创建的 next 对象。

    相当于说通过调用 Chain#proceed() 将网络请求推向下一个拦截器(proceed 中会获取下一个 Interceptor 并调用其 intercept 方法),

    并且得到 response 对象,而下一个拦截器也是类似的操作。于是,多个 interceptors 就通过这种方式串起来依次执行,

    并且前一个 Interceptor 可以得到后一个 Interceptor 执行后的 response 从而进行处理。

    通过不同的 Interceptor,OkHttp 实现了不同的功能。

    各个 Inercept 职责分明又不会互相耦合,并且可以非常方便的添加 Interceptor,

    这是 责任链 模式的体现,非常优雅的设计。

    现在可以发现 OkHttp 中的拦截器的调用过程如下图所示:

    图片描述

    步骤:

    1. OkHttpClient 调用 newCall 创建 RealCall 对象,Call 封装了 Request,代表一条即将执行的请求。
    2. 根据同步还是异步请求分别调用 RealCall 的 execute 或 enqueue 方法,将Call 加入 Dispatcher 的相应队列中。最终,同步或异步请求都会调用 getResponseWithInterceptorChain
    3. 在 getResponseWithInterceptorChain 中,OkHttp 添加用户自定义以及默认的 inceptors,并用一个 Chain 管理并依次执行每个 Interceptor。
    4. 每个 Interceptor 调用 Chain#proceed() 将请求发送给下一级的 Inceptor,并能通过这个方法获得下一级 Interceptor 的 Response。所以上图所示,Request 一级级地往下传递,而获取了网络的 Response 之后一级级地往上传递。

    展开全文
  • OKHttp请求网络

    2018-01-03 19:37:14
    首先添加依赖 Utils类: import android.os.Handler; import android.os.Message; import java.io....import okhttp3.Call; import okhttp3.Callback; import okhttp3.OkHttpClient; import okhttp3.Request;

    首先添加依赖

    Utils类:

    import android.os.Handler;
    import android.os.Message;
    
    import java.io.IOException;
    import java.util.Map;
    import java.util.Set;
    
    import okhttp3.Call;
    import okhttp3.Callback;
    import okhttp3.FormBody;
    import okhttp3.Interceptor;
    import okhttp3.OkHttpClient;
    import okhttp3.Request;
    import okhttp3.RequestBody;
    import okhttp3.Response;
    
    
    public class OkHttpUtils {
        private  MyHandler myHandler=new MyHandler();
        private static OkHttpClient okHttpClient=null;
        private OkInterface okInterface;
    
        //单列模式
        public static OkHttpClient getInstance(){
            if (okHttpClient==null){
                okHttpClient=new OkHttpClient();
            }
            return okHttpClient;
        }
    
        //OkHttp get请求
        public void okGet(String url){
            //实例化OkHttpClient
            OkHttpClient client = new OkHttpClient();
            //创建请求对象
            Request request = new Request.Builder().url(url).build();
            //创建请求队列
            Call call = client.newCall(request);
            //开始请求
            call.enqueue(new Callback() {
                //失败
                @Override
                public void onFailure(Call call, IOException e) {
                    Message msg = myHandler.obtainMessage();
                    msg.what=0;
                    msg.obj="失败";
                    myHandler.sendMessage(msg);
                }
                //成功
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    Message msg = myHandler.obtainMessage();
                    msg.what=1;
                    msg.obj=response.body().string();
                    myHandler.sendMessage(msg);
                }
            });
    
        }
    
    
        //OkHttp post请求
        public void okPost(String url,Map<String,String> map){
            //实例化OkHttpClient
            OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new MyInter()).build();
            //创建FormBody
            FormBody.Builder builder = new FormBody.Builder();
            //遍历map
            Set<String> keys = map.keySet();
            for (String key:keys) {
                //取出Value值
                String value = map.get(key);
                //添加到FormBody中
                builder.add(key,value);
            }
            //闭合FormBody
            FormBody body = builder.build();
            //创建请求对象
            Request request = new Request.Builder().url(url).post(body).build();
            //创建请求队列
            Call call = client.newCall(request);
            //开始请求
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    Message msg = myHandler.obtainMessage();
                    msg.what=0;
                    msg.obj="失败";
                    myHandler.sendMessage(msg);
                }
    
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    Message msg = myHandler.obtainMessage();
                    msg.what=1;
                    msg.obj=response.body().string();
                    myHandler.sendMessage(msg);
                }
            });
    
        }
    
        //创建Handler
        class MyHandler extends Handler{
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
    
                switch (msg.what){
                    case 0://失败
                        //获取传递过来的值
                        String  error = (String) msg.obj;
                        //调用接口的方法
                        okInterface.error(error);
                        break;
                    case 1://成功
                        //获取传递过来的值
                        String  json = (String) msg.obj;
                        //调用接口的方法
                        okInterface.success(json);
                        break;
                }
            }
        }
    
        //创建拦截器
        class MyInter implements Interceptor{
            @Override
            public Response intercept(Chain chain) throws IOException {
                //获取原来的body
                Request request = chain.request();
                RequestBody body = request.body();
                if (body instanceof FormBody) {
                    //遍历原来的所有参数,加到新的Body里面,最后将公共参数加到新的Body
                    FormBody.Builder newBuilder = new FormBody.Builder();
                    for (int i = 0; i < ((FormBody) body).size(); i++) {
                        String name = ((FormBody) body).name(i);
                        String value = ((FormBody) body).value(i);
    
                        //放入新的
                        newBuilder.add(name, value);
                    }
                    //在将公共参数添加进去
                    newBuilder.add("source", "android");
                    FormBody newBody = newBuilder.build();
                    //创建新的请求
                    Request newRequest = request.newBuilder().post(newBody).build();
                    Response response = chain.proceed(newRequest);
                    return response;
                }
                return null;
            }
        }
    
        //创建接口
        public interface OkInterface{
            //请求失败的方法
            void error(String error);
            //请求成功的方法
            void success(String json);
        }
    
        //提供外部访问的方法
        public void getOkHttp(OkInterface okInterface){
        this.okInterface=okInterface;
        }
    
    }
    
    
    
    MainActivity类:
     
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Toast;
    import com.example.okhttp.utils.Utils;
    
    public class MainActivity extends AppCompatActivity {
        String uriString="http://www.93.gov.cn/93app/data.do?channelId=0&startNum=0";
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
        //Button的点击事件
        public void bu(View v){
            //实例化
            Utils utils = new Utils();
            //调用解析json的方法
            utils.okhttp(uriString);
            //调用接口的外部方法
            utils.getokhttp(new Utils.HttpGet() {
                //重写的失败的方法
                @Override
                public void error(String error) {
                    Toast.makeText(MainActivity.this,error,Toast.LENGTH_SHORT).show();
    
                }
                //重写成功的方法
                @Override
                public void success(String json) {
                    Toast.makeText(MainActivity.this,json,Toast.LENGTH_SHORT).show();
                }
            });
        }
    }
    


     

    展开全文
  • 实现我介绍Rxjava 加上Okhttp请求方式 首先我们需要导入依赖 compile 'io.reactivex:rxjava:1.0.10' compile 'io.reactivex:rxandroid:1.2.0' compile 'com.google.code.gson:gson:2.8.2' compile '...
  • OkHttp请求耗时统计

    2020-09-23 18:22:59
    目录介绍 01.先提问一个问题 02.EventListener回调原理 03.请求开始结束监听 04.dns解析开始结束监听 ...OkHttp 版本提供了EventListener接口,可以让调用者接收一系列网络请求过程中的事件,例如DNS解析、T
  • 安卓OKhttp请求封装

    2017-05-06 17:20:00
    目前安卓开发中使用的网络工具为OKhttp,但是okhttp的使用还不是很方便,在okhttp的基础上再对请求进行封装会极大的方便网络调用。  下面直接上代码。 请求封装 public class HttpUtil { public static void...
  • 本文作者091-2018Mirs_sir博客:http://my.csdn.net/a109340声明:本文由作者 Mirs_sir 授权发布,未经原作者允许...1.Http请求原理2.OkHttp的简单使用3.OkHttp的初始化4.OkHttp请求流程分析5.OkHttp的请求拦截链6.O
  • OKHttp如何进行同步请求和异步请求?这一切都要从两个官方实例说起: 初始化OkhttpClent OkHttpClient client = new OkHttpClient.Builder() .writeTimeout(10, TimeUnit.SECONDS) .readTimeout...
  • 3.OkHttp请求流程分析

    2017-06-29 12:21:21
    3.OkHttp请求流程分析Call和RealCall经过上面的初始化之后 okhttpClient 调用public Call newCall(Request request) 方法去构建一个Call,“““java @Override public Call newCall(Request request) { return ...
  • OkHttp请求 android 超时时间

    千次阅读 2018-02-02 14:44:53
    增加://okhttpcompile '...import okhttp3.Response; /** * http回调 * Created by gb on 2018/1/18. */ public interface HttpCallInterface { void onSucceedBack(Response r
  • //定义请求码 private static final int REQUEST_CODE = 1; //定义权限信息 String[] permissionArray = { Manifest.permission.WRITE_EXTERNAL_STORAGE }; @Override protected void onCreate...
  • MVP模式OKhttp请求RecyclerView展示数据

    千次阅读 2017-12-11 01:27:08
    这是一个与OKhttp和RecyclerView相关的小demo,可以搜索(此接口只能输入手机或笔记本),切换布局,如果你不明白的话去...demo用MVP模式写成,OKhttp请求数据,RecyclerView展示数据,SpringView实现刷新和加载更多。
  • okhttp请求网络数据

    2018-12-28 00:23:07
    /** * 发送网络请求 * @param url 网络地址 ... ... * @param callback 请求返回 ...包:implementation ... Toast.makeText(MainActivity.this,"post请求成功",Toast.LENGTH_SHORT).show(); } }); } }); } }
  • //okhttp请求 private void loadData() { OkHttpClient mOkHttp = new OkHttpClient.Builder() .connectTimeout( 10 , TimeUnit. SECONDS ) .readTimeout( 20 , TimeUnit. SECONDS ) .build(); Request ...
  • 实现需求的时候用OKhttp请求数据一直报服务器500错误,用postman请求也是这样,但是拼接的网址放浏览器中却能得到json数据…后面代码,postman都换get请求也是失败,最后又排查了各种问题.没有结果问了后端大佬… 加上...
  • 使用OkHttp请求短信验证服务接口 最近在写比赛项目,登录,注册界面可能都会用到短信验证这个功能,其实这个功能后端并不难去实现,我们只需要满足对应服务商规定的API规则,请求接口给指定手机号发送验证码,然后再获取...
  • Android6.0新特性----OKHttp请求

    千次阅读 2015-12-05 18:48:38
    Android6.0新特性----OKHttp请求
  • OKHttp请求https证书验证

    千次阅读 2018-03-15 15:18:00
    * get请求 **/ public void sendGetRepuest (String url, final CallBacks callbacks) { final Request request = new Request.Builder().url(url).build(); client.newBuilder().connectTimeout...
  • 实现需求的时候用OKhttp请求数据一直报服务器500错误,用postman请求也是这样,但是拼接的网址放浏览器中却能得到json数据…后面代码,postman都换get请求也是失败,最后又排查了各种问题.没有结果问了后端大佬… 加上...
  • OkHttp请求工具类

    2016-11-19 12:12:55
    * 分发成功的时候调用 * * @param result * @param callBack */ private void deliverDataSuccess ( final String result, final DataCallBack callBack) { /** * 在这里使用异步线程处理 */...
  • 安卓 OkHttp请求失败的原因及解决

    千次阅读 2021-01-20 16:54:38
    问题: 在 API 30 (Android 10.0+R)平台上编译,使用真机调试,OkHttp在请求网络链接的时候直接onFailure了,但是使用虚拟机却可以请求成功。 原因: Android P以及Android R全面禁止了非https链接,并严格审查网站...
  • OkHttp这个库有多优秀作为...那么,这里简单看个OKHttp的接口请求姿势: OkHttpClient okHttpClient = new OkHttpClient(); Request request = new Request.Builder() .url("https://www.xxxx.com/xxx/xxx...
  • OkHttp请求数据的方法

    2016-09-07 08:56:55
    //创建okHttpClient对象 OkHttpClient mOkHttpClient = new OkHttpClient(); //创建一个Request final Request request = new Request.Builder() .url("path") .build();...com.squareup.okhttp.Ca
  • 在客户端用于访问服务器去提交请求, 在从服务器获取响应的类 GET方式 步骤: 1, 得到URL对象  URL url = new URL("path......"); 2, 根据URL对象打开HttpUrlConnection对象  HttpUrlConne
  • Okhttp请求封装

    2018-11-26 17:09:29
    /* OkHttp请求框架*/ implementation 'com.squareup.okhttp3:okhttp:3.10.0' 1.接口封装,我只写了post的json请求,post的表单请求,get请求 public class HttpUtil { /** * post请求 * @param s,接口 * @...
  • 简单的OkHttp 网络请求(成功方法) import android.os.Handler; import android.os.Message; import java.io.IOException; import okhttp3.Call; import okhttp3.Callback; import okhttp3.OkHttpClient; ...
  • 请求成功后,我的获取json代码如下: response.body().string().  然后我又在下边打印了Log查看结果: Log.i("TAG", response.body().string().) 因为OkHttp请求回调中response.body().string()只能有效...
  • 安卓:okhttp请求,获取返回数据

    千次阅读 2019-11-21 13:04:04
    要引入okhttp.jar private void HttpResponse(String url, final TextView textView) { OkHttpClient client = new OkHttpClient(); Request request = new Request .Build...
  • OkHttp请求网络数据,并listview展示

    千次阅读 2017-10-18 15:29:42
    OkHTTP使用前步骤: 第一步:导入依赖: compile 'com.squareup.okio:okio:1.5.0' compile 'com.squareup.okhttp3:okhttp:3.2.0' compile 'com.squareup.okhttp3:logging-interceptor:3.4.1' ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,229
精华内容 5,291
关键字:

okhttp请求成功后的