文章目录
要求
利用OkHttp一部获取慕课网电影数据(20条),使用Glide加载图片并显示在每个电影Item中,并且可以通过电影名称、类型进行搜索并展示。
运行效果
任务描述
一、首页显示内容:
- 影片搜索区域(名字,spinner列表,搜索按钮)
- 影片展示区域(RecyclerView 2列展示)
二、电影详情
- 影片详情(详情UI布局)
三、搜索功能实现
- 电影名搜索
- 电影类型搜索
- 叠加搜索(名字 + 类型)
注意:电影数据的访问地址:www.imooc.com/api/movie
名字和类型可在地址后面添加参数来完成访问,如:
www.imooc.com/api/movie?title=银河护卫队2&types=动作
框架地址
分析
Movie: 存储每一个电影的数据
INetCallBack: 网络请求回调接口
MovieOkHttpUtils: 使用OkHttp提供从网络请求电影数据的方法
MovieRecyclerViewAdapter: 实现界面布局,提供更新UI的方法
MovieBiz: 获取网络返回结果,提供解析电影数据的方法,并实现UI布局的方法
MainActivity: 应用主界面
MovieDetailsActivity: 电影信息详情页面
代码实现
涉及到网络请求操作以及各类框架的使用,需完成网络配置以及根据框架地址来加载相关依赖
Movie
这个比较简单,声明了电影的相关属性、全参构造方法和一些get方法。为了方便,这里把大部分参数都设置为String类型,同时实现了Serializable
接口,为了接下来在不同的Activity间传参做准备
public class Movie implements Serializable {
private String _id, average, title, description, directorsName, year, types, imageUrl, castsName;
private int stars;
public Movie(String _id, String average, int stars, String title, String description, String directorsName, String year, String types, String castsName, String imageUrl) {
this._id = _id;
this.average = average;
this.stars = stars;
this.title = title;
this.description = description;
this.directorsName = directorsName;
this.year = year;
this.types = types;
this.castsName = castsName;
this.imageUrl = imageUrl;
}
// Getter和Setter...
}
INetCallBack
这里声明的是一个接口,声明两个方法用于网络请求时的回调
public interface INetCallBack {
void onSuccess(String response);
void onFailed(Throwable ex);
}
MovieOkHttpUtils
这个类要通过实现OkHttp来提供一个获取网络数据的doGet()
方法,在此方法中完成对INetCallBack接口的回调
// OkHttp网络请求方法,返回结果字符串
public void doGet(String url, INetCallBack callBack){
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
mUiHandler.post(new Runnable() {
@Override
public void run() {
callBack.onFailed(e);
}
});
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
String respStr = null;
try {
respStr = response.body().string();
} catch (IOException e) {
mUiHandler.post(new Runnable() {
@Override
public void run() {
callBack.onFailed(e);
}
});
return;
}
String finalRespStr = respStr;
mUiHandler.post(new Runnable() {
@Override
public void run() {
callBack.onSuccess(finalRespStr);
}
});
}
});
}
这个类可以设计成单例模式,在实际开发情况下只需要一个提供doGet()
方法的对象即可
MovieRecyclerViewAdapter
电影信息展示是通过RecyclerView来实现的,这里需要实现网格布局和线型布局两种
实现分为以下四步:
- 创建一个类继承RecyclerView.Adapter
- 创建一个内部类绑定ViewHolder(继承RecyclerView.ViewHolder,在类内完成控件初始化)
- 实现Adapter的相关方法
- 设置子项点击监听
因为该类中的onBindViewHolder()
方法是运行在UI线程的,所以在此类中直接完成对UI的更改
这里需要使用到Glide来完成网络图片的获取及加载
public class MovieRecyclerViewAdapter extends RecyclerView.Adapter<MovieRecyclerViewAdapter.ViewHolder> {
private Context context;
private List<Movie> data;
private OnItemClickListener onItemClickListener;
private RecyclerView recyclerView;
public MovieRecyclerViewAdapter(Context context, RecyclerView recyclerView) {
this.context = context;
this.data = new ArrayList<>();
this.recyclerView = recyclerView;
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public void setData(List<Movie> data) {
this.data = data;
notifyDataSetChanged();
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)