Android网络请求相关

1.网络基本知识

1.1 网络分层

1.1.1物理层负责比特流在节点之间的传输
1.1.2 数据链路层 吧不可靠的物理线路上进行数据的可靠传递
1.1.3 网络层决定如何将数据从发送方到接收方
1.1.4 传输层进行端到端的通信 这上面有Tcp和Udp协议
1.1.5应用层 主要协议是HTTP 和FTP 等协议

1.2 三次握手与四次挥手

1.2.1 三次握手
第一次握手:建立连接 客户发送请求报文字段将SYN设置为1,seq设置为x 接下来客户端进入SYN_SENT状态,等待服务器
第二次握手:服务器收到客户端的SYN报文对SYN报文进行确认,设置ACK为x+1同时发送SYN设置为1 seq为y 将上述信息放到SYN+ACK中发给客户端此时进入SYN_RCVD状态
第三次握手客户端收到服务器端SYN+ACK 将ACK设置为y+1向服务端发送ACK报文

1.3.1 四次挥手

第一次挥手 客户端设置seq为ACK 向服务端发送一个FIN报文,
第二次挥手服务端接收到FIN字段 向客户端回了一个ACK报文
第三次服务端向客户发FIN报文请求关闭连接
第四次 客户端接受到服务端发送的FIN报文段,向服务端发送ACK报文然后进入等待状态 等待久了就关闭自己了

2.Volley解析

Volley是一个google官方的网络通信框架,设计是适合数据量不大,但是通信频繁的网络操作,对于下载文件等 表现会比较差
2.1 Volley使用方法
(1)下载Volley jar包 放到AndroidStudio工程下面 导入jar包
(2)开始使用
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
        StringRequest stringRequest = new StringRequest(Request.Method.GET, "www.baidu.com", new Response.Listener<String>() {
            @Override
            public void onResponse(String s) {
                //成功会掉
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {

            }
        });
        requestQueue.add(stringRequest);



   private void loadJson() {

        RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
        JSONObject paramJsonObject = new JSONObject();//传参数

        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest("www.baidu.com", paramJsonObject, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject jsonObject) {

            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {

            }
        });
        requestQueue.add(jsonObjectRequest);
    }

2.2Volley框架源码解析

我们从new RequestQueue入手

public class Volley {
    private static final String DEFAULT_CACHE_DIR = "volley";

    public Volley() {
    }

    public static RequestQueue newRequestQueue(Context context, BaseHttpStack stack) {
        BasicNetwork network;
        if (stack == null) {
            if (VERSION.SDK_INT >= 9) {
                network = new BasicNetwork(new HurlStack());
            } else {
                String userAgent = "volley/0";

                try {
                    String packageName = context.getPackageName();
                    PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
                    userAgent = packageName + "/" + info.versionCode;
                } catch (NameNotFoundException var6) {
                    ;
                }

                network = new BasicNetwork(new HttpClientStack(AndroidHttpClient.newInstance(userAgent)));
            }
        } else {
            network = new BasicNetwork(stack);
        }

        return newRequestQueue(context, (Network)network);
    }

    /** @deprecated */
    @Deprecated
    public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
        return stack == null ? newRequestQueue(context, (BaseHttpStack)null) : newRequestQueue(context, (Network)(new BasicNetwork(stack)));
    }

    private static RequestQueue newRequestQueue(Context context, Network network) {
        File cacheDir = new File(context.getCacheDir(), "volley");
        RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
        queue.start();
        return queue;
    }

    public static RequestQueue newRequestQueue(Context context) {
        return newRequestQueue(context, (BaseHttpStack)null);
    }
}
其实就判断当前版本大于9还是小于9小于就创建HttpClient大于就创建HttpURLConnection并调用start方法 我们来看start方法
public void start() {
        this.stop();
        this.mCacheDispatcher = new CacheDispatcher(this.mCacheQueue, this.mNetworkQueue, this.mCache, this.mDelivery);
        this.mCacheDispatcher.start();

        for(int i = 0; i < this.mDispatchers.length; ++i) {
            NetworkDispatcher networkDispatcher = new NetworkDispatcher(this.mNetworkQueue, this.mNetwork, this.mCache, this.mDelivery);
            this.mDispatchers[i] = networkDispatcher;
            networkDispatcher.start();
        }

    }
