android网络请求

工具包配置:OKHttp,Retrofit,gson

用到上面这几个工具包,Okhttp是发送网络请求的,Retrofit是基于okhttp,使用更方便,gson是用来解析json请求数据。
要先配置:

    implementation("com.squareup.okhttp3:okhttp:4.1.0")
    implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
     implementation 'com.squareup.retrofit2:retrofit:2.6.1' // 必要retrofit依赖
    implementation 'com.squareup.retrofit2:converter-gson:2.6.1' // 必要依赖,解析json字符所用
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.6.1'// 必要依赖,和Rxjava结合必须用到,提一下,暂时不说这个

记得添加网络权限

OkHttp的使用:

1.获取okHttpClient对象
2.创建RequestBody(当使用post请求时需要这一步,get请求不需要)
3.构建Request对象
4.构建Call对象
5.通过Call.enqueue(callback)方法来提交异步请求;execute()方法实现同步请求

  • 案例(只说post请求,get请求不写RequestBody类,然后request构建时.post换成.get即可):

参数的设置:
1.formbody:是提交表单数据,post请求,不会拼在url中
2. requestBody:是作为消息正文发送,可以把字符串、xml、json转到body中发送
3. addHeader: 是在请求头中添加参数

    public void okHttpTest(){
        //创建对象
        OkHttpClient client = new OkHttpClient();
        //formbody是提交表单数据,post请求,不会拼在url中
        FormBody formBody = new FormBody.Builder()
                .add("Id","108820004")
                .build();
        //requestBody是作为消息正文发送,可以把字符串、xml、json转到body中发送
        RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain;charset=utf-8"),"108820004");
        Request request = new Request.Builder()
        //addHeader是在请求头中添加参数
                .url("http://120.224.69.6:81/api/de/GetCountryList/") .addHeader("u","A6E95CE7366AD705996A6B4124EDAA8#ADAF8171A8552D5DCFA2EC374D638BA")			
                //这两个post是指定post请求,formbody和requestbody封装了需要传递的参数,如果使用get请求就换成.get()
                .post(formBody)
                .post(requestBody)
                .build();
        Call call = client.newCall(request);
        //发送请求
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {//请求失败
                Log.d(TAG, "onFailure: ");
            }
            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
            //请求成功
                Log.d(TAG, "onResponse: "+response);
            }
        });
    }

注意:请求是异步请求时,请求是在子线程中进行的,如果接下来的动作需要用到请求返回的数据,那就必须放在onResponse中进行,否则数据错乱。

参考:OkHttp详解

Retrofit的使用:

Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装。网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责 网络请求接口的封装
使用步骤:

  1. 创建 接收服务器返回数据 的类
    根据返回数据的字段来设计接收类
  2. 创建 用于描述网络请求 的接口
    一般定义一个用于封装的接口,然后把所有的请求接口都封装在这个接口中
  3. 为每一个请求设计接口,指定返回数据类型和参数,在创建请求时调用retrofit的create方法会自动根据接口生成实现类
    这里用到各种注解:
  • @POST,post请求,括号里写请求地址名
  • @Headers,指定编码方式,指定content-Type
  • @FormUrlEncoded,当提交表单参数时加该注解,参数名使用@Field注解
  • @Header,参数名的注解,作为消息头发送
  • @Body,作为消息正文发送,这个注解的参数是一个类,可以使用自定义实体类,里面封装各种参数(当参数比较多时可以这样用),也可以使用Okhttp的RequestBody类,这个类可以把字符串、xml文件、json等作为正文发送。这里要注意,当使用@Body的时候不要用@FormUrlEncoded

这里提一下遇到的一个巨坑,后台有一个参数是作为正文发送,而且没有参数名,只有值,当时搞得贼蛋疼,这里就用到RequestBody的功能了,把这个参数值前面加上等号作为字符串交给RequestBody就解决了,但是要记得参数名不要等号也得要加。

 	@FormUrlEncoded
    @Headers("Content-Type:application/x-www-form-urlencoded; charset=utf-8")
    @POST("User/UserLoginP")
    Call<Response<LoginBean>> getCall(@Field("account") String account, @Field("password") String password);
    
    @Headers("Content-Type:application/x-www-form-urlencoded; charset=utf-8")
    @POST("de/GetCountryList/")
    Call<ArrayResponse<AreaBean>> getCountryList(@Header("u") String u, @Body RequestBody id);
  1. 创建 Retrofit 实例
 Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(RequestInterface.HOST)
                //设置json解析器
                .addConverterFactory(GsonConverterFactory.create())
                .build();
  1. 创建 网络请求接口实例 并 配置网络请求参数
//创建网络请求接口实例
        RequestInterface request = retrofit.create(RequestInterface.class);
  1. 发送网络请求(异步 / 同步)

案例:

    /**
     * 发送请求,获取某个镇里的所有村,镇的id为参数
     */
    private void getVillageRequest(final Integer Id) {
        Log.d(TAG, "getVillageRequest: 获取村数据列表请求");
        //创建Retrofit对象
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(RequestInterface.HOST)
                //设置json解析器
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        //创建网络请求接口实例
        RequestInterface request = retrofit.create(RequestInterface.class);
        //对发送请求进行封装,参数是镇的id,无参数名,但是要有等号
        RequestBody id = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded;charset=utf-8"), "=" + Id.toString());
        Call<ArrayResponse<AreaBean>> call = request.getCountryList(SessionManager.getToken(), id);
        //发送请求,异步
        call.enqueue(new Callback<ArrayResponse<AreaBean>>() {
            //请求成功时回调
            @Override
            public void onResponse(Call<ArrayResponse<AreaBean>> call, retrofit2.Response<ArrayResponse<AreaBean>> response) {
                //处理返回的数据结果
                Log.d(TAG, "onResponse: 返回结果:" + response);
                Log.d(TAG, "onResponse: 村列表请求信息数据:" + response.body());
                ArrayResponse<AreaBean> mResponse = response.body();
                countryList = mResponse.getData();
/**
 *                 下面的村庄适配器的设置必须是村庄数据接收完成后才能进行,必须放在这一块代码中执行,之前放在TownClickListener的onItemSelected方法里请求下面,
 *                 这样会导致数据错误,有可能切换镇的时候村庄列表还是上一个镇的数据,因为请求是在子线程中进行的,在镇的监听器中是另一个线程,这是造成这个bug的原因
 */
                loadVillage(countryList);
                Log.d(TAG, "onResponse: 村列表:" + Arrays.toString(countryList));
                Log.d(TAG, "onItemSelected: 设置村级列表适配器,村列表数量:" + villageList.size());
                villageSpinnerAdapter = new SpinnerAdapter(VideoMonitorActivity.this, villageList, Id % 10000);
                village.setAdapter(villageSpinnerAdapter);
            }

            //请求失败时回调
            @Override
            public void onFailure(Call<ArrayResponse<AreaBean>> call, Throwable t) {
                Log.d(TAG, "onFailure: 连接失败原因:" + t.getMessage());
                ToastUtil.showMsg(VideoMonitorActivity.this, "连接失败");
            }
        });
    }

你可能感兴趣的:(学习日志,Okhttp,Retrofit,网络请求)