MVP的实践
来源:互联网 发布:淘宝怎么刷単赚钱 编辑:程序博客网 时间:2024/05/22 06:55
背景:
之前看到有朋友在项目中用mvp模式,他推荐我去看看google托管在github上的一个demo,然后我就下载下来看,结果是看得稀里糊涂的,感觉几个接口调来调去的,让我不够用的大脑更加混乱了。然后,我又在网上搜索一些文章看,结果绝大部分文章标题是:Retrofit+RxJava+Dragger2+MVP模式,一下子包装这么多框架进去,更是让看了之后,更是不会了。后面自己想:既然整体看不懂,为什么不一个一个的看呢?那就先只看纯MVP的demo,后面的Retrofit,RxJava, Dragger2排队一个一个来学习好了。在化繁为简的轻情况下,终于对MVP有所理解,下面我讲解下自己当时学习的过程,一是加深自己的理解,二是希望别人也能容易看懂。我会便用2个例子来构建,见如下结构:
案例一:
在MainActivty里面做用户登录的操作:
view: IUserLoginView MainActivity
module: IUser(接口), IUserImpl(接口的实现类)OnLoginListener(登录结果的回调)
presenter: UserLoginPresenter
1.先说module层要写些什么:大家对这个可能有点疑惑,因为我当初也是不知道这个moudle到底该写些什么好,只知道概念上说:业务逻辑在这里做。后面思索:在没有MVP的时候,我们要从网络上获取数据,或是将用户数据传递给服务端,不就是具体的业务逻辑吗?只不过以前是写在一个类中,现在将其划分给module就好了。以注册和登录为例,我们要将用户数据交给服务端,那么,我猜想你应该知道要怎么写了,参考如下:
public interface IUser { void login(String name,String psw,OnLoginListener loginListener);}/** * 登录的具体业务类 */public class IUserImpl implements IUser{ @Override public void login(String name, String psw, OnLoginListener loginListener) { if("123".equals(name)&&"123".equals(psw)){ User user = new User(name,psw); loginListener.onloginSucced(user); }else{ loginListener.onloginFailed(); } }}
2.再来看view层怎么写:看这个的时候,又难倒我了,再次回想没有MVP的时候,我们要拿到拿到view上的内容如用户的姓名和密码,登录之后页面要跳转,吐司提示等。所以,和view相关的,界面展示相关的,就都写在这里,另外,也不怕写漏掉,接口编程,想往里面添加就添加。
/** * 只和view相关的逻辑 */public interface IUserLoginView { String getUserName(); String getPassword(); void toDetailActivity(User user);}
3.最后是Module层:连接view和module层,将module中获取的数据设置在view上,完成交互。(我的理解是:presenter调view和module完成交互)。
/** * presenter 主要看要完成什么样的交互 * */public class UserLoginPresenter { //1. 登录: private IUser iUser; private IUserLoginView userLoginView; public UserLoginPresenter(IUserLoginView view){ this.userLoginView = view; this.iUser = new IUserImpl(); } //登录过程: public void login(){ iUser.login(userLoginView.getUserName(), userLoginView.getPassword(), new OnLoginListener() { @Override public void onloginSucced(User user) { userLoginView.toDetailActivity(user); } @Override public void onloginFailed() { } }); }}
4.最后看MainActivity如何做登录处理:
public class MainActivity extends AppCompatActivity implements IUserLoginView { private EditText et_name; private EditText et_psw; private Button btn_login; //调用Presenter: private UserLoginPresenter presenter = new UserLoginPresenter(this); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { et_name = (EditText) findViewById(R.id.et_name); et_psw = (EditText) findViewById(R.id.et_psw); btn_login = (Button) findViewById(R.id.btn_login); btn_login.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //View 要做的事情:交给presenter去做: presenter.login(); } }); } @Override public String getUserName() { return et_name.getText().toString(); } @Override public String getPassword() { return et_psw.getText().toString(); } @Override public void toDetailActivity(User user) { Intent intent = new Intent(this,DetailActivity.class); startActivity(intent); }}//布局:<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.mvptest.view.MainActivity" android:orientation="vertical" > <EditText android:id="@+id/et_name" android:layout_width="match_parent" android:layout_height="40dp" /> <EditText android:id="@+id/et_psw" android:layout_width="match_parent" android:layout_height="40dp" /> <Button android:id="@+id/btn_login" android:layout_width="match_parent" android:layout_height="50dp" /></LinearLayout>
5.整个调用过程如下: activity中点击登录按钮的时候,调用presenter中的login方法,而presenter中的login又是调用module中的login,module中login方法需要的参数来源又是通过view中的方法得来。
好了,第一个用MVP构建的登录页面完成了,现在我们再接着练习下一个例子:在recycleview页面中如何用MVP来做:
案例二:
view: IDetailView
module:IDetailData , IDetailDataImpl
presenter: DetailDataPresenter
bean: DetailDataBean(只有name,age,addresss三个字段)
1. moudle层:获取数据
//接口类:public interface IDetailData { ArrayList<DetailDataBean> getAllDetailData();}//接口的实现类:public class IDetailDataImpl implements IDetailData { @Override public ArrayList<DetailDataBean> getAllDetailData() { ArrayList<DetailDataBean> list = new ArrayList<>(); for(int i = 0;i<20;i++){ DetailDataBean bean = new DetailDataBean("name"+i,i,"address"+i); list.add(bean); } return list; }}
2. view层:
public interface IDetailView { void setAdapter(ArrayList<DetailDataBean> lists);}
3.presenter层:
/** * * view 和 module 层的交互: */public class DetailDataPresenter { private IDetailData iDetailData;//数据源 private IDetailView iDetailView;//将其绑定到activity public DetailDataPresenter(DetailActivity view){ this.iDetailData = new IDetailDataImpl(); this.iDetailView = view; } public void getData(){ // iDetailData.getAllDetailData(); //view层做业务: iDetailView.setAdapter(iDetailData.getAllDetailData()); }}
4.Activity:
public class DetailActivity extends AppCompatActivity implements IDetailView { private RecyclerView mRecyclerView; private DetailDataPresenter presenter = new DetailDataPresenter(this); private HomeAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_detail); initView(); presenter.getData(); } private void initView() { mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview); } @Override public void setAdapter(ArrayList<DetailDataBean> lists) { mAdapter = new HomeAdapter(lists); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); mRecyclerView.setAdapter(mAdapter); } public class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.MyViewHolder>{ private ArrayList<DetailDataBean> mData; public HomeAdapter(ArrayList<DetailDataBean> lists) { this.mData = lists; } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { MyViewHolder holder = new MyViewHolder(LayoutInflater.from(DetailActivity.this).inflate(R.layout.item_home, parent, false)); return holder; } @Override public void onBindViewHolder(MyViewHolder holder, int position) { holder.tv1.setText(mData.get(position).getName()); holder.tv2.setText(mData.get(position).getAge()+""); holder.tv3.setText(mData.get(position).getAddress()); } @Override public int getItemCount() { return mData.size(); } class MyViewHolder extends RecyclerView.ViewHolder { TextView tv1; TextView tv2; TextView tv3; public MyViewHolder(View view) { super(view); tv1 = (TextView) view.findViewById(R.id.tv_name); tv2 = (TextView) view.findViewById(R.id.tv_age); tv3 = (TextView) view.findViewById(R.id.tv_address); } } }}//布局很简单:activity中放置一个recycleview. recucleview的item布局是放3个textview,就不贴出来了。
5.调用过程:activity中需要获取数据展示在adapter中,所以先调用presenter中的getData方法,而这个方法又是先调用moudle中的getAllDetailData方法,得到一个数据集合作为参数,返回给view中setAdapter方法。
以上是自己学习mvp的整体过程,google中的todoapp -mvp搭建如下:看个人的习惯吧,只要是符合MVP思想,都可以的。
public interface TaskDetailContract { interface View extends BaseView<Presenter> { void showTask(Task task); void showError(); void showTaskDeleted(); void showTaskMarkedComplete(); void showTaskMarkedActive(); boolean isActive(); } interface Presenter extends BasePresenter { void getTask(); void deleteTask(); void completeChanged(Task task, boolean isChecked); }}
- MVP的实践
- MVP + okHttpUtils的简单实践
- MVP实践
- MVP实践
- Android实践:MVC到MVP的演化
- Android MVP模式实践
- 类MVP实践报告
- Android Mvp实践
- android MVP 实践笔记
- MVP架构实践
- Retrofit实践(MVP+RxJava)
- Android Mvp实践
- Android MVP解析实践
- MVP理解与实践
- android MVP实践
- android 官方mvp实践
- MVP模式解析实践
- 在Android上用MVP模式编程的实践
- Windows14
- 工厂方法模式
- Windows下的Django安装与环境配置
- UVA 230
- jni方法的注册和调用
- MVP的实践
- 3174: [Tjoi2013]拯救小矮人
- [awk]练习2
- Vim 插件管理器概览
- Windows15
- CentOS7 安装Redis
- 网络请求 Gson解析
- ORACLE常用数据查询
- Windows16