其实就是开启 几个线程 一个是缓存调度线程 四个网络请求线程 一共五个线程在后台运行 按照Volley的使用流程 后面就是讲request加入到队列中去我们看 add方法
public <T> Request<T> add(Request<T> request) {
        request.setRequestQueue(this);
        Set var2 = this.mCurrentRequests;
        synchronized(this.mCurrentRequests) {
            this.mCurrentRequests.add(request);
        }

        request.setSequence(this.getSequenceNumber());
        request.addMarker("add-to-queue");
        if (!request.shouldCache()) {
            this.mNetworkQueue.add(request);
            return request;
        } else {
            this.mCacheQueue.add(request);
            return request;
        }
    }
判断是否需要缓存 如果不需要缓存 直接走mCacheQueue线程,如果需要缓存走mNetworkQueue 线程
mCacheQueue 线程其实就是一个线程维护缓存管理的,代码如下,其实主要就是判断有没有缓存 如果有缓存 取缓存的数据,如果有缓存但是过期了 那么就去请求,没有过期就响应
private void processRequest() throws InterruptedException {
        final Request<?> request = (Request)this.mCacheQueue.take();
        request.addMarker("cache-queue-take");
        if (request.isCanceled()) {
            request.finish("cache-discard-canceled");
        } else {
            Entry entry = this.mCache.get(request.getCacheKey());
            if (entry == null) {
                request.addMarker("cache-miss");
                if (!this.mWaitingRequestManager.maybeAddToWaitingRequests(request)) {
                    this.mNetworkQueue.put(request);
                }

            } else if (entry.isExpired()) {
                request.addMarker("cache-hit-expired");
                request.setCacheEntry(entry);
                if (!this.mWaitingRequestManager.maybeAddToWaitingRequests(request)) {
                    this.mNetworkQueue.put(request);
                }

            } else {
                request.addMarker("cache-hit");
                Response<?> response = request.parseNetworkResponse(new NetworkResponse(entry.data, entry.responseHeaders));
                request.addMarker("cache-hit-parsed");
                if (!entry.refreshNeeded()) {
                    this.mDelivery.postResponse(request, response);
                } else {
                    request.addMarker("cache-hit-refresh-needed");
                    request.setCacheEntry(entry);
                    response.intermediate = true;
                    if (!this.mWaitingRequestManager.maybeAddToWaitingRequests(request)) {
                        this.mDelivery.postResponse(request, response, new Runnable() {
                            public void run() {
                                try {
                                    CacheDispatcher.this.mNetworkQueue.put(request);
                                } catch (InterruptedException var2) {
                                    Thread.currentThread().interrupt();
                                }
                            }
                        });
                    } else {
                        this.mDelivery.postResponse(request, response);
                    }
                }
            }
        }
    }
mNetworkQueue这个线程就是网络请求线程 主要是调用网络请求方法,将返回的数据刷新到缓存之中,
private void processRequest() throws InterruptedException {
        Request<?> request = (Request)this.mQueue.take();
        long startTimeMs = SystemClock.elapsedRealtime();

        try {
            request.addMarker("network-queue-take");
            if (request.isCanceled()) {
                request.finish("network-discard-cancelled");
                request.notifyListenerResponseNotUsable();
                return;
            }

            this.addTrafficStatsTag(request);
            NetworkResponse networkResponse = this.mNetwork.performRequest(request);
            request.addMarker("network-http-complete");
            if (networkResponse.notModified && request.hasHadResponseDelivered()) {
                request.finish("not-modified");
                request.notifyListenerResponseNotUsable();
                return;
            }

            Response<?> response = request.parseNetworkResponse(networkResponse);
            request.addMarker("network-parse-complete");
            if (request.shouldCache() && response.cacheEntry != null) {
                this.mCache.put(request.getCacheKey(), response.cacheEntry);
                request.addMarker("network-cache-written");
            }

            request.markDelivered();
            this.mDelivery.postResponse(request, response);
            request.notifyListenerResponseReceived(response);
        } catch (VolleyError var6) {
            var6.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs);
            this.parseAndDeliverNetworkError(request, var6);
            request.notifyListenerResponseNotUsable();
        } catch (Exception var7) {
            VolleyLog.e(var7, "Unhandled exception %s", new Object[]{var7.toString()});
            VolleyError volleyError = new VolleyError(var7);
            volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs);
            this.mDelivery.postError(request, volleyError);
            request.notifyListenerResponseNotUsable();
        }
    }
