这一节中,我们使用Retrofit实现一个的网络请求。
首先我们需要在App的build.gradle中添加对Retrofit库的依赖,并进行同步。
implementation 'com.squareup.retrofit2:retrofit:2.5.0';
网络权限不用额外注册,因为在使用Okhttp时我们已经声明了网络权限。
除此之外需要注意,Retrofit是基于OKhttp的封装,所以如果你单独使用Retrofit,OKhttp的库同样需要导入。
接下来我们就可以开始编写Retrofit相关的代码了。
为了让大家更好的理解Retrofit,我们先说一下Retrofit的两个特征
注解和设计模式,如果你之前学习过Java的注解,也了解过设计模式,或者先前在Python或别的编程语言中接触过它们,这会帮助你理解Retrofit。但如果统统没有,那也没有关系。我建议先跟我敲一遍代码,将程序跑通。然后看一下我提供的这几篇文章,更多的了解Retrofit。最后再自己敲击一遍,确认掌握Retrofit的基本使用之后,再去看一下注解和设计模式相关的文章。
在做这个系列教程的时候,一个很大的疑虑一直困扰着我的写作,我的读者在编程世界已经走到了哪一步?他们的基础如何?我的教程应该更详尽一些还是粗略一些,或者只需提供思路,快马加鞭一路向前即可?所以如果我的文章对您产生了些微的帮助,或者内容的什么地方有误/让你产生了困惑,都可以在评论区留言联系我,这对我帮助很大,也会直接影响到后面的讲解思路和教程内容。谢谢支持。
接下来我们按照先前所说的思路进行Retrofit的学习
1.新建一个RetrofitService接口,一般命名为xxxService,我们这儿叫它meituanService(因为我们的测试URL是美团的域名)
Retrofit将 Http请求 抽象成 Java接口:采用 注解 描述网络请求参数 和配置网络请求参数.
如果你只复制接口的代码,会一片飘红,可以像上一节一样使用Alt+Enter进行导包,如果列表中没有出现正确的导包内容,可以手动导入。下面我提供了完整的代码。
代码如下
package com.example.testretrofit; // 包名
// 一系列库的导入
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Headers;
import retrofit2.http.Query;
// 我们定义的接口
public interface meituanService {
@GET("getMerchantComment") // @GET注解的作用:采用Get方法发送网络请求
// @Headers注释的作用:添加一个Header,我们这儿添加了一个user-agent
@Headers("User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36")
/*
所有注释针对下面的内容
从左往右看,方法名为inquireMeiTuan,意为查询美团,你也可以使用别的方法名,但命名最好能表达方法和业务的意图。
返回类型为Call<*>,*是接收数据的类,我们直接获得Responsebody中的内容,这样简单一些,后续会进行调整。
之后十来行都是传参,这里是链式调用,我让每个参数另起一行,这样比较清晰。当然你也可以选择在一行里
写一个八百米长的链式调用。@Query用于Get中指定参数,格式如下@Query("name")格式 字段名,呈现结果为
getMerchantComment?platform=(填入一个String类型的值)&partner=xxx$……
你可能会困惑前面一长串Url,也就是域名、虚拟目录等去哪儿了?这个会在后面出现,不用急。
*/
Call inquireMeiTuan(@Query("platform")String platform,
@Query("partner")String partner,
@Query("originUrl")String originUrl,
@Query("riskLevel")String riskLevel,
@Query("optimusCode")String optimusCode,
@Query("id")String id,
@Query("userId")String userId,
@Query("offset") String offset,
@Query("pageSize")String pageSize,
@Query("sortType") String sortType);
};
接口暂时就完成了,接下来我们就可以基于这个接口进行网络请求了。
首先我们看一下昨天的代码,和昨天类似,我们先找到之前设计的RetrofitButton,然后给它注册一个监听器,在它的onClick中写具体的Retrofit代码和逻辑。
你可能已经发现了一个问题,这个活动(Activity)的代码有些臃肿,很难找到合适的地方去继续写我们的代码。事实上,在真实开发中,我们并不会在Activity中写逻辑和具体业务代码,Activity只用负责页面的显示和交互,请求数据等代码都写在另外的类里。但作为一个Demo,我们不用这么复杂。
点击图中红色括号框选的"{",Android Studio会为我们找到这个大括号的另一半。我们在这下面开始写新的代码,这样两个Button和请求的逻辑就是同级的了,不会发生嵌套上的错误。
这个左括号是setOnClickListener()方法内部类中的大括号,我们应该找setOnClickListener方法右边的圆括号。
写到下面两张截图的地方,别傻傻的自己敲,最后展示完整的代码。
// 从这儿开始,我们要进行Retrofit相关代码的编写
Button RetrofitButton = (Button) findViewById(R.id.RetrofitButton);
// 注册监听事件
RetrofitButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 创建Retrofit实例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.meituan.com/meishi/api/poi")
.build()
;
// 获取UserMgrService对象
meituanService mtService = retrofit.create(meituanService.class);
// 调用
retrofit2.Call call = mtService.inquireMeiTuan("1", "126",
"https%3A%2F%2Fwww.meituan.com%2Fmeishi%2F6309410%2F",
"1", "1", "6309410", "", "0",
"10", "1");
call.enqueue(new retrofit2.Callback() {
@Override
public void onResponse(retrofit2.Call call, retrofit2.Response response) {
try {
String result = response.body().string();
Log.d("testMyApp", result);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(retrofit2.Call call, Throwable t) {
Log.e("testMyApp", "出错啦!");
}
});
}
});
假设你已经编写好了上述的代码,接下来我们就几个关键的点进行说明。
创建Retrofit实例过程中,我们先通过Retrofit.Builder构建,再调用baseUrl方法设置基础URL。
在接口调用时,我们自己填写了十个对应的值,在真正的App网络通信中,这些值很可能就是从用户的点击、搜索,翻页等操作产生。
最后一步对Call对象的操作你会发现和Okhttp中很像,因为Retrofit本来就是对Okhttp的封装。除此之外需要提醒的是,OKhttp和Retrofit的网络通信,我们都只演示了异步请求,因为同步相对来说用的比较少,而且同步更简单。
最后,核对一下我们的代码,就可以像昨天一样开始运行App。
为了区分Okhttp和Retrofit的网络请求,我们在log上做一点小修改。
然后我们连接USB,运行程序。
测试Okhttp按钮时一切正常,输出也没有问题。
但点击RetrofitButton时,App闪退,且Log中没有打印返回数据。
我们来排查一下问题
一切顺利!
下一讲中,我们将要带着新的知识,重新奔赴小红书。
我们会遇到新的问题,然后再重新反思我们的网络请求知识是否学到位?在这样不断的、反复的拉扯中,你会对Android逆向和Android开发都增进理解。
本节中的代码和资源
链接:https://pan.baidu.com/s/1JQ3iA-Uef9cDMdg91ZEd6g
提取码:78yb