Android的一种MVP模式框架

今天给大家分享的是一种将view的初始化和逻辑与activity分离的架构,采用的是mvp模式。但令人遗憾的是,这仅仅是一个新的思路,我在实际使用中发现其并不能完全将UI逻辑与activity分开,所以在实际中没办法认为这种设计是合理的。设计的初衷是觉得activity要接收intent或者要进行很多其他的处理,很难让人认为activity是一个与View相关的类,所以我们的想法是将view的逻辑从activity中分离,这种分离的方式我们就要用到一个UI类的接口。这个思路来自:https://github.com/wongcain/MVP-Simple-Demo,我仅仅是对作者的代码进行了分析和小部分修改。

ViewUiImp.java

package frame.kale.com.frame;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * @author Jack Tony
 * @brief
 * @date 2015/4/4
 */
public interface ViewUiImp {

    /**
     *
     * @param inflater
     * @param container
     */
    public void initViews(LayoutInflater inflater, ViewGroup container);

    public View getRootView();
}

这个接口中只有两个方法,一个是初始化views的方法,一个是得到根view的方法。我们希望activity仅仅与这个接口进行交互,而不用管view的逻辑。view的逻辑判断都是在实现这个接口的类中来进行的。为了让activity能更好的复用 代码,这里我们需要创建一个 activity的基类。

BasePresenterActivity.java

package frame.kale.com.frame;

import android.app.Activity;
import android.os.Bundle;

/**
 * @author Jack Tony
 * @brief 与activity有关的表现层的基类
 * @date 2015/4/4
 */
public  abstract class BasePresenterActivity <V extends ViewUiImp> extends Activity {
    protected V uiImp; // ViewUiImp的对象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        try {
            // 产生一个对象,并且调用initViews方法来初始化views
            uiImp = getViewUiClass().newInstance();
            uiImp.initViews(getLayoutInflater(), null);
            // 把根view设置到activity中
            setContentView(uiImp.getRootView());
            // 绑定views
            onBindViewUi();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 当activity退出后,通过onDestroyViewUi来销毁views
     */
       @Override
    protected final void onDestroy() {
        onDestroyViewUi();
        uiImp = null;
        super.onDestroy();
    }

    protected abstract Class<V> getViewUiClass();

    /**
     * 绑定views时触发的方法
     */
    protected void onBindViewUi(){}

    /**
     * 移出views时触发的方法
     */
    protected void onDestroyViewUi() {}
}

可以看到我们通过newInstance()来初始化了一个ViewUiImp对象,并且通过getRootView()来得到根view,之后将这个根view设置进了activity中。这些步骤中我们看到的都是接口对象,没有任何实体,灵活性很强。此外,在activity初始化或者销毁时都会触发view被绑定或被销毁时的回调,便于我们在activity的子类中进行操作。

现在,我们搭好了框架,那么就来尝试写一个实现类来看看效果如何吧。

package frame.kale.com.frame;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.TextView;

/**
 * @author Jack Tony
 * @brief
 * @date 2015/4/4
 */
public class HelloWorldViewUi implements ViewUiImp{

    private View rootView;

    public TextView helloWorldTv;
    public EditText msgEt;

    @Override
    public void initViews(LayoutInflater inflater, ViewGroup container) {
        rootView = inflater.inflate(R.layout.activity_main, container, false);
        helloWorldTv = (TextView) rootView.findViewById(R.id.textView);
        msgEt = (EditText) rootView.findViewById(R.id.editText);
    }

    @Override
    public View getRootView() {
        return rootView;
    }
}

这个类很简单,做了初始化views和返回根view的操作。目前看来findviewById的方法和view的逻辑都可以在这里进行。那么我们在activity的实现类中会做什么事情呢?我们做的事情也很简单,只需要继承我们刚写的基类,并且注入一个HelloWorldViewUi对象就可以了。

public class MainActivity extends BasePresenterActivity<HelloWorldViewUi> {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        uiImp.helloWorldTv.setText("12345");
    }

    @Override
    protected Class<HelloWorldViewUi> getViewUiClass() {
        return HelloWorldViewUi.class;
    }

}

我们可以利用这个uiImp对象来操作布局中定义的各种view,确实很简洁方便。但问题又来了!这里看到的确实是将ui和activity进行了抽离,但activity仍旧会进行ui逻辑的操作,对于menu这样的初始化和定义还是在activity中进行的,所以目前来看view和activity没有完全的独立开。比如下面的代码就很难放入uiImp接口中去。

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.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();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

总结一下就是这个思路很不错,但在实际使用中还是有一定问题的,以后还得多思考多研究啊。

源码下载:http://download.csdn.net/detail/shark0017/8565091

参考自:

https://github.com/wongcain/MVP-Simple-Demo

