从github上的优秀实例看MVP模式

来源:互联网 发布:dede源码素材资源网 编辑:程序博客网 时间:2024/05/19 13:14

github上有一个关于MVP模式学习的实例https://github.com/antoniolg/androidmvp,虽然只有简单的几个类,却收获了几千个星。这个例子确实通俗易懂,直观的体现出了MVP模式的特点:


考虑这样一个需求,页面显示一个列表,数据源需要特别获取。

分析一下这个过程,页面首先显示出进度提示框表示正在加载,然后数据源获取数据并传给页面的列表进行渲染。

MVP模式,model ,view,presenter。。视图层只处理UI操作,包括显示dialog,拿到数据后的处理(关闭dialog并渲染列表),这里可以细分为关闭dialog和为列表的适配器设置数据列表。     presenter是视图层和数据层沟通的桥梁,控制着双方的行为。  数据源则负责获取数据并返回。


首先对三个类进行抽象:

1.视图层:

package com.antonioleiva.mvpexample.app.main;import java.util.List;public interface MainView {    void showProgress();    void hideProgress();    void setItems(List<String> items);    void showMessage(String message);}


2.数据层:

package com.antonioleiva.mvpexample.app.main;import java.util.List;public interface FindItemsInteractor {    interface OnFinishedListener {        void onFinished(List<String> items);    }    void findItems(OnFinishedListener listener);}

这里一个接口用来返回拿到的数据,接口中的方法将数据传入。在获取数据的方法里将这个接口传入,接口的实例化是在代理中实现的。


3.代理层:

package com.antonioleiva.mvpexample.app.main;public interface MainPresenter {    void onResume();    void onItemClicked(int position);    void onDestroy();}
视图层在调用onResume和onDestroy时的逻辑也要通过代理的方法实现。



下面是创建的实例,首先是数据实例:

1.数据层:

public class FindItemsInteractorImpl implements FindItemsInteractor {    @Override public void findItems(final OnFinishedListener listener) {        new Handler().postDelayed(new Runnable() {            @Override public void run() {                listener.onFinished(createArrayList());            }        }, 2000);    }    private List<String> createArrayList() {        return Arrays.asList(                "Item 1",                "Item 2",                "Item 3",                "Item 4",                "Item 5",                "Item 6",                "Item 7",                "Item 8",                "Item 9",                "Item 10"        );    }}

只有两个方法,也可以看成只有一个方法,就是拿到数据并通过回调接口返回。


2.视图层:
public class MainActivity extends Activity implements MainView, AdapterView.OnItemClickListener {    private ListView listView;    private ProgressBar progressBar;    private MainPresenter presenter;    @Override protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        listView = (ListView) findViewById(R.id.list);        listView.setOnItemClickListener(this);        progressBar = (ProgressBar) findViewById(R.id.progress);        presenter = new MainPresenterImpl(this, new FindItemsInteractorImpl());    }    @Override protected void onResume() {        super.onResume();        presenter.onResume();    }    @Override public boolean onCreateOptionsMenu(Menu menu) {        getMenuInflater().inflate(R.menu.main, menu);        return true;    }    @Override public boolean onOptionsItemSelected(MenuItem item) {        switch (item.getItemId()) {            case R.id.action_settings:                return true;            default:                return super.onOptionsItemSelected(item);        }    }    @Override protected void onDestroy() {        presenter.onDestroy();        super.onDestroy();    }    @Override public void showProgress() {        progressBar.setVisibility(View.VISIBLE);        listView.setVisibility(View.INVISIBLE);    }    @Override public void hideProgress() {        progressBar.setVisibility(View.INVISIBLE);        listView.setVisibility(View.VISIBLE);    }    @Override public void setItems(List<String> items) {        listView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, items));    }    @Override public void showMessage(String message) {        Toast.makeText(this, message, Toast.LENGTH_LONG).show();    }    @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) {        presenter.onItemClicked(position);    }}

视图层拥有一个代理实例,将几个生命阶段的逻辑以及列表项点击全部托管给代理进行处理,自己只负责实现接口中的几个ui操作方法。


3.代理层:

public class MainPresenterImpl implements MainPresenter, FindItemsInteractor.OnFinishedListener {    private MainView mainView;    private FindItemsInteractor findItemsInteractor;    public MainPresenterImpl(MainView mainView, FindItemsInteractor findItemsInteractor) {        this.mainView = mainView;        this.findItemsInteractor = findItemsInteractor;    }    @Override public void onResume() {        if (mainView != null) {            mainView.showProgress();        }        findItemsInteractor.findItems(this);    }    @Override public void onItemClicked(int position) {        if (mainView != null) {            mainView.showMessage(String.format("Position %d clicked", position + 1));        }    }    @Override public void onDestroy() {        mainView = null;    }    @Override public void onFinished(List<String> items) {        if (mainView != null) {            mainView.setItems(items);            mainView.hideProgress();        }    }    public MainView getMainView() {        return mainView;    }}

首先代理的构造器要传入视图和数据两个实例,然后通过调用这两个实例的方法来完成控制。这里代理的几个任务有,在视图销毁时设置解绑,对列表项点击事件的响应,在视图刚开始时控制视图显示等待中并开始控制数据源获取数据,在数据获取完成后通过实现的回调接口将数据传给视图层。

需要注意的是代理实现了数据层的接口,以此来接收并处理数据。


0 0
原创粉丝点击