为Fragment也写一个ViewInject

简介: title: 为Fragment也写一个ViewInjectdate: 2018-10-28 11:29:51tags: fragment ViewInject1.简介鸿洋博客:https://blog.csdn.net/lmj623565791/article/details/39269193前段时间根据鸿洋的博客,写了一个ViewInject,本以为可以和findViewById说再见了,但是今天在fragment中使用ViewInject,却报了空指针的错误,原来是控件没有实例化就调用了。

title: 为Fragment也写一个ViewInject
date: 2018-10-28 11:29:51
tags: fragment ViewInject


1.简介

鸿洋博客:https://blog.csdn.net/lmj623565791/article/details/39269193
前段时间根据鸿洋的博客,写了一个ViewInject,本以为可以和findViewById说再见了,但是今天在fragment中使用ViewInject,却报了空指针的错误,原来是控件没有实例化就调用了。找了一下,我把目光放到ViewInjectUtil.inject(getActivity)上。

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        ViewInjectUtils.inject(getActivity());//问题可能出在这里
        init();
        setListener();
    }

ViewInject只是一个标志,实际上是通过inject方法调用其他方法,读取ViewInect中的值,实现动态绑定。因为Activity中可以直接调用findViewById()方法,而Fragment中则需要先获得所绑定的视图View,然后通过view.findViewById()来获取控件。
所以有必要给fragment重新写一个inject()方法,网上没有太多关于Fragment的inject(),干脆自己动手写一个,以下代码基于鸿洋博客中代码加以修改。

2.动手为Fragment写一个inject()方法

在ViewInjectUtils.java中添加方法fragmentInject()

public static void fragmentInject(Fragment fragment){
    fragmentInjectViews(fragment);
}

因为是给Fragment用的,所以传入的参数是一个Fragment,不再是activity。fragmentInjectView()是具体的注入方法,接下来我们来写fragmentInjectView()

private static void fragmentInjectViews(Fragment fragment){
        Class<? extends View> viewClass = fragment.getView().getClass();
        Class<? extends Fragment> fragmentClass = fragment.getClass();
        Field[] fields = fragmentClass.getDeclaredFields();
        //遍历所有成员对象
        for(Field field : fields){
            ViewInject viewInjectAnnotation = field.getAnnotation(ViewInject.class);
            if (viewInjectAnnotation != null) {
                int viewId = viewInjectAnnotation.value();
                if(viewId != -1){
                    Log.e("TAG", "injectViews: "+viewId);
                    //初始化View
                    try {
                        //通过view获取fingViewById()方法
                        Method method = viewClass.getMethod(METHOD_FIND_VIEW_BY_ID, int.class);
                        //让view调用findViewById()获取到控件对象,返回获取到控件对象的fragmentlayout
                        Object resView = method.invoke(fragment.getView(), viewId);
                        field.setAccessible(true);
                        //将fragmentLayout设置给fragment.
                        field.set(fragment, resView);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

不同的地方有3处:

  1. 声明了viewClass和fragmentClass两个变量。viewClass是fragment所绑定view的反射类,fragmentClass就是我们写的Fragment类的反射类。
  2. fields是通过fragmentClass获取的Fragment类中的字段
  3. 在"初始化View"下面,Method是通过viewClass获得的,resView也是通过fragment.getView()来取得对应ID的view。

主要思路:控件的引用声明在fragment中,但要通过view的findViewById方法获取控件对象,所以我们既需要fragment,又需要其对应的View。第2处不同中,获取到了fragment中声明的字段(其中包括我们声明的控件引用),第3处不同中,我们通过view获取到findViewById()方法,之后通过让view执行findViewById()方法获取到对应的控件对象,返回的resView是一个获取到控件对象的fragmentLayout,最后把它set给我们的fragment。

3.在fragment中调用fragmentInject()方法

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        ViewInjectUtils.fragmentInject(this);
        init();
        setListener();
    }

我们在onActivityCreated中调用fragmentInject()方法,因为fragmrent在onCreateView()中已经绑定了所属的view,之后通过getView()方法取得view。

4.总结

这里用到的是java反射的知识,感觉自己对这一块还很陌生,正好借这个机会稍微了解了一下这方面的知识,写下记录希望对大家有用。

目录
相关文章
|
9月前
|
XML 缓存 Android开发
QMUI实战(二)—Activity 和 Fragment,我们该选择谁?
在一开始,官方只提供了 Activity 来作为 UI 界面的载体,因此我们也别无选择,只能用它。而在 Android 3.0 后,Fragment 也面世了,它一开始是用于适配平板的,以邮件列表与详情的适配为例,手机端够小,因此开始展示列表,点击进入详情,而平板够大,则可以列表显示在左侧,详情显示在右侧,点击列表只是切换详情。对于这种适配场景,列表页和详情页必须在同一个 Activity 里了,而这便是我所知道的 Fragment 诞生的场景了。
113 0
|
11月前
|
XML API Android开发
Fragment初识
Fragment初识
54 0
|
XML ARouter API
Fragivity:像使用Activity一样使用Fragment
近年来,SPA,即单Activity架构逐渐开始受到欢迎,随之而生了很多优秀的三方库,大部分是基于Fragment作为实现方案,Fragivity 使用 Fragment + Navigatiion 打造最好用的 SPA 框架
413 0
|
Android开发 开发者 容器
Fragment详解
前言 谢谢你那么的、安静的捧场。 Fragment的概述及其设计初衷 Fragment代表了Activity的子模块,因此可以把Fragment理解成Activity片段。
1127 0
|
XML Android开发 数据格式
|
XML API Android开发
怎么知道Fragment属于哪个Activity呢?
如果程序是一条线运行的,Fragment 中 getActivity() 是获取的上一个打开或者执行的Activity中的值。   多个Activity也是如此,就看顺序是怎么执行的,getActivity获得的是当前Activity的上下文,也就是上一个Activity的值。
1112 0