IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android中MVP架构设计模式面试问题讲解 -> 正文阅读

[移动开发]Android中MVP架构设计模式面试问题讲解

1.MVC架构的特点

在Android当中,相比传统的MVC设计模式,View层(视图层)对应的是Android当中的布局文件。而布局文件是用XML格式来写的。但是这个XML布局文件它并不像Java Web端那么强大,能做的事情非常有限。而Controller所对应的Activity这个类,它不仅要处理业务逻辑,同时它也要处理Android当中的一些操作UI的功能。我们在实际项目开发过程中,有很多UI操作的逻辑写在Activity当中。这就导致Controller层中充斥了很多View层应当做的内容,从而使得Controller层非常冗余厚重。为了改善这一点,我们引入了MVP的架构模式。

2.MVP定义

<1>M:依然是业务逻辑和实体模型。

<2>V:对应于Activity,负责View的绘制以及与用户交互。

<3>P:负责完成VIew与Model间的交互。

3.MVP的优点

相较于MVC,MVP加入了Presenter层,我们便可以把之前Activity中作为Controller层的内容抽出来放入Presenter层,Activity则可以彻底加入View层了。这样我们也就完全切断了View层与Model层之间的联系。Activity与XML作为View层只对如何操作UI、渲染数据到界面上关心,而Model层则只关心如何获取数据源。至于数据源的二次处理以及数据注入UI则由Presenter关心,彻底切断数据与界面渲染。

4.MVP实例讲解

根据实例我们学习一下MVP,顺手搭建一套MVP的框架

首先是View层,我们先定义一个接口

/**
 * View层接口基类
 */
public interface MvpBaseIView {

}

这个接口基类其实是为了一会儿多个类的关联使用,里面是没有代码的。

接着是Activity的基类

/**
 * View层Activity基类,在子类中实现MvpBaseIView子类
 */
public abstract class MvpBaseActivity<T extends MvpBaseIPresenter> extends AppCompatActivity{

    protected Bundle savedInstanceState;
    protected T mPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //在界面未初始化之前调用的初始化窗口
        initWindows();
        if (initArgs(getIntent().getExtras())) {
            this.savedInstanceState = savedInstanceState;
            requestWindowFeature(Window.FEATURE_NO_TITLE);
            setContentView(getContentLayoutId());
            initWidget();
            mPresenter = getPresenterImpl();
            initData();
        } else {
            finish();
        }
    }

    /**
     * 初始化窗口
     */
    protected void initWindows() {

    }

    /**
     * 初始化相关参数
     *
     * @param bundle 参数bundle
     * @return 如果参数正确返回true, 错误返回false
     */
    protected boolean initArgs(Bundle bundle) {
        return true;
    }

    /**
     * 得到当前界面的资源文件Id
     *
     * @return 资源文件Id
     */
    protected abstract int getContentLayoutId();

    /**
     * 初始化控件
     */
    protected void initWidget() {

    }

    /**
     * 初始化数据
     */
    protected void initData() {

    }

    protected abstract T getPresenterImpl();
}

这样View层的两个基类就都有了。

接下来是Model层的两个

Model层回调接口基类

public interface MvpBaseCallBack {

}

Model层接口基类

public interface MvpBaseIModel {

}

Model基类

public class MvpBaseModel<T extends MvpBaseCallBack> {

    protected T callback;
    protected Context context;

    public MvpBaseModel(Context context, T callback) {
        this.context = context;
        this.callback = callback;
    }
}

最后就是我们的Presenter层

Presenter接口基类

/**
 * Presenter层接口基类
 */
public interface MvpBaseIPresenter {

}

Presenter基类

public abstract class MvpBasePresenter<T extends MvpBaseIModel,U extends MvpBaseIView> {

    protected T mModel;
    protected U iView;

    public MvpBasePresenter(Context context,U mView) {
        mModel = getModelImp();
        iView = mView;
    }

    protected abstract T getModelImp();
}

这样基类就完成了。我们可以看到,Activity中持有Presenter的对象,而Presenter中又持有IView和Model的对象。这样三者就联系在了一起。但是Activity和Model之间却没有直接的关联。

接下来是我们对于基类的使用。

首先先上一个实体类,模拟网络请求返回的实体

public class Entity {
    private String str;
    private int hide;

