那些年我用过的Android网络请求库

下面是我使用过的网络框架,每种框架都有自己的优点缺点,要更具自身的应用场景选择。

测试使用一个ip地址查询接口进行测试:http://ip.tianqiapi.com?ip=xxx.xxx.xxx.xxx。
在Android中请求网络时要注意几点问题:
1.权限 :<uses-permission android:name="android.permission.INTERNET"/>
2.不能在主线程请求网络,将报错。
3.不能在子线程操作UI,将报错。
4.为了保证数据安全,在Android P 不能使用http,要更改为https,但是可以通过在AndroidManifest.xml文件中application标签增加 android:usesCleartextTraffic="true"来避免强制https,当然还有其他办法,不止一种,但一种足矣。(还是推荐自己的服务升级为https)。

一、HttpURLConnection

要说第一还是当属HttpURLConnection,在java阶段学习网络编程时从他开始。

首先是构建URL,通过URL打开HttpURLConnection,在使用IO流读取数据,这是最基本的操作了。可以更具setRequestMethod(“GET”)来修改请求类型。其他类型的操作也十分麻烦。

 @Override
 protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);
     new Thread() {
         @Override
         public void run() {
             super.run();
             doHttpURLConnection("http://ip.tianqiapi.com?ip=39.156.66.18");
         }
     }.start();
 }