最后执行了ResponseDeliveryRunnable这个线程 这个线程就是将结果返回回去 我们直接看正确的结果返回
private static class ResponseDeliveryRunnable implements Runnable {
        private final Request mRequest;
        private final Response mResponse;
        private final Runnable mRunnable;

        public ResponseDeliveryRunnable(Request request, Response response, Runnable runnable) {
            this.mRequest = request;
            this.mResponse = response;
            this.mRunnable = runnable;
        }

        public void run() {
            if (this.mRequest.isCanceled()) {
                this.mRequest.finish("canceled-at-delivery");
            } else {
                if (this.mResponse.isSuccess()) {
                    this.mRequest.deliverResponse(this.mResponse.result);
                } else {
                    this.mRequest.deliverError(this.mResponse.error);
                }

                if (this.mResponse.intermediate) {
                    this.mRequest.addMarker("intermediate-response");
                } else {
                    this.mRequest.finish("done");
                }

                if (this.mRunnable != null) {
                    this.mRunnable.run();
                }

            }
        }
    }
最终点进去后会发现调用了request子类的监听器回调到给了子线程
  protected void deliverResponse(String response) {
        Object var3 = this.mLock;
        Listener listener;
        synchronized(this.mLock) {
            listener = this.mListener;
        }

        if (listener != null) {
            listener.onResponse(response);
        }

    }

3.okHttp解析

3.1okHttp基础使用
简单来说就是 用建造模式创建一个request 然后用httpClient创造一个call出来 然后执行call的两个接口回调
 Request.Builder requestBuilder = new Request.Builder().url("www.baidu.com");
        requestBuilder.method("GET",null);
        Request request = requestBuilder.build();
        OkHttpClient okHttpClient = new OkHttpClient();
        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 {
            }
        });

3.2 封装OkHttp

(1)写一个请求回调,用单例模式创建一个 然后传入地址 创建一个request生成一个call 调用call 回调响应的数据
public class OkHttpEngine {
    private static volatile OkHttpEngine mInstance;
    private OkHttpClient mOkHttpClient;
    private Handler mHandler;


    public static OkHttpEngine getInstance(Context context) {
        if (mInstance == null) {

            synchronized (OkHttpEngine.class) {
                if (mInstance == null) {
                    mInstance = new OkHttpEngine(context);
                }
            }

        }
        return mInstance;
    }


    private OkHttpEngine(Context context) {
        File externalCacheDir = context.getExternalCacheDir();
        int cacheSize = 10 * 1024 * 1024;
        OkHttpClient.Builder builder = new OkHttpClient.Builder().connectTimeout(15, TimeUnit.SECONDS).writeTimeout(20, TimeUnit.SECONDS).readTimeout(10, TimeUnit.SECONDS).cache(new Cache(externalCacheDir.getAbsoluteFile(), cacheSize));
        mOkHttpClient = builder.build();
        mHandler = new Handler();
    }
    public void getAsynHttp(String url, ResultCallBack callBack) {
        Request request = new Request.Builder().url(url).build();
        Call call = mOkHttpClient.newCall(request);
        dealResult(call, callBack);
    }
    public void dealResult(Call call, final ResultCallBack callBack) {
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //失败的
            }  @Override
            public void onResponse(Call call, Response response) throws IOException {
                sendSuccessCallback(response.body().toString(), callBack);
            }
        });
    }
    public void sendSuccessCallback(final String str, final ResultCallBack callBack) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (callBack != null) {
                    try {
                        callBack.onResponse(str);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }
}

3.3 okHttp源码解析

请参考更加详细的文章地址https://blog.csdn.net/a820703048/article/details/86829476

4Retrofit

Retrofit 底层是基于OkHttp它更多的是运用运行时注解的方式提供功能
4.1Retrofit 的基本使用
4.1.1 注解
注解分为三大类分别是Http请求方法注解、标记类注解、参数类注解。其中Http类注解有POST GET DELETE HEAD PATCH OPTIONS HTTP 标记类注解有比如FromUrlEncoded Multipart Streaming
4.1.2基础使用教程
 Retrofit build = new Retrofit.Builder().baseUrl("wwww.huya.com").build();
        IpService ipService = build.create(IpService.class);
        Call<IpData> call = ipService.getIpData();
        call.enqueue(new Callback<IpData>() {
            @Override
            public void onResponse(Call<IpData> call, Response<IpData> response) {
                
            }

            @Override
            public void onFailure(Call<IpData> call, Throwable t) {

            }
        });
