第3单元 mvp架构,dagger2,butterknife的使用

前言
框架发展mvc mvp mvvm mvpvm
MVP把Activity,Framgent中的UI逻辑抽象成View接口
把业务逻辑交给Presenter主持
Model类还是原来的Model

使用MVP的好处
分离了视图逻辑和业务逻辑,降低了耦合
Activity只处理生命周期的任务,代码变得更加简洁
视图逻辑和业务逻辑分别抽象到了View和Presenter的接口中去,提高代码的可阅读性
业务逻辑抽到Presenter中去,避免后台线程引用着Activity导致Activity的资源无法被系统回收从而引起内存泄露和OOM

结构图
在这里插入图片描述
目录结构
在这里插入图片描述

MVP实例

把一个大虾串通过mvp模式下载,并在recycleView中展示.

在这里插入图片描述
IModel

/**
 * 数据层的公共方法
 */
public interface IModel {
    
    
    //数据销毁方法
    void destroy();
}

通用方法

public class BaseModel implements IModel {
    
    
    @Override
    public 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();


}

BaseActivity

package com.fenghongzhang.mvp.view;

import android.os.Bundle;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.fenghongzhang.mvp.presenter.IPresenter;

public abstract class BaseActivity<P extends IPresenter> extends AppCompatActivity implements IActivity,IView {
    
    

    protected P mPresenter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(bindLayout());
        initView();
        initData();
    }

    @Override
    public void showToast(String msg) {
    
    
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onDestroy() {
    
    
        super.onDestroy();
        if(mPresenter != null){
    
    
            mPresenter.destroy();
        }
    }
}

IFragment

//所有fragment的顶层接口
public interface IFragment extends IActivity {
    
    

    View getViewById(@IdRes int id);

}

BaseFragment

package com.fenghongzhang.mvp.view;

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 com.fenghongzhang.mvp.presenter.IPresenter;

public abstract class BaseFragment<P extends IPresenter> extends Fragment implements IView,IFragment {
    
    


    protected View mView;

    protected P mPresenter;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    
    
        return mView = inflater.inflate(bindLayout(),container,false);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    
    
        super.onActivityCreated(savedInstanceState);
        initView();
        initData();
    }

    @Override
    public View getViewById(int id) {
    
    
        return mView.findViewById(id);
    }

    @Override
    public void onDestroy() {
    
    
        super.onDestroy();
        if(mPresenter != null){
    
    
            mPresenter.destroy();
        }
    }

    @Override
    public void showLoading() {
    
    

    }

    @Override
    public void hideLoading() {
    
    

    }

    @Override
    public void showToast(String msg) {
    
    

    }
}

IPresenter

/**
 * 主持层
 * 负责view和model的通讯
 */
public interface IPresenter {
    
    
    //销毁对象
    void destroy();
}

BasePresenter

/**
 * presenter是view和model交互的桥梁.所有需要拿到这个两个对象.
 * 但是他又是一个基础的presenter.类型不能限定死了.
 * 所以使用泛型来限制一下.
 */
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 destroy() {
    
    

    }
}

实际使用目录
在这里插入图片描述
从上到下的代码

FoodAdapter

package com.fenghongzhang.mvp.food.adapter;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.bumptech.glide.Glide;
import com.fenghongzhang.mvp.R;
import com.fenghongzhang.mvp.food.entity.Food;

import java.util.List;

public class FoodAdapter extends RecyclerView.Adapter<FoodAdapter.ViewHolder> {
    
    

    private List<Food.DataBean> list;

    private Context context;

    public FoodAdapter(List<Food.DataBean> list, Context context) {
    
    
        this.list = list;
        this.context = context;
    }

    static class ViewHolder extends RecyclerView.ViewHolder{
    
    

        ImageView rvimg;
        public TextView rmtext;

        public ViewHolder(@NonNull View itemView) {
    
    
            super(itemView);
            rvimg = itemView.findViewById(R.id.rv_img);
            rmtext = itemView.findViewById(R.id.rv_tv);
        }
    }

    @NonNull
    @Override
    public FoodAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    
    
        View inflate = LayoutInflater.from(context).inflate(R.layout.rv_layout, null);
        return new ViewHolder(inflate);
    }

    @Override
    public void onBindViewHolder(@NonNull FoodAdapter.ViewHolder holder, int position) {
    
    
        Food.DataBean dataBean = list.get(position);
        holder.rmtext.setText(dataBean.getTitle());
        Glide.with(context).load(dataBean.getPic()).into(holder.rvimg);
    }


    @Override
    public int getItemCount() {
    
    
        return list.size();
    }
}

Food

package com.fenghongzhang.mvp.food.entity;

import java.util.List;

public class Food {
    
    


