android mvp实例

由于以前的MVC模式,不能很好的实现MODEL和View的分离,便出现了MVC模式的变种:MVP。

MVP模式的出现,就是为了彻底分离model与view,使项目的整理结构清晰。

由于MVP模式有很多变种,这些变种的出现多是为了处理MVP模式的一些短板,这些变种的区别大体上遵循的原则是实现model与view的分离,不同点在于对model,presenter,view的分工略有不同。

目前于我而言,还是处于一个学习的阶段,所以呢,还是从简单的易懂的方式开始学习。

我们以实例来学习编写这种模式,写程序之前,首先要明确的一点是:分工。

下面的实例分工原则是:view负责数据展示以及与用户交互,presenter负责view与model的通信,model负责获取数据。

任务分配完成,下面开始编码,以下实现的功能很简单,okhttp去请求一段图文列表并展示。

大致了解了MVP是干什么了以后,写代码感觉还是没什么思路,比如此时此刻的我。好吧,我们都知道MVP模式其实需要写很多的接口,这些接口实际上是为了实现模块之间的解耦。那么如何写这些接口呢?

首先,我们要做的就是从网络上载入一段列表数据到手机上展示。View层用来展示这些数据,那么首先就来写View层的接口。接口需要有的功能是加载过程中的进度条显示与隐藏,追加图文数据,加载失败或无数据。

public interface IImagesView
{
    void addImageNews(List<ImageBean> imageNews);
    void showLoadProgress();
    void hideLoadProgress();
    void showLoadFailed();
}

接着,我们知道MVP中的View通常指的是与用户交互的Fragment,Activity,View等。那么我们需要在Activity中去实现刚才定义的接口。

public class MainActivity extends Activity implements IImagesView
{

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

    @Override
    public void addImageNews(List<ImageBean> imageNews)
    {

    }

    @Override
    public void showLoadProgress()
    {

    }

    @Override
    public void hideLoadProgress()
    {

    }

    @Override
    public void showLoadFailed()
    {

    }
}

接着继续思考,首先这个Activity作为View层接口的实现类,需要展示数据,那么这些数据从哪里来呢?我们清楚,数据需要从model中来,那么我们首先让model去获取数据。接着,定义一个接口用于处理获取数据成功或是失败的回掉处理。

public interface LoadImageNewsListener
{
    void success(List<ImageBean> data);
    void failed(String msg,Exception e);
}

定义一个用于model层加载数据的接口

/**
 * model层加载数据接口类
 * @author Administrator
 *
 */
public interface IImageModel
{
    void loadImageNews(LoadImageNewsListener listener);
}

定义Model层加载数据的实现类

/**
 * Model层实现类,用于获取网络数据
 *
 * @author Administrator
 *
 */
public class ImageModelImpl implements IImageModel
{

    @Override
    public void loadImageNews(final LoadImageNewsListener listener)
    {
             //这里发起请求数据,同时在拿到数据以后用接口去处理,这个接口在后续的Presener中实现具体的处理(Presener会将数据较给View的接口类处理)
        OkGo.get(Urls.IMAGES_URL).cacheKey("imagenews").cacheMode(CacheMode.DEFAULT).execute(new StringCallback()
        {
            @Override
            public void onSuccess(String arg0, okhttp3.Call arg1, okhttp3.Response arg2)
            {
                Log.i("resposne:", arg0);
                Log.i("resposne:", arg2.body().toString());
                listener.onSuccess(JSON.parseArray(arg2.body().toString(), ImageBean.class));
            };

        @Override
        public void onError(okhttp3.Call call, okhttp3.Response response, Exception e)

        {
            Log.i("error:", response.body().toString());
            Log.i("error:", e.getMessage());
            listener.onFailed(response.body().toString(), e);
            };
        });
    }
}

