MVVM与DataBinding简单案例
一、MVVM
1.MVVM是什么
MVVM(Model–View–Viewmodel)是一种软件架构模式。
M----->Model层:请求的原始数据
V----->View层:视图展示,由ViewController来控制
VM---->ViewModel层:负责业务处理和数据转化
MVVM与MVC的不同
首先我们简化一下MVC的架构模式图:
在这里,Controller需要做太多得事情,表示逻辑、业务逻辑,所以代码量非常的大。而MVVM:
在MVVM中,我们趋向于将view和view controller作为一个整体(这也解释了为什么不称它为MVVCVM),新的viewModel代替原来的viewController协调view与model之间的交互。
2.基本使用
创建好一个Android Project之后,在gradle文件中添加如下几行代码,表示开启databinding:
android {
...
dataBinding{
enabled true
}
...
}
3.以两个功能案例举例areacode(地区和区号)和topimage(图片加载)
二、areacode(地区和区号)
1.页面布局
2.主要model
3.VM:AreaCodeViewModel
3.activity
4.显示效果
三、topimage(图片加载),添加RecyclerView展示数据列表
1.布局文件
2.主要model
3.VM之TopImageViewModel
public class TopImageViewModel {
private List<ImgInfoModel> listImage = new ArrayList<>();
private List<ImgInfoModel> listImage_refresh = new ArrayList<>();
private DataBindingRecyclerViewAdapter adapter;
public TopImageViewModel(final TopImageActivity activity) {
OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象
FormBody.Builder forBody1 = new FormBody.Builder();//创建表单请求体
forBody1.add("LANGUAGE", String.valueOf(0));//传递键值对参数
forBody1.add("CURR", "RMB");//传递键值对参数
forBody1.add("NO_DEVICE", String.valueOf(1));//传递键值对参数
FormBody.Builder forBody = new FormBody.Builder();//创建表单请求体
forBody.add("COMMONINFO", String.valueOf(forBody1));//传递键值对参数
forBody.add("TOKENINFO", "");//传递键值对参数
forBody.add("VIPCONTENT", "");//传递键值对参数
Request request = new Request.Builder()//创建Request 对象
.url("https://xxxxxxxxxxxxxxx")//接口
.post(forBody.build())//传递请求体
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
Log.d("kwwl", "获取数据失败----");
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
// Log.d("kwwl", "获取数据成功了----");
// Log.d("kwwl", "response.code()---==" + response.code());
// Log.d("kwwl", "response.body().string()---==" + response.body().string());
RImgInfoModel model = new Gson().fromJson(response.body().string(), RImgInfoModel.class);
if (model.getRESULTCODE().getVIPCODE() == 0) {
listImage.addAll(model.getVIPCONTENT());
listImage_refresh.addAll(listImage);
//Only the original thread that created a view hierarchy can touch its views
//翻译过来:只有创建这个view的线程才能操作这个view
//在使用Volley的时候这个问题就不怎么会遇到了,那是因为无论是HttpURLConnection还是OkHttp
//最终的回调接口,即onResponse运行在子线程
//所以一旦在回调接口对UI进行了操作,将会出现上述提示
//一般来讲,会使用handle解决这个问题
activity.runOnUiThread(new Runnable() {
public void run() {
adapter = new DataBindingRecyclerViewAdapter(activity, R.layout.item_image, com.dawn.mvvmanddatabinding.BR.imgItem, listImage);
activity.binding.recyclerView.setLayoutManager(new LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false));
activity.binding.recyclerView.setAdapter(adapter);
adapter.setOnItemCkickListener(new DataBindingRecyclerViewAdapter.ItemClickListener() {
@Override
public void itemClick(View view, int position) {
Log.e("111",listImage.get(position).getST_IMGENGNAME()+"---");
Toast.makeText(activity, listImage.get(position).getST_IMGPATH()+"----"+position, Toast.LENGTH_LONG).show();
}
});
}
});
} else
Log.d("kwwl", model.getRESULTCODE().getVIPINFO() + "================");
}
});
}
public void refresh() {
listImage.clear();
if (listImage_refresh.size() != 0)
listImage.addAll(listImage_refresh);
adapter.notifyDataSetChanged();
}
public void remove() {
if (listImage.size() != 0)
listImage.remove(0);
adapter.notifyDataSetChanged();
}
public void add() {
ImgInfoModel p = new ImgInfoModel();
p.setST_IMGENGNAME("我爱吃水果 --新增的图片");
p.setST_IMGPATH("https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1302960203,381285259&fm=26&gp=0.jpg");
listImage.add(0, p);
adapter.notifyDataSetChanged();
}
}
4.适配器布局
5.适配器代码
public class DataBindingRecyclerViewAdapter extends RecyclerView.Adapter<DataBindingRecyclerViewAdapter.ViewHolder> {
Context mContext;
int mLayoutId;
int mVarId;
private List mData;
public static final int TYPE_HEADER = 1, TYPE_FOOTER = 2, TYPE_NORMAL = 0;
boolean haveHeader = false;
boolean haveFooter = false;
View headerView, footerView;
private ItemClickListener itemClickListener;
public OnBindingViewHolderListener onBindingViewHolderListener;
public DataBindingRecyclerViewAdapter(Context context, int layoutId, int varId, List data) {
mContext = context;
mLayoutId = layoutId;
mVarId = varId;
mData = data;
}
public void setOnItemCkickListener(ItemClickListener listener) {
this.itemClickListener = listener;
}
public void setOnBindingViewHolderListener(OnBindingViewHolderListener listener) {
onBindingViewHolderListener = listener;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_HEADER:
return new ViewHolder(headerView, viewType);
case TYPE_FOOTER:
return new ViewHolder(footerView, viewType);
case TYPE_NORMAL:
return new ViewHolder(LayoutInflater.from(mContext).inflate(mLayoutId, parent, false), viewType);
default:
return new ViewHolder(LayoutInflater.from(mContext).inflate(mLayoutId, parent, false), viewType);
}
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
switch (holder.viewType) {
case TYPE_HEADER:
break;
case TYPE_FOOTER:
break;
case TYPE_NORMAL:
default:
ViewDataBinding binding = DataBindingUtil.bind(holder.itemView);
Object data;
if (haveHeader) {
data = mData.get(position - 1);
} else {
data = mData.get(position);
}
if (itemClickListener != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
itemClickListener.itemClick(holder.itemView, position);
}
});
}
binding.setVariable(mVarId,data);
binding.executePendingBindings();
if (onBindingViewHolderListener != null) {
onBindingViewHolderListener.onHolderBinding(holder, position);
}
break;
}
}
/**
* 调用之后请调用NotifyDataSetChange 如果在setAdapter之后
*
* @param view
*/
public void addFooterView(View view) {
haveFooter = true;
footerView = view;
}
/**
* 调用之后请调用NotifyDataSetChange 如果在setAdapter之后
*
* @param view
*/
public void addHeaderView(View view) {
haveHeader = true;
headerView = view;
}
public void removeFooterView() {
footerView = null;
haveFooter = false;
}
public View getFooterView() {
return footerView;
}
public void cleanData() {
mData.clear();
notifyDataSetChanged();
}
public List getAllData() {
return mData;
}
public void addData(List data) {
mData.addAll(data);
notifyDataSetChanged();
}
@Override
public int getItemCount() {
int extraCount = 0;
if (haveHeader) {
extraCount++;
} else if (haveFooter) {
extraCount++;
}
return mData.size() + extraCount;
}
@Override
public int getItemViewType(int position) {
if (position == 0 && haveHeader) {
return TYPE_HEADER;
} else if (position == mData.size() && haveFooter) {
return TYPE_FOOTER;
} else {
return TYPE_NORMAL;
}
}
public class ViewHolder extends RecyclerView.ViewHolder {
int viewType;
public ViewHolder(View itemView, int viewType) {
super(itemView);
this.viewType = viewType;
}
}
public interface ItemClickListener {
void itemClick(View view, int position);
}
public interface OnBindingViewHolderListener {
void onHolderBinding(ViewHolder holder, int position);
}
}
6.加载适配器图片代码
7.activity代码
8.效果图