前言
框架发展mvc mvp mvvm mvpvm
MVP把Activity,Framgent中的UI逻辑抽象成View接口
把业务逻辑交给Presenter主持
Model类还是原来的Model
使用MVP的好处
分离了视图逻辑和业务逻辑,降低了耦合
Activity只处理生命周期的任务,代码变得更加简洁
视图逻辑和业务逻辑分别抽象到了View和Presenter的接口中去,提高代码的可阅读性
业务逻辑抽到Presenter中去,避免后台线程引用着Activity导致Activity的资源无法被系统回收从而引起内存泄露和OOM
目录结构
MVP实例
把一个大虾串通过mvp模式下载,并在recycleView中展示.
IMode 接口
/**
* 数据层的公共方法
*/
public interface IModel {
//数据销毁方法
void destroy();
}
IView接口
/**
* 视图层的顶层. 是activity和 fragment的接口层
*/
public interface IView {
//加载提示信息
void showLoading();
//取消加载提示信息
void hideLoading();
//吐司提示
void showToast(String msg);
}
IActivity接口
/**
* 所有Activity的顶层接口
* 放一些页面共有的方法
* 必须加载布局是必须的
* 查找组件是必须的
* 初始化数据源是必须的
*/
public interface IActivity {
//每一个Activity都是绑定布局
int bindLayout();
//findviewbyid
void initView();
//赋值
void initData();
//注入用的-一会说
// void inject();
}
IFragment接口
//所有fragment的顶层接口
public interface IFragment extends IActivity {
View getViewById(@IdRes int id);
}
IPresenter接口
//所有fragment的顶层接口
public interface IFragment extends IActivity {
View getViewById(@IdRes int id);
}
BaseModel
public class BaseModel implements IModel {
@Override
public void destroy() {
}
}
BaseActivity
package mvp.view;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import mvp.model.BaseModel;
import mvp.presenter.BasePresenter;
public abstract class BaseActivity<P extends BasePresenter> extends AppCompatActivity implements IActivity,IView {
protected P mpresenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(bindlayour());
inintData();
inintView();
}
}
BaseFragment
package mvp.view;
import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import mvp.presenter.BasePresenter;
public abstract class BaseFragment <P extends BasePresenter> extends Fragment implements IActivity,IView {
protected P mpresenter;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
View inflate = inflater.inflate(bindlayour(), null);
return inflate;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
inintData();;
inintView();
}
}
BasePresenter
package mvp.presenter;
import mvp.model.BaseModel;
import mvp.model.IModel;
import mvp.view.IView;
public class BasePresenter<M extends IModel,V extends IView>implements IPresenter {
protected M mModel;
protected V mView;
public BasePresenter(M mModel, V mView) {
this.mModel = mModel;
this.mView = mView;
}
@Override
public void destoory() {
}
}
build.geadle
apply plugin: 'com.android.application'
改
apply plugin: 'com.android.library'
defaultConfig {
applicationId "com.example.mvp_name"//删除
minSdkVersion 24
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
大虾
FoodAdapter
package com.example.a1810ag3.Adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.example.a1810ag3.R;
import com.example.a1810ag3.entrty.Food;
import java.util.List;
public class FoodAdapter extends RecyclerView.Adapter<FoodAdapter.FoodViewHolder> {
private Context context;
private List<Food.DataBean> list;
public FoodAdapter(Context context, List<Food.DataBean> list) {
this.context = context;
this.list = list;
}
class FoodViewHolder extends RecyclerView.ViewHolder {
private ImageView img;
private TextView text;
public FoodViewHolder(@NonNull View itemView) {
super(itemView);
img = (ImageView)itemView. findViewById(R.id.img);
text = (TextView) itemView.findViewById(R.id.text);
}
}
@NonNull
@Override
public FoodViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.item, null);
return new FoodViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull FoodViewHolder holder, int position) {
holder.text.setText(list.get(position).getTitle()+"");
Glide.with(context).load(list.get(position).getPic()).into(holder.img);
}
@Override
public int getItemCount() {
return list.size();
}
}
Api
package com.example.a1810ag3.entrty;
import retrofit2.Call;
import retrofit2.http.GET;
public interface Api {
@GET("/ios/cf/dish_list.php?stage_id=1&limit=10&page=1")
Call<Food> getCall();
}
Food
package com.example.a1810ag3.entrty;
import java.util.List;
public class Food {
/**
* ret : 1
* data : [{"id":"t8289","title":"油焖大虾","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/9/8289.jpg","collect_num":"1670","food_str":"大虾 葱 生姜 植物油 料酒","num":1670},{"id":"2127","title":"四川回锅肉","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/3/2127.jpg","collect_num":"1591","food_str":"猪肉 青蒜 青椒 红椒 姜片","num":1591},{"id":"30630","title":"超简单芒果布丁","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/31/30630.jpg","collect_num":"1549","food_str":"QQ糖 牛奶 芒果","num":1549},{"id":"9073","title":"家常红烧鱼","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/10/9073.jpg","collect_num":"1426","food_str":"鲜鱼 姜 葱 蒜 花椒","num":1426},{"id":"10097","title":"家常煎豆腐","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/11/10097.jpg","collect_num":"1419","food_str":"豆腐 新鲜红椒 青椒 葱花 油","num":1419},{"id":"10509","title":"水煮肉片","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/11/10509.jpg","collect_num":"1342","food_str":"瘦猪肉 生菜 豆瓣酱 干辣椒 花椒","num":1342},{"id":"46968","title":"红糖苹果银耳汤","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/47/46968.jpg","collect_num":"1253","food_str":"银耳 苹果 红糖","num":1253},{"id":"10191","title":"麻婆豆腐","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/11/10191.jpg","collect_num":"1224","food_str":"豆腐 肉末 生抽 白糖 芝麻油","num":1224},{"id":"2372","title":"皮蛋瘦肉粥","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/3/2372.jpg","collect_num":"1151","food_str":"大米 皮蛋 猪肉 油条 香葱","num":1151},{"id":"2166","title":"蚂蚁上树","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/3/2166.jpg","collect_num":"1145","food_str":"红薯粉 肉 姜 蒜 花椒","num":1145}]
*/
private int ret;
private List<DataBean> data;
public int getRet() {
return ret;
}
public void setRet(int ret) {
this.ret = ret;
}
public List<DataBean> getData() {
return data;
}
public void setData(List<DataBean> data) {
this.data = data;
}
public static class DataBean {
/**
* id : t8289
* title : 油焖大虾
* pic : http://www.qubaobei.com/ios/cf/uploadfile/132/9/8289.jpg
* collect_num : 1670
* food_str : 大虾 葱 生姜 植物油 料酒
* num : 1670
*/
private String id;
private String title;
private String pic;
private String collect_num;
private String food_str;
private int num;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getPic() {
return pic;
}
public void setPic(String pic) {
this.pic = pic;
}
public String getCollect_num() {
return collect_num;
}
public void setCollect_num(String collect_num) {
this.collect_num = collect_num;
}
public String getFood_str() {
return food_str;
}
public void setFood_str(String food_str) {
this.food_str = food_str;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
}
}
Foodcontract
package com.example.a1810ag3.mvp.contract;
import com.example.a1810ag3.entrty.Food;
import java.util.List;
import MVP.model.IModel;
import MVP.view.IView;
import okhttp3.Callback;
public interface Foodcontract {
interface IFoodModel extends IModel{
// 下载
void getFoodData(Callback callback);
}
interface IFoodView extends IView{
// 展示
void initAdapter(List<Food.DataBean> list);
}
}
FoodModel
package com.example.a1810ag3.mvp.model;
import com.example.a1810ag3.mvp.contract.Foodcontract;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
public class FoodModel implements Foodcontract.IFoodModel {
String uri = "http://www.qubaobei.com/ios/cf/dish_list.php?stage_id=1&limit=10&page=1";
@Override
public void getFoodData(Callback callback) {
OkHttpClient client = new OkHttpClient
.Builder()
.build();
Request request = new Request.
Builder()
.get()
.url(uri)
.build();
client.newCall(request).enqueue(callback);
}
@Override
public void destoory() {
}
}
FoodPresenter
package com.example.a1810ag3.mvp.precenter;
import com.example.a1810ag3.entrty.Food;
import com.example.a1810ag3.mvp.contract.Foodcontract;
import com.google.gson.Gson;
import java.io.IOException;
import java.util.List;
import MVP.presenter.BasePresenter;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
public class FoodPresenter extends BasePresenter<Foodcontract.IFoodModel,Foodcontract.IFoodView> {
public FoodPresenter(Foodcontract.IFoodModel mModel, Foodcontract.IFoodView mView) {
super(mModel, mView);
}
public void getData(){
mModel.getFoodData(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String s = response.body().string();
Food food = new Gson().fromJson(s, Food.class);
List<Food.DataBean> data = food.getData();
mView.initAdapter(data);
}
});
}
}
MainActivity
package com.example.a1810ag3.mvp.view;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import com.example.a1810ag3.Adapter.FoodAdapter;
import com.example.a1810ag3.R;
import com.example.a1810ag3.entrty.Food;
import com.example.a1810ag3.mvp.contract.Foodcontract;
import com.example.a1810ag3.mvp.model.FoodModel;
import com.example.a1810ag3.mvp.precenter.FoodPresenter;
import com.google.gson.Gson;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.callback.StringCallback;
import com.lzy.okgo.model.Response;
import java.util.ArrayList;
import java.util.List;
import MVP.view.BaseActivity;
import okhttp3.Callback;
public class MainActivity extends BaseActivity<FoodPresenter> implements Foodcontract.IFoodModel,Foodcontract.IFoodView {
private RecyclerView rv;
@Override
public void inintDate() {
FoodPresenter foodPresenter = new FoodPresenter(new FoodModel(), this);
foodPresenter.getData();;
}
@Override
public void initAdapter(List<Food.DataBean> list) {
final FoodAdapter foodAdapter = new FoodAdapter(this, list);
runOnUiThread(new Runnable() {
@Override
public void run() {
rv.setLayoutManager(new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL));
rv.setAdapter(foodAdapter);
}
});
}
@Override
public void destoory() {
}
@Override
public int bindLayout() {
return R.layout.activity_main;
}
@Override
public void inintView() {
rv = (RecyclerView) findViewById(R.id.rv);
}
@Override
public void showToast() {
}
@Override
public void getFoodData(Callback callback) {
}
}
Layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".mvp.view.MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.recyclerview.widget.RecyclerView>
</LinearLayout>
item
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/img"
android:layout_width="160dp"
android:layout_height="160dp" />
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
依赖
implementation 'androidx.recyclerview:recyclerview:1.0.0' // 这是是androidx的
implementation 'com.google.code.gson:gson:2.8.0'//gson依赖
implementation 'com.github.bumptech.glide:glide:4.11.0'//Glide
implementation 'com.squareup.okhttp3:okhttp:3.12.1'//okhttp依赖
implementation 'com.squareup.okhttp3:logging-interceptor:3.4.1'// log拦截器依赖
implementation 'com.lzy.net:okgo:3.0.4'//okgo依赖
BufferKnife