MVP背景
MVP 作为框架思想之一,同时作为MVC的演化产物 解决了MVC所存在的一些短板。
MVP三个角色
1、Model -
提供数据的存取功能,Presenter 通过M 层获取或存储数据。
2、View-
安卓中通常指Activity 或View 控件, 他含有一个Presenter 变量,通常View 通过实现一个接口,将View 上的操作转角给P 进行实现,最后Presenter 调用View 接口将结果返回给View 。
3、Presenter -
负责连接View 和Model 这也是MVP 与MVC 不同的核心之处,他从M 层获取数据后返回给View, 使得V 与M 之间没有耦合,职责更清晰。
两种实现
实现MVP 通常有两种方式:
1、将Activity 或Fragment 作为Presenter 抽象一个View 层。
2、将Activity或Fragment 作为View 抽象一个Presenter 层。
第一种方式的缺点是无法重用Presenter 如果需要在Dialog 或Adapter 中实现P 就需要根据其特性重写对应的P基类,这样会导致一个Activity 有多个不同的P 基类产生。
因此通常将重用P 的方式2 作为mvp 的方案。下面使用第二种方式实现一个简单的案例。
案例
1、BaseView
BaseView 放置一些View 共有的一些行为。
public interface BaseView {
//可放置一些View 共有的行为
public void showBeforRequest(); //请求前弹窗
}
2、BasePresenter
BasePresenter 中关联 View 对象。
public abstract class BasePresenter {
public V mV;
public void attach(V baseView) {
this.mV = baseView;
}
}
3、BaseActivity
通常会定义一个BaseActivity 这里绑定Presenter 与Activity,实现一些通用的Activity 的逻辑。
public abstract class BaseActivity extends AppCompatActivity implements BaseView {
public P presenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Presenter 的实例化延迟到具体Activity 和Fragment
presenter = initPresenter();
presenter.attach(this);
}
public abstract P initPresenter();
@Override
public void showBeforRequest() {
Toast.makeText(getApplication(), "加载中。。。", Toast.LENGTH_SHORT).show();
}
}
上面是MVP 的base 类的基础实现,下面开始具体业务。
4、具体View
某个具体View 需要对View 更新的行为。
public interface FruitView extends BaseView {
//某个业务的具体行为
void showFruitList(List strings);
}
5、具体Presenter
对应具体Presenter 需要进行的数据领域的行为。
public class FruitPresenter extends BasePresenter {
public void getFruitData() {
List list = new ArrayList<>();
list.add("香蕉");
list.add("水黎");
list.add("菠萝");
list.add("苹果");
list.add("荔枝");
mV.showFruitList(list);
}
}
6、具体Activity 或Fragment
具体Activity 中关联对应Presenter。
public class MVPMainActivity extends BaseActivity implements FruitView {
Button mButton;
RecyclerView mRecyclerView;
List fruitData;
FruitAdapter fruitAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_m_v_p_main);
mButton = findViewById(R.id.btn_get);
mRecyclerView = findViewById(R.id.rv);
mButton.setOnClickListener(v -> {
showBeforRequest();
presenter.getFruitData();
});
}
@Override
public FruitPresenter initPresenter() {
return new FruitPresenter();
}
@Override
public void showFruitList(List strings) {
this.fruitData = strings;
fruitAdapter = new FruitAdapter();
mRecyclerView.setAdapter(fruitAdapter);
mRecyclerView.setLayoutManager(new LinearLayoutManager(MVPMainActivity.this));
}
class FruitAdapter extends RecyclerView.Adapter {
@NonNull
@Override
public FruitViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(MVPMainActivity.this).inflate(R.layout.fruit_item, null, false);
FruitViewHolder viewHolder = new FruitViewHolder(view);
return viewHolder;
}
@Override
public void onBindViewHolder(@NonNull FruitViewHolder holder, int position) {
TextView viewById = holder.itemView.findViewById(R.id.tv_content);
viewById.setText(fruitData.get(position));
}
@Override
public int getItemCount() {
return fruitData.size();
}
class FruitViewHolder extends RecyclerView.ViewHolder {
public FruitViewHolder(@NonNull View itemView) {
super(itemView);
}
}
}
}