https://github.com/bboyfeiyu/android-tech-frontier/tree/master/androidweekly/%E4%B8%80%E7%A7%8D%E5%9C%A8android%E4%B8%AD%E5%AE%9E%E7%8E%B0MVP%E6%A8%A1%E5%BC%8F%E7%9A%84%E6%96%B0%E6%80%9D%E8%B7%AF

时间: 04-04

Android的一种MVP模式框架的相关文章

Android 架构设计实现——MVP模式

转载请注明出处:http://blog.csdn.net/smartbetter/article/details/70853135 随着 UI 创建技术的功能日益增强,UI 层也履行着越来越多的职责.为了更好地细分视图(View)与模型(Model)的功能,让 View 专注于处理数据的可视化以及与用户的交互,同时让 Model 只关系数据的处理,基于 MVC(Model View Controller) 模式的 MVP(Model-View-Presenter) 模式应运而生.目前MVP模式在

高通方案的Android设备几种开机模式的进入与退出

高通方案的Android设备主要有以下几种开机模式,Android.EDL.Fastboot.Recovery和FFBM,其进入及退出的方式如下表. 开机模式 屏幕表现 冷启动 热启动 按键退出 命令退出 Android/Normal 显示Android界面 按Power键 adb reboot 手机短按,VR长按Power键 adb shell reboot -p(关机) Recovery/OTA/卡刷 显示Recovery界面 按住OK键(Vol+),再按Power键 adb reboot

Android Activity 四种启动模式

Activity启动方式有四种,分别是: standard singleTop singleTask singleInstance 可以根据实际的需求为Activity设置对应的启动模式,从而可以避免创建大量重复的Activity等问题. 设置Activity的启动模式,只需要在AndroidManifest.xml里对应的<activity>标签设置android:launchMode属性,例如: [html] view plain copy <activity android:nam

android launchmode(四种启动模式)应用场景及实例

模式介绍 [1] standard 模式 这是默认模式,每次激活Activity时都会创建Activity实例,并放入任务栈中. [2] singleTop 模式 如果在任务的栈顶正好存在该Activity的实例,就重用该实例( 会调用实例的 onNewIntent() ),否则就会创建新的实例并放入栈顶,即使栈中已经存在该Activity的实例,只要不在栈顶,都会创建新的实例. [3] singleTask 模式 如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的 onNew

Android上实现MVP模式的途径

今天我想分享我在Android上实现MVP(Model-View-Presenter)模式的方法.如果你对MVP模式还不熟悉,或者不了解为什么要在Android应用中使用MVP模式,推荐你先阅读这篇维基百科文章和这篇博客. 使用Activity和Fragment作为View合适么? 目前,在很多使用了MVP模式的Android项目中,主流做法是将Activity和Fragment作为视图层来进行处理.而Presenters通常是通过继承被视图层实例化或者注入的对象来得到的.我认可这种方式可以节省

关于Android MVP模式的思考

最近经常看到各种介绍MVP模式的博客的,之前写过不少的Android应用,在做那些应用的时候,都是要求快速完成,所以从开始设计到写代码就一直考虑着重用.以前写的项目基本都是不断重构项目,将项目代码变得更加精简,提高代码之间的复用性.但是代码并没有特别地注重按照MVC模式或者是MVP模式来,更多的是直接考虑模块化,重用,精简.所以看了MVP模式后,决定去总结一下自己代码中的问题并优化,算是对自己之前写的代码的回顾. MVP框架 MVP框架是目前在Android流行起来的框架,它非常适合用于Andr

Android Activity 的四种启动模式 lunchMode 和 Intent.setFlags();singleTask的两种启动方式。

Android Activity 的四种启动模式 lunchMode 和 Intent.setFlags(); 一.Android Activity 四种启动模式 lunchMode 在Manifest 配置文件中的属性如下: (1) android:launchMode="standard" (2)android:launchMode="singleTop" (3)android:launchMode="singleTask" (4)andro

Android Activity 的四种启动模式 lunchMode 和 Intent.setFlags();

一.Android Activity 四种启动模式 lunchMode 在Manifest 配置文件中的属性如下: (1) android:launchMode="standard" (2)android:launchMode="singleTop" (3)android:launchMode="singleTask" (4)android:launchMode="singleInstance" 二.说明: Android 中

在 2016 年学 Android 是一种什么样的体验?

@author ASCE1885的 Github 简书 微博 CSDN 知乎 本文由于潜在的商业目的,不开放全文转载许可,谢谢! 广而告之时间:我的新书<Android 高级进阶>(https://item.jd.com/10821975932.html )在京东开始预售了,欢迎订购! 转眼间 2016 年的电量已不足 20%,不禁感慨 How Time Flies!不知不觉 Android 移动开发已经走过了八年的光阴,在这八年的时间中,Android 开发从最初的简单调用系统 API,到各