private void doHttpURLConnection(String u){
    try {
        URL url =new URL(u);
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
        urlConnection.setRequestMethod("GET");
        InputStreamReader inputStreamReader =new InputStreamReader(urlConnection.getInputStream());
        BufferedReader bufferedReader =new BufferedReader(inputStreamReader);
        String temp="";
        StringBuffer stringBuffer =new StringBuffer();
        while ((temp=bufferedReader.readLine())!=null){
         stringBuffer.append(temp);
        }
        Log.i(TAG, "doHttpURLConnection: "+stringBuffer);
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

二、Okhttp

接下来是Okhttp,非常火的一个网络库,由Square公司提供。有很多优点,如利用响应缓存来避免重复的网络请求、拥有拦截器等,地址:https://github.com/square/okhttp。

首先是引入他,最新的是4.3.1。

 implementation("com.squareup.okhttp3:okhttp:4.3.1")

API非常好用,首先是构建OkHttpClient,全局只需要初始化一次即可,可以通过内部构建对象Builder设置参数,如读取超时时间,接着通过Request.Builder()构建请求对象,如果是Get请求,则直接使用.get(),如果是Post请求,则使用.post(RequestBody),里面还要传入RequestBody对象,可以通过RequestBody的静态方法create创建,也可以使用他的子类,如FormBody。

Okhttp请求分为同步和异步,如果是同步的话,使用OhttpClitent.execute(),如果是异步,则要使用enqueue(),并传入回调地址。

Callback是回调接口,包括两个方法,失败回调onFailure和成功回调onResponse,通过response.body()可以拿到响应对象ResponseBody,最简单通过ResponseBody.string方法转换成string,不是toString()!!!,如果响应头中没有Content Type,则使用UTF8编码,否则使用指定编码,但是要注意的是,string方法只能调用一次,调用之后Okhttp会释放资源,所以第二次调用会报错。如果响应对象过大,可能引起OutOfMemoryError

 private void dpOkHttp(String u){
     OkHttpClient httpClient =new OkHttpClient();
     FormBody body =new FormBody.Builder().build();
     Request request =new Request.Builder()
             .url(u)
             .post(body)
             .build();
     String string = null;
     //同步
     try {
         string = httpClient.newCall(request).execute().body().string();
         Log.i(TAG, "dpOkHttp: "+string);
     } catch (IOException e) {
         e.printStackTrace();
     }
     
     //异步
     httpClient.newCall(request).enqueue(new Callback() {
         @Override
         public void onFailure(@NotNull Call call, @NotNull IOException e) {
         }
         @Override
         public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
             Log.i(TAG, "onResponse: "+response.body().string());
         }
     });
 }

三、okhttputils

这是张鸿洋大神封装的Okhttp库,以前写demo的时候经常用,使用也很简单。具体详细使用可以查看https://github.com/hongyangAndroid/okhttputils。注意版本要对应。

implementation 'com.zhy:okhttputils:2.6.2'
implementation("com.squareup.okhttp3:okhttp:3.3.1")
private  void doOkhttpUtil(String u){
    OkHttpClient httpClient =new OkHttpClient.Builder()
            .build();
    OkHttpUtils.initClient(httpClient);
    OkHttpUtils.get()
            .url(u)
            .build()
            .execute(new StringCallback() {
                @Override
                public void onError(Call call, Exception e, int id) {
                    e.printStackTrace();
                }
                @Override
                public void onResponse(String response, int id) {
                    Log.i(TAG, "onResponse: "+response);
                }
            });
}

四、Volley

在Goole I/O 2013上发布的网络通信库,优点是自动调度网络请求、支持请求优先级、支持取消请求,可以取消单个请求或多个,等,场合在数据不大但通信频繁的情况下,jar包体积非常小,并且Volley回调时候是在主线程,可以直接操作UI,okhttputils也是在主线程,但是Okhttp不是,需要通过Handler处理。缺点也有,如文件下载和图片加载一般。

这个可以到https://developer.android.google.cn/training/volley详细查看。

首先是构建RequestQueue请求列队,全局也只初始化一次就好,接着构建Request请求对象,有StringRequest、ImageRequest、ClearCacheRequest、JsonRequest这四个子类。可以给Request设置一个tag,并通过RequestQueue.cancelAll(tag)可以进行取消。`

implementation 'com.android.volley:volley:1.1.1'
 private void doVolley(String u) {
     RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
     StringRequest stringRequest = new StringRequest(Request.Method.GET,u, new Response.Listener<String>() {
         @Override
         public void onResponse(String response) {
             Log.i(TAG, Thread.currentThread().getName()+" onResponse: " + response);
         }
     }, new Response.ErrorListener() {
         @Override
         public void onErrorResponse(VolleyError error) {
         }
     });
     stringRequest.setTag("tag");
     Request<String> request = requestQueue.add(stringRequest);
     requestQueue.cancelAll("tag");
 }

五、Retrofit

首先这是Square公司的,也是基于Okhttp扩展,最终网络请求由Okhttp完成,而Retrofit负责请求接口的封装。我现在一直在用这个。

他的地址https://square.github.io/retrofit/或https://github.com/square/retrofit

Retrofit全程操作依靠注解和接口来完成,写法不同于上面四种,非常有风格。

implementation("com.squareup.okhttp3:okhttp:3.3.1")
implementation 'com.squareup.retrofit2:retrofit:2.7.1'

首先创建一个接口,返回值在Call< T>中,@GET("/")表示请求路径,@Query是参数,也就是?后面的数据

public interface Apis {
    @GET("/")
    Call<ResponseBody> getIpAddress(@Query("ip")String ip);
}

接着就可以用以下方式请求了,其中Retrofit和Apis也不用每次请求都创建,create使用动态代理返回一个代理Apis的对象。构建Retrofit时候要通过baseUrl指明主机地址,请求时会拼接上@Get、@Post等中的值。

  private void doRetrofit(String u) {
      OkHttpClient okHttpClient = new OkHttpClient();
      Retrofit retrofit = new Retrofit.Builder()
              .client(okHttpClient)
              .baseUrl("http://ip.tianqiapi.com/")
              .build();
      Apis apis = retrofit.create(Apis.class);
      apis.getIpAddress("39.156.66.18").enqueue(new retrofit2.Callback<ResponseBody>() {
          @Override
          public void onResponse(retrofit2.Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
              try {
                  Log.i(TAG, "onResponse: " + response.body().string());
              } catch (IOException e) {
              }
          }
          @Override
          public void onFailure(retrofit2.Call<ResponseBody> call, Throwable t) {
          }
      });
  }

还要很多注解:
请求方式注解:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、HTTP
标记注解:FormUrlEncoded、Multipart、Streaming
参数类注解:Headers、Header、Body、Field、FieldMap、Part、PartMap、Query、QueryMap、Path
配合这些注解可以完成文件上传,Post提交json等请求。

更实用的是转换器,通过他可以把json字符串转换成对象。如果没有转换器,返回值必须一律是ResponseBody。
引入依赖,内部使用com.google.gson处理。

implementation 'com.squareup.retrofit2:converter-gson:2.4.0'

IpAddress。

public class IpAddress {
    private String ip;
    private String country;
    private String province;
    private String city;
    private String isp;

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getIsp() {
        return isp;
    }

    public void setIsp(String isp) {
        this.isp = isp;
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    @Override
    public String toString() {
        return "IpAddress{" +
                "ip='" + ip + '\'' +
                ", country='" + country + '\'' +
                ", province='" + province + '\'' +
                ", city='" + city + '\'' +
                ", isp='" + isp + '\'' +
                '}';
    }
}

修改返回值。

public interface Apis {
    @GET("/")
    Call<IpAddress> getIpAddress(@Query("ip")String ip);
}
 private void doRetrofit(String u) {

        OkHttpClient okHttpClient = new OkHttpClient();

        Retrofit retrofit = new Retrofit.Builder()
                .client(okHttpClient)
                .baseUrl(u)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        Apis apis = retrofit.create(Apis.class);
        apis.getIpAddress("39.156.66.18").enqueue(new retrofit2.Callback<IpAddress>() {
            @Override
            public void onResponse(retrofit2.Call<IpAddress> call, retrofit2.Response<IpAddress> response) {
                Log.i(TAG, "onResponse: " + response.body().toString());

            }

            @Override
            public void onFailure(retrofit2.Call<IpAddress> call, Throwable t) {
                t.printStackTrace();
            }
        });
    }

输出如下,非常的方便
在这里插入图片描述

发布了42 篇原创文章 · 获赞 7 · 访问量 7741

猜你喜欢

转载自blog.csdn.net/HouXinLin_CSDN/article/details/104353766