RecyclerView+Retrofit2的基本用法
1.简介
上一章节写了RadioGroup+ViewPager+Fragment的组合使用,这一章我们在fragment里面加入内容。
我的笔记都是在上一张的基础上增加的内容:
上一章:RadioGroup+ViewPager+Fragment的组合使用
需要了解的知识点:
1.recyclerview的基本使用
2.Retrofit2的基本使用
下面是内容的图片

2.RecyclerView的基本使用
2.1 RecyclerView的导包
implementation 'com.android.support:recyclerview-v7:27.1.1'
这里的版本最好和系统的appcompat-v7保持一致
在这里我讲一下为什么有的导入依赖的时候是compile 有的却是implementation 。
这是因为android studio在3.0以后加入了implementation ,implementation 对于使用了该命令编译的依赖,对该项目有依赖的项目将无法访问到使用该命令编译的依赖中的任何程序,也就是将该依赖隐藏在内部,而不对外部公开。
2.2 RecyclerView的布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recommend_rv"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
2.2 RecyclerView的适配器
public class RecommendAdapter extends RecyclerView.Adapter<RecommendAdapter.VH> {
private View mView;
private VH mVH;
private List<String> mList;
private Context mContext;
public RecommendAdapter(Context context, List<String> list) {
this.mList = list;
this.mContext = context;
}
//添加view,不过返回的是ViewHolder类型
@NonNull
@Override
public VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
mView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recommend, parent, false);
mVH = new VH(mView);
return mVH;
}
//对item里面添加内容
@Override
public void onBindViewHolder(@NonNull VH holder, int position) {
if (mList.size() != 0) {
Glide.with(mContext).load(mList.get(position)).into(holder.itemimage);
}
}
//返回list的长度,但是RecyclerView不能为0
@Override
public int getItemCount() {
return mList.size() > 0 ? mList.size() : 1;
}
public class VH extends RecyclerView.ViewHolder {
public ImageView itemimage;
public VH(View itemView) {
super(itemView);
itemimage = (ImageView) itemView.findViewById(R.id.recommend_image);
}
}
}
图片的加载有使用到glide,我以后的章节再单独讲glide的一些使用方法。
关于适配器的简单理解:
1.class继承了RecyclerView.Adapter必须要声明类型,类型必须要是RecyclerView.ViewHolder,而这个类型又需要自己重新写一个class来继承RecyclerView.ViewHolder
2.重写的class,里面写item的一些findViewById
3.Adapter需要继承3个函数
3.1 getItemCount() list的长度,不能为空
3.2 onBindViewHolder() item需要设置的内容
3.3 onCreateViewHolder() 这个是的ViewHolder 类型,里面来设置layout,返回的是ViewHolder 类型
2.3 RecyclerView的数据导入
因为这里我们需要使用Retrofit2来获取数据,所以先把RecyclerView的部分先暂停。我们来讲一下获取数据,然后获取到数据后,再把RecyclerView的数据添加讲一下。
3.Retrofit2的基本使用
3.1 Retrofit2的导包
这里我把glide的导包和Okhttp的使用也加入,我这边使用的地方只有两处,所有不做特别多的介绍。
glide和Okhttp功能都比较强大,有兴趣的可以去了解一下。
glide是用来做图片加载的一个好用的工具
//glide的依赖
implementation 'com.github.bumptech.glide:glide:4.8.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
// Okhttp库
implementation 'com.squareup.okhttp3:okhttp:3.1.2'
//Retrofit的依赖
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.8.0'
3.2 Retrofit2的bean文件的创建
这里推荐一下GsonFormat这个android studio的小插件,很好用。
因为录制的问题,我这边没有办法录制gif,只好截图


下面是从网页上获取的数据,把数据复制

复制到弹出的对话框中,可以点击format来整理数据,然后按确定

再点击确定就创建了相关的数据

