zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    Linux删除文件相关命令
    Bing语句
    VS2013配置Winpcap
    node10-mongoose
    node09-cookie
    node08-express
    node07-http
    node06-path
    node05-fs
    node04-buffer
  • 原文地址:https://www.cnblogs.com/tianzhijiexian/p/4393722.html
Copyright © 2011-2022 走看看