public interface IpService {
    @GET("www.baidu.com")
    Call<IpData> getIpData();
}
4.1.3注解分解
HTTP前面几个比较容易懂的就不解释了
(1)动态配置@Path 就是将字符串拼接起来
 @GET("{path}/getinfo")
    Call<IpData> getIpMsg(@Path("path") String path);
(2)动态查询条件@Query
 @GET("getInfo")
    Call<IpData> getData(@Query("ip") String ip);
(3) 动态查询QueryMap
 @GET("getInfo")
    Call<IpData> getIPMsg(@QueryMap Map<String,String> options);
(4)传输类型为键值对 @Field @FormUrlEncoded是表明这个是一个表单请求
    @FormUrlEncoded
    @POST
    Call<IpData> postMsg(@Field("ip")String ip);
(5)用Post方式将JSON字符串作为请求体送到服务器@body
@POST("getinfo")
    Call<IpData> postmsg(@Body IpData data);
(6) 单个文件上传 @Part
@Multipart
    @POST("user/photo")
    Call<IpData> update(@Part MultipartBody.Part photo);
(7) 消息头Header为 给请求加入请求头 如果想要加入多个就用{}把它们包裹起来
  @GET("some/end")
    @Headers("Accept-Encoding:application/json")
    Call<IpData> getCarType();
(8)Header用动态的形式加入进去
    @GET("some")
    Call<IpData> gethost(@Header("Location") String location);

4.2 源码解析Retrofit

 Retrofit build = new Retrofit.Builder()
Retrofit 我们通过Builder来创建Retrofit线程池然后我们查看build方法
static class Android extends Platform {
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

    static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }
我们看build的源代码
  public Retrofit build() {
      if (baseUrl == null) {//地址不能为空 
        throw new IllegalStateException("Base URL required.");
      }

      okhttp3.Call.Factory callFactory = this.callFactory; //转换工厂
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      Executor callbackExecutor = this.callbackExecutor;//用来将回调传递到ui线程
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      //用于存储对call转化对象
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      // Make a defensive copy of the converters.//用于存储转发数据对象
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
    }

我们来看create方法的创建过程
 public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            // If the method is a method from Object then defer to normal invocation.
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }
其实是使用了代理对象 第一个参数是代理对象 第二个是调用的方法 第三个是方法参数 我们看一下 loadSerivceMethod方法做了什么
  ServiceMethod<?, ?> loadServiceMethod(Method method) {
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = new ServiceMethod.Builder<>(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }
判断serviceMethodCache查询传入方法是否有缓存 如果有就用缓存的serviceMethod如果没有就创建一个加入serviceMethodCache缓存起来
    public ServiceMethod build() {
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      if (responseType == Response.class || responseType == okhttp3.Response.class) {
        throw methodError("'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
      }
      responseConverter = createResponseConverter();

      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }

      if (httpMethod == null) {
        throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
      }

      if (!hasBody) {
        if (isMultipart) {
          throw methodError(
              "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
        }
        if (isFormEncoded) {
          throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
              + "request body (e.g., @POST).");
        }
      }

      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        if (Utils.hasUnresolvableType(parameterType)) {
          throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
              parameterType);
        }

        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        if (parameterAnnotations == null) {
          throw parameterError(p, "No Retrofit annotation found.");
        }

        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }

    
      return new ServiceMethod<>(this);
    }
Retrofit 的build代码如下
    public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
    }
adapterFactories列表默认会添加defaultCallAdapterFactory这个是ExecutorCallAdapterFactory 看它的get方法
 @Override
  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public Call<Object> adapt(Call<Object> call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }

###最终调用了enqueue 方法解析响应

 call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response<T> response;
        try {
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
        callSuccess(response);
      }
toResponse 方法如下 responseConverter就是此前降到的createResponseConverter返回的Converter ,GsonConverterFactory中有一个方法叫responseBodyConverter,它最终创建GsonResponseBodyConverter,这其中convert方法会将回调的数据转为JSON格式,我们也知道此前调用的responseConverter.convert是为了转为特定的数据格式,call的enqueque方法主要是做okHttp的网络请求返回的Response进行数据转换并回调给UI线程
 R toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值