    public Entity(String str, int hide) {
        this.str = str;
        this.hide = hide;
    }

    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }

    public int getHide() {
        return hide;
    }

    public void setHide(int hide) {
        this.hide = hide;
    }
}

接着就是我们的View层两大件

/**
 * View层视图接口
 */
public interface DemoIView extends MvpBaseIView {
    void showText(String str);
    void showView();
    void hideView();
    String getXText();
}

这里可以看到View层接口我定义了四个动作,分别是显隐控件和设置获取TextView上的文字,这个要根据具体页面设置。

/**
 * View层视图实现类
 */
public class DemoActivity extends MvpBaseActivity<DemoIPresenter> implements DemoIView{

    private TextView tv_center;
    private View view_gang;

    @Override
    protected int getContentLayoutId() {
        return R.layout.activity_main;
    }

    @Override
    protected void initWidget() {
        tv_center = findViewById(R.id.tv_center);
        view_gang = findViewById(R.id.view_gang);
    }

    @Override
    protected void initData() {
        mPresenter.getData();
    }

    @Override
    protected DemoIPresenter getPresenterImpl() {
        return new DemoPresenter(this,this);
    }

    @Override
    public void showText(String str) {
        tv_center.setText(str);
    }

    @Override
    public void showView() {
        view_gang.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideView() {
        view_gang.setVisibility(View.GONE);
    }

    @Override
    public String getXText() {
        return tv_center.getText().toString().trim();
    }
}

Activity实现了IView的接口,并且实现了里面的接口方法,将定义的动作表现在了界面上。这里注意,我们在getPresenterImpl中返回了Presenter类的实例,并且该Activity还实现了IView接口。

下来便是我们的Model层

public interface DemoCallback extends MvpBaseCallBack {
    void success(Entity entity);
    void failure();
}

Callback中规中矩,还是成功和失败两个接口。

接着是Model接口类

public interface DemoIModel extends MvpBaseIModel {
    void getData(String strEnter);
}

Model实现类?

public class DemoModel extends MvpBaseModel<DemoCallback> implements DemoIModel {

    public DemoModel(Context context, DemoCallback callback) {
        super(context, callback);
    }

    @Override
    public void getData(String strEnter) {
        try {
            new Thread().sleep(2000);
            if (strEnter.equals("11111")){
                //成功
                callback.success(new Entity("xixixxi",0));
            }else{
                //失败
                callback.failure();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Model类中我们在getData方法中模拟了一个网络请求,并进行了回调。

这样我们的Model层也编写完成了。

下来就是Presenter层了。

我们先进行接口设计

public interface DemoIPresenter extends MvpBaseIPresenter {
    void getData();
}

由于我们只有一个获取界面数据的需求,所以这里只定义了一个接口方法

public class DemoPresenter extends MvpBasePresenter<DemoIModel,DemoIView>
        implements DemoIPresenter,DemoCallback{

    private Context mContext;

    public DemoPresenter(Context context, DemoIView mView) {
        super(context, mView);
        mContext = context;
    }

    @Override
    protected DemoIModel getModelImp() {
        return new DemoModel(mContext,this);
    }

    @Override
    public void success(Entity entity) {
        iView.showText(entity.getStr());
        if (entity.getHide() == 0) {
            iView.hideView();
        }else{
            iView.showView();
        }
    }

    @Override
    public void failure() {
        ToastUtil.toastWord(mContext,"错误");
    }

    @Override
    public void getData() {
        mModel.getData(iView.getXText());
    }
}

在Presenter的实现类中,一方面是刚才我们定义的接口方法getData中调用了Model层的方法。另一方面是我们在回调中调用了IView接口中方法对界面进行了操作。当然还有在getModelImp中返回我们创建的Model类实例。这就是一套完整的MVP设计模式。我个人觉得MVP除了解耦,最大的魅力就是开发的不耽误功夫。我们可以先进行界面的开发,将界面可能需要的工作提前都设置好,比如给TextView设置文本,从Edittext获取值,根据变量显隐控件,按钮需要的点击事件等,都可以提前设置好对应的方法。接着等接口出来我们就可以很快对接接口,并将数据设置进去。不影响之前的界面,方便快捷,思路清晰。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-03-11 22:21:45  更:2022-03-11 22:23:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/1 22:29:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码