post方式发送json格式的网络请求(基于Retrofit2)

笔者最近用图灵V2版本,V2跟V1版比起来,很大的区别是网络请求,V1版只需一条网址链接即可请求数据,V2版本则需要以请求参数格式为 json的post请求数据,无疑增大了难度
打开图灵官网API V2.0接入文档

文档给我们提供了请求示例和返回示例,看着数据十分复杂,复杂的数据就不必用android原生的json解析方式了,因为很容易出错。这里用谷歌的神器gson以及它的插件GsonFormat(用来生成json数据对应的javabean)
请求示例:

{
	"reqType":0,
    "perception": {
        "inputText": {
            "text": "附近的酒店"
        },
        "inputImage": {
            "url": "imageUrl"
        },
        "selfInfo": {
            "location": {
                "city": "北京",
                "province": "北京",
                "street": "信息路"
            }
        }
    },
    "userInfo": {
        "apiKey": "",
        "userId": ""
    }
}

根据你的用途,选择你需要的数据,比如说我根本不需要图片聊天和定位,那我可以删掉上面的

  "inputImage": {
            "url": "imageUrl"
        },
        "selfInfo": {
            "location": {
                "city": "北京",
                "province": "北京",
                "street": "信息路"
            }
        }

然后把剩下的json数据复制,在项目里建立一个javabean类,名字就叫Ask.class吧,表示
发送数据实体类,根据发送给图灵api的json,使用GsonFormat工具生成请求数据实体类Ask(请求体)
给Android Studio安装好Gsonformat,在建好的Ask.class里按alt+s,把json数据示例复制进去,点击ok即可生成对应代码,这个Ask.class就搞定了
打开谷歌浏览器的postman插件,测试一下发送数据给图灵api,看有没有返回数据,text里面自己写想跟图灵聊的内容,apiKey和userId要上图灵官网自取
post方式发送json格式的网络请求(基于Retrofit2)_第1张图片

点击Send得到返回数据
post方式发送json格式的网络请求(基于Retrofit2)_第2张图片
然后把返回的数据复制一下,建立一个Take.class,作为接收的Json数据实体类,然后用把这些返回数据复制到GsonFormat里生成代码就好啦。
接下来,咱们就要进行写代码进行网络请求了,这里用retrofit2网络框架,它结合了gson和okHttp3,是个集网络请求和数据处理的强大工具,具体使用可以看Android:手把手带你深入剖析 Retrofit 2.0 源码和
这是一份很详细的 Retrofit 2.0 使用教程(含实例讲解)
在build.gradle里添加依赖

//    Retrofit
    //    retrofit
    implementation 'com.squareup.okhttp3:okhttp:3.1.2'
    implementation 'com.squareup.retrofit2:retrofit:2.0.1'
    implementation 'com.squareup.retrofit2:converter-gson:2.0.1'

添加网络权限


创建 用于描述网络请求 的接口
Retrofit将 Http请求 抽象成 Java接口:采用 注解 描述网络请求参数 和配置网络请求参数

/**
 * 描述: Retrofit的实现接口
 */

public interface Api {
    //发送json数据形式的post请求,把网络请求接口的后半部分openapi/api/v2写在里面
    //Get是请求数据实体类,Take接受数据实体类
    @POST("openapi/api/v2") //Post请求发送数据
    Call request(@Body Ask ask);//@body即非表单请求体,被@Body注解的ask将会被Gson转换成json发送到服务器,返回到Take。 // 其中返回类型为Call<*>,*是接收数据的类
}

关于请求体:
可以指定一个对象用作带有 @Body 注释的 HTTP 请求体。
该对象也将使用 Retrofit 实例上指定的转换器(ConverterFactory)进行转换。 如果没有添加转换器,则只能使用 RequestBody。
创建 Retrofit 实例

//       创建Retrofit对象
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://openapi.tuling123.com/")//设置网络请求url,后面一段写在网络请求接口里面
                .addConverterFactory(GsonConverterFactory.create())//添加Gson支持,然后Retrofit就会使用Gson将响应体(api接口的Take)转换我们想要的类型。
                .build();

baseUrl其实就是我们请求地址的域名,这个域名配合上文的Api.class接口中的参数才是一个完整的请求路径。

把数据填入ask,形成json格式的请求体

 private void request(String text) {
//      把输入的文本数据存储在请求实体类中,赋予了各个字段的数据
        Ask ask = new Ask();
        Ask.UserInfoBean info = new Ask.UserInfoBean();//用户信息
        info.setApiKey("申请的key");//将机器人的key值填入  
        info.setUserId("用户id");//将用户id填入 
        ask.setUserInfo(info);
        Ask.PerceptionBean.InputTextBean pre = new Ask.PerceptionBean.InputTextBean(text);//将要发送给机器人的文本数据text的对象(就像遥控器)命名为pre
        ask.setPerception(new Ask.PerceptionBean(pre));

创建 网络请求接口实例

//       创建网络请求接口的实例,这样才能调用接口
        Api api = retrofit.create(Api.class);
//      Take为响应实体类,用来接受机器人返回的回复数据,以下为接口调用
        //// 用法和OkHttp的call如出一辙,
        //// 不同的是:如果是Android系统,回调方法执行在主线程
        Call call = api.request(ask);//ask在前面赋予了各个字段的数据,在接口api中转成了json格式的数据,发送请求

发送网络请求(异步 / 同步)
封装了 数据转换、线程切换的操作
推荐直接用异步请求,因为同步请求需要写在子线程里,增加了代码量。
以下是异步请求:

//发送网络请求(异步)
 call.enqueue(new Callback() {
            //         请求成功
            @Override
            public void onResponse(Call call, Response response) {
//              接受到的机器人回复的数据
                 mText= response.body().getResults().get(0).getValues().getText();
//              把接受到的数据传入addData方法中,类型是TYPE_RECEIVED接受数据
                addData(mText, Chat.TYPE_RECEIVED,getCurrentTime());//机器人说的话添加到接收文本框里
                saveReceiveData();//保存接收到的数据
                speakText(mText);//读出图灵机器人说的话的文本
                Log.d(TAG,"接受到的机器人回复的数据: "+mText);
            }
            //            请求失败
            @Override
            public void onFailure(Call call, Throwable t) {
                Log.d(TAG,"请求失败: "+t.toString());
            }
        });
    }

调用call中的enqueue方法,这是一个异步请求,不会阻塞线程,类似于OKHttp中的enqueue,不同的是这里的两个回调方法onResponse和onFailure都是在主线程中执行,意味着我们可以直接在这两个回调方法中更新UI,爽吧!
Call 实例可以同步或异步执行。 每个实例只能使用一次,但调用 clone()将创建一个可以使用的新实例。

处理返回数据
通过response类的 body()对返回的数据进行处理

上述代码里就有这部分,就是返回体里面取出你所需要的数据(Results里面有个数组,第一个元素{}里就有Values,里面有需要的text)

mText= response.body().getResults().get(0).getValues().getText();

至此,搞定啦!

参考文章:
【Android 进阶】Retrofit2 目前最优雅的网络请求框架
一个App带你学会Retrofit2.0,麻麻再也不用担心我的网络请求了!

你可能感兴趣的:(post方式发送json格式的网络请求(基于Retrofit2))