zoukankan      html  css  js  c++  java
  • android MVP模式介绍与实战

    描述


    MVP模式是什么?MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。

    MVC和MVP的区别?


    为什么会出现MVP模式呢?这是因为原有的MVC模式有一些短板。比如在android开发中,activity充当着MVC中Controller的角色,但是在实际开发中处理view的逻辑和角色。当业务界面复杂时我的activity会显得很庞大。于是出现了MVP模式,它新增了一个Presenter角色用于处理数据和界面的模型以及逻辑,Activity仅仅用于展示界面和用户交互,这样就解决了MVC中角色不清的局面。
    所以,MVP与MVC的重大区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会直接从Model中读取数据而不是通过 Controller。
    在MVC里,View是可以直接访问Model的!从而,View里会包含Model信息,不可避免的还要包括一些业务逻辑。 在MVC模型里,更关注的Model的不变,而同时有多个对Model的不同显示,即View。所以,在MVC模型里,Model不依赖于View,但是View是依赖于Model的。不仅如此,因为有一些业务逻辑在View里实现了,导致要更改View也是比较困难的,至少那些业务逻辑是无法重用的。

    MVC模式结构

    • Model 业务逻辑和实体模型
    • Controller 对应Activity
    • View 视图以及布局文件

    Alt text

    MVP模式结构

    • Model: 业务逻辑和实体模型
    • View:用户交互和视图显示,在android中对应activity
    • Presenter: 负责完成View于Model间的逻辑和交互

    小节:MVP模式相当于在MVC模式中又加了一个Presenter用于处理模型和逻辑,将View和Model完全独立开,在android开发中的体现就是activity仅用于显示界面和交互,activity不参与模型结构和逻辑,

    #### 实战
    谷歌官网给了我们一个MVP模式实战的例子,它是一个类似记事本的app,源码地址在:https://github.com/googlesamples/android-architecture
    官方案例的框架图如下:
    enter image description here

    看完源码后发现其不适合初学者理解,于是我自己写了一个demo方便大家理解。
    demo源码地址:https://github.com/halibobo/AndroidMvpExample
    源码主要类的结构如下

    Alt text

    下面来看源码
    View层对应的是MainActivity,它继承了抽离出View所有操作方法的接口OperationView

    /**
     * *Created by su on 2016/6/22.
     */
        public interface OperationView {
    
        void showCreatingPhone();
    
        void showPhoneCountChange();
    
        void showNoPhone();
    
        void showFactoryBusy();
    
        void showCreatedPhone();
    }

    MainActivity具体对每个操作进行了具体的实现

     1 public class MainActivity extends AppCompatActivity implements OperationView {
     2 
     3     private ListView listView;
     4 
     5     private Button btnCreate;
     6 
     7     private PhonePresenter phonePresenter;
     8 
     9     private ProgressDialog mLoadingDialog;
    10     ArrayAdapter<Phone> arrayAdapter;
    11     private Toast toast;
    12     @Override
    13     protected void onCreate(Bundle savedInstanceState) {
    14         super.onCreate(savedInstanceState);
    15         setContentView(R.layout.activity_main);
    16         Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    17         setSupportActionBar(toolbar);
    18 
    19         PhoneFactory phoneFactory = new PhoneFactory();
    20         phoneFactory.createPhone("nokia",555);
    21         phonePresenter = new PhonePresenter(phoneFactory, this);
    22         btnCreate = (Button) findViewById(R.id.btnCreate);
    23         listView = (ListView) findViewById(R.id.listView);
    24         arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, phoneFactory.getPhonesList());
    25         btnCreate.setOnClickListener(new View.OnClickListener() {
    26             @Override
    27             public void onClick(View v) {
    28                 phonePresenter.addPhone(new Phone("iphone", 4000+ new Random().nextInt(1000)));
    29             }
    30         });
    31 
    32         listView.setAdapter(arrayAdapter);
    33 
    34         listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    35             @Override
    36             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    37                 phonePresenter.removePhone(position);
    38             }
    39         });
    40 
    41     }
    42 
    43     @Override
    44     public void showCreatingPhone() {
    45         mLoadingDialog = new ProgressDialog(this);
    46         mLoadingDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
    47         mLoadingDialog.setMessage("工厂正在生产手机");
    48         mLoadingDialog.setCancelable(true);
    49         mLoadingDialog.show();
    50     }
    51 
    52     @Override
    53     public void showPhoneCountChange() {
    54         arrayAdapter.notifyDataSetChanged();
    55     }
    56 
    57     @Override
    58     public void showNoPhone() {
    59         findViewById(R.id.noPhone).setVisibility(View.VISIBLE);
    60     }
    61 
    62     @Override
    63     public void showFactoryBusy() {
    64         showToast("工厂繁忙,请稍后再试!");
    65     }
    66 
    67     @Override
    68     public void showCreatedPhone() {
    69         if (mLoadingDialog != null && mLoadingDialog.isShowing()) {
    70             mLoadingDialog.dismiss();
    71         }
    72         mLoadingDialog = null;
    73         showToast("新生产出一台手机!");
    74         findViewById(R.id.noPhone).setVisibility(View.GONE);
    75     }
    76 
    77     private void showToast(String string) {
    78         if (toast == null) {
    79             toast = Toast.makeText(this, string, Toast.LENGTH_SHORT);
    80         }else{
    81             toast.setText(string);
    82         }
    83         toast.show();
    84     }
    85 }

    Model层对应的是PhoneFactory,它处理和数据相关的一些简单操作

     1 /**
     2  * Created by su on 2016/6/22.
     3  */
     4 
     5 /**
     6  * 手机工厂类
     7  */
     8 
     9 public class PhoneFactory {
    10     private ArrayList<Phone> phonesList = new ArrayList<>();
    11 
    12 
    13     public void addPhone(Phone phone) {
    14         phonesList.add(phone);
    15     }
    16 
    17     public void removePhone(Phone phone) {
    18         phonesList.remove(phone);
    19     }
    20 
    21     public void removePhone(int index) {
    22         if (index >= 0 && index < phonesList.size()) {
    23             phonesList.remove(index);
    24         }
    25     }
    26 
    27     public void createPhone(String name, double price) {
    28         Phone phone = new Phone(name, price);
    29         phonesList.add(phone);
    30     }
    31 
    32     public ArrayList<Phone> getPhonesList() {
    33         return phonesList;
    34     }
    35 
    36     public int getPhoneCounts() {
    37         return phonesList.size();
    38     }
    39 }

    下面是最为重要的Presenter层 对应代码中的PhonePresenter,它处理界面逻辑和数据模型等,源码如下:

     1 public class PhonePresenter implements TaskPresenter{
     2 
     3     private final PhoneFactory phoneFactory;
     4     private final OperationView operationView;
     5 
     6     private static final long createPhoneTime = 2000;
     7     private static final int msgWhat = 0x102;
     8 
     9 
    10     public PhonePresenter(@NonNull PhoneFactory phoneFactory, @NonNull OperationView operationView) {
    11         this.phoneFactory = phoneFactory;
    12         this.operationView = operationView;
    13     }
    14 
    15     @Override
    16     public void addPhone(Phone phone) {
    17         operationView.showPhoneCountChange();
    18         if (mHandler.hasMessages(msgWhat)) {
    19             operationView.showFactoryBusy();
    20             return;
    21         }
    22         Message message = new Message();
    23         message.what = msgWhat;
    24         message.obj = phone;
    25         mHandler.sendMessageDelayed(message, createPhoneTime);
    26         operationView.showCreatingPhone();
    27     }
    28 
    29     @Override
    30     public void removePhone(int index) {
    31         phoneFactory.removePhone(index);
    32         if (phoneFactory.getPhoneCounts() <= 0) {
    33             operationView.showNoPhone();
    34         }
    35         operationView.showPhoneCountChange();
    36     }
    37 
    38     @Override
    39     public void removePhone(Phone phone) {
    40 
    41     }
    42 
    43     public ArrayList<Phone> getPhones() {
    44         ArrayList<Phone> phones = phoneFactory.getPhonesList();
    45         if (phones.isEmpty()) {
    46             operationView.showNoPhone();
    47         }
    48         return phones;
    49     }
    50 
    51     private Handler mHandler = new Handler() {
    52         @Override
    53         public void handleMessage(Message msg) {
    54             super.handleMessage(msg);
    55             phoneFactory.addPhone((Phone)msg.obj);
    56             operationView.showCreatedPhone();
    57             operationView.showPhoneCountChange();
    58         }
    59     };
    60 }

    运行效果图如下:

    Alt text

    总结

    使用MVP模式会使得代码多出一些接口但是使得代码逻辑更加清晰,尤其是在处理复杂界面和逻辑时,我们可以对同一个activity将每一个业务都抽离成一个Presenter,这样代码既清晰逻辑明确又方便我们扩展。当然如果我们的业务逻辑本身就比较简单的话使用MVP模式就显得,没那么必要。所以我们不需要为了用它而用它,具体的还是要要业务需要

    谢谢大家

    demo地址在:https://github.com/halibobo/AndroidMvpExample

  • 相关阅读:
    multiprocessing 多进程实现 生产者与消费者模型JoinableQueue
    条件锁condition与Queue()
    threading 官方 线程对象和锁对象以及条件对象condition
    【NOIp训练】—子串查找VII(AC自动机+树链剖分+线段树)
    【NOIp训练】—子串查找VII(AC自动机+树链剖分+线段树)
    【HDU 5628】—Clarke and math(狄利克雷卷积快速幂)
    【HDU 5628】—Clarke and math(狄利克雷卷积快速幂)
    【NOIp2019模拟】题解
    【NOIp2019模拟】题解
    【NOIp2019模拟】题解
  • 原文地址:https://www.cnblogs.com/huolongluo/p/6608102.html
Copyright © 2011-2022 走看看