Android MVP 学习

本文详细解释了Android MVP架构的概念,对比MVC模式,并通过示例展示了如何将代码分离为Model、View和Presenter三个部分,使得代码更加清晰易维护。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android MVP 学习

我们都听说过MVC,但是MVP是什么鬼呢?

MVP概念

M对应Model,V对应View,P对应Presenter。

MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。作为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从直接Model中读取数据而不是通过 Controller。

MVC与MVP的示意图如下,
这里写图片描述
我们可以从图中,直观的看出,MVP与MVC的区别。

为什么使用MVP

那么为什么要使用MVP呢?

你是否把所有的代码都写在Activity中,但是,随着代码的维护,你会发现,Activity的代码会变得越来越臃肿,变的越来越难以维护。

这是因为,你把所有的代码都放在了View中,我们就可以把其中的代码分离开来,变成MVP模型。

使用MVP的好处有很多。其中的一个好处是可以使代码分离,变得更加清晰,我们修改界面(View)的时候,其他代码不需要改动(Model和Presenter)。当然好处不止这些。

MVP结构

MVP一般的结构如下,

-IModel,Model的接口,定义数据操作的方法
-Model,实现了Imodel接口
-IView,View的接口,定义页面显示的方法
-View,实现IView接口,一般为Activity
-Presenter

在MVP模式里,View只应该有简单的Set/Get的方法,用户输入和设置界面显示的内容,除此就不应该有更多的内容,绝不容许直接访问Model–这就是与MVC很大的不同之处。

接下来,举一个例子,该例子中,从网上获取内容,并在页面上显示。

IView代码

public interface IView {
    void setText(String content);//更新界面
}

View的具体实现,

public class MainActivity extends ActionBarActivity implements IView {
    private Button btn;
    private TextView tv;
    private MyPresenter mPresenter;
    final String strurl = "http://fabowang.sinaapp.com/";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mPresenter = new MyPresenter(this);
        btn = (Button) findViewById(R.id.button1);
        tv = (TextView) findViewById(R.id.textView1);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                mPresenter.printWeb(strurl);
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void setText(String content) {//更新页面
        // TODO Auto-generated method stub
        tv.setText(content);
    }
}

IModel代码,

public interface IModel {
    void getWeb(String url,IListener listen);//获取网络数据
}

其中IListener是自定义的接口,用来回调,代码如下,

public interface IListener {
    void callBack(String result);
}

Model的具体实现,

public class MyModel implements IModel {
    private String result = "";

    @Override
    public void getWeb(final String strurl, final IListener listener) {
        result = "";

        new Thread() {
            public void run() {
                URL url = null;
                try {
                    url = new URL(strurl);
                } catch (MalformedURLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                try {
                    URLConnection conn = url.openConnection();

                    BufferedReader rd = new BufferedReader(
                            new InputStreamReader(conn.getInputStream()));
                    String line = "";
                    while ((line = rd.readLine()) != null) {
                        System.out.println(line);
                        result = result + line;
                    }
                    listener.callBack(result);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            };
        }.start();
    }
}

Presenter代码如下,

public class MyPresenter {

    private IModel model;
    private IView view;
    private Handler mHandler = new Handler();

    public MyPresenter(IView view) {
        super();
        this.view = view;
        this.model = new MyModel();
    }

    public void printWeb(String url) {
        model.getWeb(url, new IListener() {
            @Override
            public void callBack(final String result) {
                // TODO Auto-generated method stub
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        //update view
                        view.setText(result);
                    }
                });
            }

        });
    }
}

Ok,让我们来梳理一下,

  1. Iview定义了更新view的接口,而MainActivity实现了该接口,另外MyPresenter含有Iview的引用,其会调用Iview.setText方法,进而调用MainActivity的具体接口实现,所以实现了更新界面。这是P调用V。

  2. View(即MainActivity)包含一个MyPersenter实例,其可以调用printWeb来得到网络内容,并更新界面。这是V调用P

  3. Model负责数据的获取,MyPresenter包含IModel的引用,其会调用Model的具体实现,得到数据。

  4. 由于多线程的问题,我们引入回调接口(IListener),在Model得到网络内容后,回调该接口,并更新UI(调用setText方法)。

不知读者有没有发现,虽然这样,代码感觉复杂了很多,但是结构很清晰,如果我们要修改获取网络数据的代码,我们直接修改Model的实现就好了,其他的代码,我们不需要修改。

本文的代码可以从github上获得,https://github.com/KingPaul/MVPDemo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值