    /**
     * ret : 1
     * data : [{"id":"8289","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},{"id":"2262","title":"糖醋肉","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/3/2262.jpg","collect_num":"1081","food_str":"猪肉 红椒 黄椒 洋葱 蛋清","num":1081},{"id":"9971","title":"鱼香豆腐","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/10/9971.jpg","collect_num":"1010","food_str":"豆腐 木耳 胡萝卜 香葱 番茄酱","num":1010},{"id":"10172","title":"干煸四季豆","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/11/10172.jpg","collect_num":"993","food_str":"四季豆 干辣椒 蒜头 酱油 糖","num":993},{"id":"2685","title":"胡萝卜肉末蒸蛋","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/3/2685.jpg","collect_num":"929","food_str":"胡萝卜 肉 蛋 生抽 盐","num":929},{"id":"9972","title":"虎皮青椒","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/10/9972.jpg","collect_num":"892","food_str":"青辣椒 大蒜 香醋 白糖 生抽","num":892},{"id":"10437","title":"叉烧排骨","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/11/10437.jpg","collect_num":"806","food_str":"排骨 李锦记叉烧酱 植物油 清水 油菜","num":806},{"id":"2892","title":"\u201c五行\u201d彩蔬汤","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/3/2892.jpg","collect_num":"761","food_str":"黑木耳 玉米 牛蒡 胡萝卜 西兰花","num":761},{"id":"2348","title":"麻辣肉丝面","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/3/2348.jpg","collect_num":"760","food_str":"面条 肉丝 淀粉 酱油 辣椒","num":760},{"id":"10044","title":"土豆炖翅根","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/11/10044.jpg","collect_num":"758","food_str":"土豆 翅根 葱 姜 料酒","num":758},{"id":"33783","title":"美人豆浆","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/34/33783.jpg","collect_num":"758","food_str":"黄豆 红豆 绿豆 黑豆 黑米","num":758}]
     */

    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 : 8289
         * 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.fenghongzhang.mvp.food.mvp.contract;

import com.fenghongzhang.mvp.food.entity.Food;
import com.fenghongzhang.mvp.model.IModel;
import com.fenghongzhang.mvp.view.IActivity;
import com.fenghongzhang.mvp.view.IView;

import java.util.List;

import okhttp3.Callback;
/**
 * 用来约束 Model 和 View的功能接口
 * 在这里定义要使用的方法
 */
public interface FoodContract {
    
    

    //请求数据
    public interface IFoodModel extends IModel{
    
    
       void getFoodData(Callback callback);
    }

    //展示数据
    public interface IFoodView extends IView {
    
    
       void initAdapter(List<Food.DataBean> food);
    }
}

FoodModel

package com.fenghongzhang.mvp.food.mvp.model;

import android.widget.Toast;

import com.fenghongzhang.mvp.food.mvp.contract.FoodContract;
import com.fenghongzhang.mvp.model.BaseModel;

import java.io.IOException;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class FoodModel extends BaseModel implements FoodContract.IFoodModel {
    
    

    @Override
    public void getFoodData(Callback callback) {
    
    
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        OkHttpClient build = builder.build();

        Request.Builder request = new Request.Builder();
        Request build1 = request.get().url("http://www.qubaobei.com/ios/cf/dish_list.php?stage_id=1&limit=20&page=1").build();

        build.newCall(build1).enqueue(callback);
    }
}

FoodPresenter

package com.fenghongzhang.mvp.food.mvp.presenter;

import android.util.Log;

import com.fenghongzhang.mvp.food.entity.Food;
import com.fenghongzhang.mvp.food.mvp.contract.FoodContract;
import com.fenghongzhang.mvp.model.IModel;
import com.fenghongzhang.mvp.presenter.BasePresenter;
import com.fenghongzhang.mvp.view.IView;
import com.google.gson.Gson;

import java.io.IOException;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;

//在M和V中交互
public class FoodPresenter extends BasePresenter<FoodContract.IFoodModel,FoodContract.IFoodView> {
    
    

    private static final String TAG = "FoodPresenter";
    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 string = response.body().string();
                Food food = new Gson().fromJson(string, Food.class);
//                Log.i(TAG, "onResponse: "+food.getData().get(0).getTitle());
                mView.initAdapter(food.getData());
            }
        });
    }


}

FoodActivity

package com.fenghongzhang.mvp.food.mvp.view;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;

import android.os.Bundle;

import com.fenghongzhang.mvp.R;
import com.fenghongzhang.mvp.food.adapter.FoodAdapter;
import com.fenghongzhang.mvp.food.entity.Food;
import com.fenghongzhang.mvp.food.mvp.contract.FoodContract;
import com.fenghongzhang.mvp.food.mvp.model.FoodModel;
import com.fenghongzhang.mvp.food.mvp.presenter.FoodPresenter;
import com.fenghongzhang.mvp.view.BaseActivity;
import com.fenghongzhang.mvp.view.IActivity;
import com.fenghongzhang.mvp.view.IView;

import java.util.List;

public class FoodActivity extends BaseActivity<FoodPresenter> implements FoodContract.IFoodView {
    
    
    private RecyclerView rv;

    private FoodPresenter foodPresenter;
    @Override
    public int bindLayout() {
    
    
        return R.layout.activity_food;
    }

    @Override
    public void initView() {
    
    
        rv = (RecyclerView) findViewById(R.id.rv);
        foodPresenter = new FoodPresenter(new FoodModel(),this);
    }

    @Override
    public void initData() {
    
    
        foodPresenter.getData();
    }

    @Override
    public void showLoading() {
    
    

    }

    @Override
    public void hideLoading() {
    
    

    }

    @Override
    public void initAdapter(List<Food.DataBean> food) {
    
    
        final FoodAdapter foodAdapter = new FoodAdapter(food, this);
        runOnUiThread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                rv.setLayoutManager(new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL));

                rv.setAdapter(foodAdapter);
            }
        });

    }
}

ButterKnife的使用

https://blog.csdn.net/shuai_ge_feng/article/details/105322420

Dagger2的使用

https://blog.csdn.net/shuai_ge_feng/article/details/108682307

猜你喜欢

转载自blog.csdn.net/shuai_ge_feng/article/details/113780304