好了,现在MODEL已经取到数据,而View就等着去拿Model里的数据了,但是我们要让Model和View分离,显然,View中不可以持有model的引用,那么关键的地方到了,现在就用Presenter去实现。

/**
 * Presenter实现类,要实现model与View的通信,并处理一些业务逻辑
 *
 * @author Administrator
 *
 */
public class ImagePresenterImpl implements IImageNewsPresenter, LoadImageNewsListener
{
    private IImagesView mIImagesView;
    private IImageModel mIImageModel;

    public ImagePresenterImpl(IImagesView iamgeview, IImageModel imagemodel)
    {
    this.mIImagesView = iamgeview;
    this.mIImageModel = imagemodel;
    }

    @Override
    public void loadImageNews()
    {
        mIImagesView.showLoadProgress();
        mIImageModel.loadImageNews(this);
    }

    @Override
    public void onSuccess(List<ImageBean> data)
    {
        mIImagesView.hideLoadProgress();
        mIImagesView.addImageNews(data);
    }

    @Override
    public void onFailed(String msg, Exception e)
    {
        mIImagesView.hideLoadProgress();
        mIImagesView.showLoadFailed();
    }

}

到这里除了还没有在View中显示出来,其实大部分逻辑都写完了,将前后的流程串起来后,其实我做了这么一件事。
一、我在model层中定义了一个去获取数据的接口 IImageModel ,然后再model层的实现类 ImageModelImpl 中发请求从网络端去获取数据。
二、model层的接口方法 loadImageNews 的参数列表中持有一个和Presener层通信的引用接口 LoadImageNewsListener(这个接口处理加载数据成功与失败)。
三、在Presener层中我定义了一个接口用于加载数据,同时在Presener的实现类中实现了两个接口,分别为Presener层中加载数据的接口,和加载数据结果的监听接口(这个接口在model层中获取数据时保留有引用);同时,Presener层持有Model层的接口引用和View层的接口引用,分别处理了下面这些事:1、加载数据时通知View的接口显示进度条,同时通知model取获取数据。2、实现了获取数据结果以后的处理,若成功,通知View的接口类隐藏进度条,同时通知View的接口类加载数据;失败则通知View接口类隐藏进度条,同时显示出错误信息。

OK,以上描述不知各位是否思路上会有一点清晰了呢?其实我们还有事情没有做,现在Presener让model取到数据后,通知View接口类去做的事情,不知道View做了没有呢?
显然,还没有做呢,View接口类的实现类其实就是MainActivity,这就是我们所说的View,MainActivity实现了View的接口类,我们需要做的事情是,实现其中的方法,同时把从Presener抽出来的数据显示出来,如下:

public class MainActivity extends Activity implements IImagesView
{

    private ListView mListView;

    private ImageAdapter mAdapter;

    private Dialog mDialog;

    private IImageNewsPresenter presenter;

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

        mListView = (ListView) findViewById(R.id.listview);
        mAdapter = new ImageAdapter(this);
        presenter = new ImagePresenterImpl(this);

        mListView.setAdapter(mAdapter);
        presenter.loadImageNews();
    }

    @Override
    public void addImageNews(List<ImageBean> imageNews)
    {
        mAdapter.refreshData(imageNews);
    }

    @Override
    public void showLoadProgress()
    {
        mDialog = new ProgressDialog(this);
        mDialog.show();
    }

    @Override
    public void hideLoadProgress()
    {
        if (null != mDialog)
        {
            mDialog.dismiss();
        }
    }

    @Override
    public void showLoadFailed()
    {
        Toast.makeText(this, "访问出现错误......", Toast.LENGTH_LONG).show();
    }
}

由此,我们可以总结出mvp模式的一般特点:

* Model层,数据层,主要负责网络层和数据库层的交互
* View层,UI层,主要负责数据的显示,并向Presener报告用户的行为
* Presener,从Model层中取数据,并应用到UI层,决定UI层要显示什么,并响应用户的行为.

demo下载地址

·

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值