美文网首页
IOC框架(一)

IOC框架(一)

作者: 世道无情 | 来源:发表于2019-02-13 06:50 被阅读0次

    1. IOC


    Inversion of Control,控制反转,
    目的是:帮我们注入setContentView布局文件、注入findViewById、注入onClick事件;

    这篇文章只是记录 注入setContentView布局文件、注入findViewById

    注入setContentView布局文件:在Activity类上添加注解,自动帮我们注入布局文件;
    注入findViewById:在Activity中每个控件添加注解,自动帮我们findViewById;

    下边通过
    注入 setContentView布局文件,替代传统的 setContentView(R.layout.activity_zhujie);
    注入 InjectView,替代传统的 findViewById;

    2. 效果如下


    点击111 - 弹出 111;
    点击222 - 弹出 222;


    图片.png

    3. 代码如下


    1>:定义两个注解:

    第一:ContentView :用于类上声明哪个布局文件

    // Target:表示作用在哪里 FIELD:成员变量 TYPE:类 CONSTRUCTOR:构造方法
    @Target(ElementType.TYPE)
    // Retention: 表示什么时候生效 RUNTIME:运行时 CLASS:编译时 SOURCE: 源码资源
    @Retention(RetentionPolicy.RUNTIME)
    // ContentView: 在类上边使用,用于标明该Activity需要使用的布局文件
    public @interface ContentView {
        int value();
    }
    

    第二:ViewInject :用于成员变量,findViewById

    // Target:表示作用在哪:FIELD:成员变量 TYPE:类 CONSTRUCTOR:构造方法
    @Target(ElementType.FIELD)
    // Retention:表示什么时间生效 RUNTIME:运行时 CLASS: 编译时 SOURCE:源码资源
    @Retention(RetentionPolicy.RUNTIME)
    // ViewInject: 在成员变量上使用,用于指定View的id
    public @interface ViewInject {
        int value();
    }
    
    2>:ViewInjectUtils
    /**
     * ================================================
     * Email: 2185134304@qq.com
     * Created by Novate 2019/1/2 10:15
     * Version 1.0
     * Params:
     * Description:    反射注入setContentView、findViewById
     * ================================================
    */
    
    public class ViewInjectUtils {
    
        private static final String METHOD_SET_CONTENTVIEW = "setContentView";
        private static final String METHOD_FIND_VIEW_BY_ID = "findViewById";
    
        public static void inject(Activity activity){
            // setContentView
            injectContentView(activity);
            // findViewById
            injectViews(activity);
        }
    
        /**
         * 注入:setContentView
         */
        private static void injectContentView(Activity activity){
            // 传递activity对象,获取它的Class类型
            Class<? extends Activity> clazz = activity.getClass();
            // 判断这个类中是否写了ContentView注解
            ContentView contentView = clazz.getAnnotation(ContentView.class);
            // 如果写了该注解
            if (contentView != null){
                // 读取该注解的value
                int contentViewLayoutId = contentView.value();
                try{
                    // 得到 setContentView 这个方法,然后调用 invoke 即可
                    Method method = clazz.getMethod(METHOD_SET_CONTENTVIEW,
                            int.class);
                    method.setAccessible(true);
                    method.invoke(activity, contentViewLayoutId);
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    
    
    
        /**
         * 注入:findViewById
         */
        private static void injectViews(Activity activity){
            // 传递activity对象,获取它的Class类型
            Class<? extends Activity> clazz = activity.getClass();
            // 获取该类中所有的字段(成员变量,不是方法) public、private、protected,不包括父类字段
            // getFields(): 获取该类中所有的public字段(成员变量,不是方法)
            // getConstructors()和getDeclaredConstructors():表示获取某个类的构造函数
            // getMethods()和getDeclaredMethods(),表示获取某个类的方法
            Field[] fields = clazz.getDeclaredFields();
            // 遍历所有成员变量
            for (Field field : fields){
                // 获取该变量的ViewInject注解
                ViewInject viewInjectAnnotation = field
                        .getAnnotation(ViewInject.class);
                // 如果该变量写了 ViewInject注解
                if (viewInjectAnnotation != null){
                    // 获取value
                    int viewId = viewInjectAnnotation.value();
                    if (viewId != -1){
                        Log.e("TAG", viewId+"");
                        // 初始化View
                        try{
                            // 调用findViewById,调用反射执行
                            Method method = clazz.getMethod(METHOD_FIND_VIEW_BY_ID,
                                    int.class);
                            Object resView = method.invoke(activity, viewId);
                            field.setAccessible(true);
                            field.set(activity, resView);
                        } catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }
    
    3>:activity_zhujie.xml
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/id_btn"
            android:text="111"
            />
    
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/id_btn02"
            android:text="222"
            />
    </LinearLayout>
    
    4>:ZhuJieActivity
    /**
     * ================================================
     * Email: 2185134304@qq.com
     * Created by Novate 2019/1/2 13:48
     * Version 1.0
     * Params:
     * Description:    注入setContentView、findViewById
     * ================================================
    */
    
    // 反射注入 setContentView主布局文件
    @ContentView(value = R.layout.activity_zhujie)
    public class ZhuJieActivity extends AppCompatActivity implements View.OnClickListener{
    
        // 反射注入 findViewById
        @ViewInject(R.id.id_btn)
        private Button mBtn1 ;
        @ViewInject(R.id.id_btn02)
        private Button mBtn2;
    
    
        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            ViewInjectUtils.inject(this);
    
            mBtn1.setOnClickListener(this);
            mBtn2.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.id_btn:
                    Toast.makeText(ZhuJieActivity.this , "111" , Toast.LENGTH_SHORT).show();
                     break;
                case R.id.id_btn02:
                    Toast.makeText(ZhuJieActivity.this , "222" , Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    }
    
    以上就实现了用:

    反射注入 setContentView主布局文件,实现了传统的 setContentView;
    反射注入 ViewInject,实现了传统的 有多少个控件,就有多少个findViewById;

    相关文章

      网友评论

          本文标题:IOC框架(一)

          本文链接:https://www.haomeiwen.com/subject/blszlqtx.html