xUtils的源码分析

github官网:

https://github.com/wyouflf/xUtils3

简单使用

public class MainActivity extends AppCompatActivity {
    @ViewInject(R.id.test_tv)
    TextView mTextTv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        x.view().inject(this);
        mTextTv.setText("xutils的使用");
    }
    @Event(value = R.id.test_iv,
            type = View.OnClickListener.class/*可选参数, 默认是View.OnClickListener.class*/)
    private void onTestBaidu1Click(View view) {
        Toast.makeText(getApplicationContext(),"图片",Toast.LENGTH_SHORT).show();
    }
}

源码分析

x.view().inject(this);源码分析
inject实际就是一个接口,参数有Activity或者Fragment等
x.vjew()实际返回的ViewInjectorImpl对象,看inject方法

 @Override
    public void inject(Activity activity) {
        //获取Activity的ContentView的注解,这里是我们的MainActivity
        Class handlerType = activity.getClass();
        try {
        //①对其进行分析,返回ContentView 
            ContentView contentView = findContentView(handlerType);
            if (contentView != null) {
            //获取ContentView中的值
                int viewId = contentView.value();
                if (viewId > 0) {
                  //获取MainActivity中的setContentView的方法
                    Method setContentViewMethod = handlerType.getMethod("setContentView", int.class);
                   //反射执行该方法
                    setContentViewMethod.invoke(activity, viewId);
                }
            }
        } catch (Throwable ex) {
            LogUtil.e(ex.getMessage(), ex);
        }
        //传入的Activity,改activity中所有的注解,ViewFinder对象
        injectObject(activity, handlerType, new ViewFinder(activity));
    }

①findContentView源码分析

  /**
     * 从父类获取注解View
     */
    private static ContentView findContentView(Class thisCls) {
        if (thisCls == null || IGNORED.contains(thisCls)) {
            return null;
        }
  //MainActivity中的ContentView的注解
        ContentView contentView = thisCls.getAnnotation(ContentView.class);
        if (contentView == null) {
//获得本类的父类
            return findContentView(thisCls.getSuperclass());
        }
        return contentView;
    }

injectObject(activity, handlerType, new ViewFinder(activity));源码分析

 private static void injectObject(Object handler, Class handlerType, ViewFinder finder) {

        if (handlerType == null || IGNORED.contains(handlerType)) {
            return;
        }

        // 从父类到子类递归
        injectObject(handler, handlerType.getSuperclass(), finder);

        // inject view获得所有的属性
        Field[] fields = handlerType.getDeclaredFields();
        if (fields != null && fields.length > 0) {
            for (Field field : fields) {
              //所有属性的类型
                Class fieldType = field.getType();
                if (
                /* 不注入静态字段 */     Modifier.isStatic(field.getModifiers()) ||
                /* 不注入final字段 */    Modifier.isFinal(field.getModifiers()) ||
                /* 不注入基本类型字段 */  fieldType.isPrimitive() ||
                /* 不注入数组类型字段 */  fieldType.isArray()) {
                    continue;
                }
                //获得所有注解ViewInject,如TextView
                ViewInject viewInject = field.getAnnotation(ViewInject.class);
                if (viewInject != null) {
                    try {
                        View view = finder.findViewById(viewInject.value(), viewInject.parentId());
                        if (view != null) {
                          //所有设置属性都可以
                            field.setAccessible(true);
                            field.set(handler, view);
                        } else {
                            throw new RuntimeException("Invalid @ViewInject for "
                                    + handlerType.getSimpleName() + "." + field.getName());
                        }
                    } catch (Throwable ex) {
                        LogUtil.e(ex.getMessage(), ex);
                    }
                }
            }
        } // end inject view

事件注解

       //获得该类的所有方法
        Method[] methods = handlerType.getDeclaredMethods();
        if (methods != null && methods.length > 0) {
            for (Method method : methods) {
                 //不能是静态方法或者不是私有方法
                if (Modifier.isStatic(method.getModifiers())
                        || !Modifier.isPrivate(method.getModifiers())) {
                    continue;
                }

                //检查当前方法是否是event注解的方法
                Event event = method.getAnnotation(Event.class);
                if (event != null) {
                    try {
                        // id参数
                        int[] values = event.value();
                        int[] parentIds = event.parentId();
                        int parentIdsLen = parentIds == null ? 0 : parentIds.length;
                        //循环所有id,生成ViewInfo并添加代理反射
                        for (int i = 0; i < values.length; i++) {
                            int value = values[i];
                            if (value > 0) {
                                ViewInfo info = new ViewInfo();
                                info.value = value;
                                info.parentId = parentIdsLen > i ? parentIds[i] : 0;
                                method.setAccessible(true);
                               //源码分析
                                EventListenerManager.addEventMethod(finder, info, event, handler, method);
                            }
                        }
                    } catch (Throwable ex) {
                        LogUtil.e(ex.getMessage(), ex);
                    }
                }
            }
        } // end inject event

    }
 public static void addEventMethod(
            //根据页面或view holder生成的ViewFinder
            ViewFinder finder,
            //根据当前注解ID生成的ViewInfo
            ViewInfo info,
            //注解对象
            Event event,
            //页面或view holder对象
            Object handler,
            //当前注解方法
            Method method) {
        try {
            View view = finder.findViewByInfo(info);

            if (view != null) {
                // 注解中定义的接口,比如Event注解默认的接口为View.OnClickListener
                Class listenerType = event.type();
                // 默认为空,注解接口对应的Set方法,比如setOnClickListener方法
                String listenerSetter = event.setter();
                if (TextUtils.isEmpty(listenerSetter)) {
                    listenerSetter = "set" + listenerType.getSimpleName();
                }


                String methodName = event.method();

                boolean addNewMethod = false;
                /*
                    根据View的ID和当前的接口类型获取已经缓存的接口实例对象,
                    比如根据View.id和View.OnClickListener.class两个键获取这个View的OnClickListener对象
                 */
                Object listener = listenerCache.get(info, listenerType);
                DynamicHandler dynamicHandler = null;
                /*
                    如果接口实例对象不为空
                    获取接口对象对应的动态代理对象
                    如果动态代理对象的handler和当前handler相同
                    则为动态代理对象添加代理方法
                 */
                if (listener != null) {
                    dynamicHandler = (DynamicHandler) Proxy.getInvocationHandler(listener);
                    addNewMethod = handler.equals(dynamicHandler.getHandler());
                    if (addNewMethod) {
                        dynamicHandler.addMethod(methodName, method);
                    }
                }

                // 如果还没有注册此代理
                if (!addNewMethod) {

                    dynamicHandler = new DynamicHandler(handler);

                    dynamicHandler.addMethod(methodName, method);

                    // 生成的代理对象实例,比如View.OnClickListener的实例对象
                    listener = Proxy.newProxyInstance(
                            listenerType.getClassLoader(),
                            new Class[]{listenerType},
                            dynamicHandler);

                    listenerCache.put(info, listenerType, listener);
                }

                Method setEventListenerMethod = view.getClass().getMethod(listenerSetter, listenerType);
                setEventListenerMethod.invoke(view, listener);
            }
        } catch (Throwable ex) {
            LogUtil.e(ex.getMessage(), ex);
        }
    }

你可能感兴趣的:(xUtils的源码分析)