这里如果改了名字需要使用注解来说明你的json解析时候的名字
使用@SerializedName来注解,这里我们使用原来的就好。
数据来自 作者:夕夜_如风
连接:https://www.jianshu.com/p/796496029886
我这里是使用的360的api其实还可以使用bing的壁纸api这个看个人喜好。
接口:http://wallpaper.apc.360.cn/index.php?c=WallPaperAndroid&a=getAppsByCategory&cid=1&start=0&count=99
3.3 Retrofit2的接口的创建
这里使用的是GET的数据请求
retrofit还有POST、PATH等等
@Query相当于& 用来添加内容
public interface GetRequestInterface {
/**
* http://wallpaper.apc.360.cn/index.php?c=WallPaperAndroid&a=getAppsByCategory&cid=1&start=0&count=99
* cid:类别id,类别已知:
* start:跳过的记录数
* count:返回的数量
* 1:每日精选
* 5:游戏
* 6:美女
* 9:风景
* 10:视觉创意
* 11:明星影视
* 12:汽车
* 14:萌宠动物
* 15:小清新
* 16:体育
* 22:军事
* 26:动漫卡通
* 30:情感
* 35:文字
*
*
* 解析
* total:返回数据数量
* data:返回的数据
* pid:
* cid:类别ID
* url:壁纸地址
* fav_total:收藏数
*/
@GET("index.php")
Call<BaseResponse> getCall(@Query("c") String WallPaperAndroid, @Query("a") String getAppsByCategory,
@Query("cid") int cid, @Query("start") int start, @Query("count") int count);
}
4.Retrofit2的数据获取和RecyclerView的数据添加
public class Fragment_Recommend extends Fragment {
private static final String TAG = "Fragment_Recommend";
private View myView;
private LinearLayout mNetworkNo;
private TextView mRetry;
private RecyclerView mRecommendRv;
private GridLayoutManager gridLayoutManager;
private RecommendAdapter recommendAdapter;
private List<String> mListUrl;
private static final String WallPaperAndroid = "WallPaperAndroid";
private static final String GetAppsByCategory = "getAppsByCategory";
private static final int GETTYPE = 1;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
myView = inflater.inflate(R.layout.wallpaper_recommend, container, false);
initData();
initView();
return myView;
}
private void initData() {
mListUrl = new ArrayList<>();
Request();
gridLayoutManager = new GridLayoutManager(myView.getContext(), 2);
recommendAdapter = new RecommendAdapter(myView.getContext(), mListUrl);
}
private void Request() {
//okhttp的网络等待
OkHttpClient.Builder builder = new OkHttpClient().newBuilder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS);
final OkHttpClient client = builder.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://wallpaper.apc.360.cn/")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
// 步骤5:创建 网络请求接口 的实例
GetRequestInterface request = retrofit.create(GetRequestInterface.class);
Call<BaseResponse> call = request.getCall(WallPaperAndroid, GetAppsByCategory, GETTYPE, 0, 99);
//步骤6:发送网络请求(异步)
call.enqueue(new Callback<BaseResponse>() {
@Override
public void onResponse(@NonNull Call<BaseResponse> call, @NonNull Response<BaseResponse> response) {
Log.d(TAG, "onResponse: " + response.body());
BaseResponse baseResponse = response.body();
if (baseResponse == null) {
return;
}
for (BaseResponse.DataBean data : baseResponse.getData()) {
Log.d(TAG, "data.getUrl() = " + data.getUrl());
Log.d(TAG, "data.getC_t() = " + data.getC_t());
Log.d(TAG, "data.getPid() = " + data.getPid());
Log.d(TAG, "data.getFav_total() = " + data.getFav_total());
mListUrl.add(data.getUrl());
}
}
@Override
public void onFailure(@NonNull Call<BaseResponse> call, @NonNull Throwable t) {
Log.d(TAG, "retrofit is error");
}
});
}
private void initView() {
mNetworkNo = (LinearLayout) myView.findViewById(R.id.network_no);
mRetry = (TextView) myView.findViewById(R.id.retry);
mRecommendRv = (RecyclerView) myView.findViewById(R.id.recommend_rv);
mRecommendRv.setLayoutManager(gridLayoutManager);
mRecommendRv.setAdapter(recommendAdapter);
}
}
我们先说RecyclerView的设置
mListUrl = new ArrayList<>();
Request();
gridLayoutManager = new GridLayoutManager(myView.getContext(), 2);
recommendAdapter = new RecommendAdapter(myView.getContext(), mListUrl);
mRecommendRv.setLayoutManager(gridLayoutManager);
mRecommendRv.setAdapter(recommendAdapter);
mListUrl 是我们得到的数据
1.我们先对RecyclerView设置他的布局类型GridLayoutManager
RecyclerView有3种类型
LinerLayoutManager 以垂直或者水平列表方式展示Item
GridLayoutManager 以网格方式展示Item(后面的int就是横向显示的个数)
StaggeredGridLayoutManager 以瀑布流方式展示Item
2.把数据传入适配器
3.设置RecyclerView的适配器
Retrofit2的代码解析:
private void Request() {
//okhttp的网络等待
OkHttpClient.Builder builder = new OkHttpClient().newBuilder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS);
final OkHttpClient client = builder.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://wallpaper.apc.360.cn/")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
// 步骤5:创建 网络请求接口 的实例
GetRequestInterface request = retrofit.create(GetRequestInterface.class);
Call<BaseResponse> call = request.getCall(WallPaperAndroid, GetAppsByCategory, GETTYPE, 0, 99);
//步骤6:发送网络请求(异步)
call.enqueue(new Callback<BaseResponse>() {
@Override
public void onResponse(@NonNull Call<BaseResponse> call, @NonNull Response<BaseResponse> response) {
Log.d(TAG, "onResponse: " + response.body());
BaseResponse baseResponse = response.body();
if (baseResponse == null) {
return;
}
for (BaseResponse.DataBean data : baseResponse.getData()) {
Log.d(TAG, "data.getUrl() = " + data.getUrl());
Log.d(TAG, "data.getC_t() = " + data.getC_t());
Log.d(TAG, "data.getPid() = " + data.getPid());
Log.d(TAG, "data.getFav_total() = " + data.getFav_total());
mListUrl.add(data.getUrl());
}
}
@Override
public void onFailure(@NonNull Call<BaseResponse> call, @NonNull Throwable t) {
Log.d(TAG, "retrofit is error");
}
});
}
在没有Retrofit2之前,一般使用的网络请求是okhttp,Retrofit2是对okhttp的一个封装。是square公司出的jar包。
//okhttp的网络等待
OkHttpClient.Builder builder = new OkHttpClient().newBuilder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS);
final OkHttpClient client = builder.build();
这里是okhttp的一些判断处理,连接等待,读写,都是10秒
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://wallpaper.apc.360.cn/")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
retrofit2初始化
这里还可以加入addCallAdapterFactory方法,addCallAdapterFactory使用RxJavaCallAdapterFactory,如果加入rxjava的配合,那么接口的GetRequestInterface.java类就需要更改。这里不做那么深的讲解,后续有兴趣的读者可以去了解一下。
// 步骤5:创建 网络请求接口 的实例
GetRequestInterface request = retrofit.create(GetRequestInterface.class);
Call<BaseResponse> call = request.getCall(WallPaperAndroid, GetAppsByCategory, GETTYPE, 0, 99);
这里传入需要解析的格式,然后和网络请求的各个参数
//步骤6:发送网络请求(异步)
call.enqueue(new Callback<BaseResponse>() {
@Override
public void onResponse(@NonNull Call<BaseResponse> call, @NonNull Response<BaseResponse> response) {
Log.d(TAG, "onResponse: " + response.body());
BaseResponse baseResponse = response.body();
if (baseResponse == null) {
return;
}
for (BaseResponse.DataBean data : baseResponse.getData()) {
Log.d(TAG, "data.getUrl() = " + data.getUrl());
Log.d(TAG, "data.getC_t() = " + data.getC_t());
Log.d(TAG, "data.getPid() = " + data.getPid());
Log.d(TAG, "data.getFav_total() = " + data.getFav_total());
mListUrl.add(data.getUrl());
}
}
@Override
public void onFailure(@NonNull Call<BaseResponse> call, @NonNull Throwable t) {
Log.d(TAG, "retrofit is error");
}
});
这里的BaseResponse是我们bean文件的类名,json解析的时候也需要这个类名。如果连接的参数不对,或者json的解析不对。都会走onFailure。
5.小结
1.RecyclerView的适配器的使用,继承的类型
2.RecyclerView的list不能为空,还有onCreateViewHolder的返回的类型
3.RecyclerView的设置布局的显示样式
4.Retrofit2的接口的写法,注意使用的post还是get
5.Retrofit2的bean文件的名称如果不是json解析的需要加入注解
6.Retrofit2的返回时候判断空,如果没有判断如果json返回为错的,会报错
6.扩展
Retrofit2也可以加入rxjava的,使用的时候一般会rxjava+Retrofit2+Glide一起使用。
保存当前的fragment的转态,不让fragment被finish了
mWallpaperVp.setOffscreenPageLimit(mList.size() - 1);
主要函数是setOffscreenPageLimit,然后当前的viewpager的长度-1
可以给作者评论,关注加喜欢吗?
