美文网首页
butterknife组件化开发library中R类问题的批量解

butterknife组件化开发library中R类问题的批量解

作者: RetroX | 来源:发表于2017-03-24 22:44 被阅读6373次

过时: butterknife现在的plugin已处理id不一致的问题

至于R2是什么东西 -> 异步butterknife官方Github主页文档

最近在模块化重构项目的时候,之前的项目在app模块里大量使用了butterknife,但是迁移到library里面后由于R类中变量不再是final类型而导致各种问题,于是引发了一些思考

Butterknife 的作者JakeWharton大神也提供了R2的解决方案(PS:别人给他的pull request),大致的使用方法如下 ,使用R2处理相关问题...

@BindView(R2.id.toolbar)
    Toolbar toolbar;

那么问题来了,就是在 view.getId()方法中,系统返回的值是R类中的id而不是R2中的id,而且两个R类中相同变量的id并不相同,所以会翻车。错误操作普通修改方式的实例代码引用自博客Butter Knife简介和使用指南

// 错误的写法
@OnClick({R2.id.back, R2.id.txt_bind_we_chat_btn, R2.id.txt_bind_phone_btn})
public void onClick(View view) {
    switch (view.getId()) {
        case R2.id.back:
            break;
        case R2.id.txt_bind_phone_btn:
            break;
        case R2.id.txt_bind_we_chat_btn:
            break;
    }
}

// 一个很蛋疼的修复处理方式
@OnClick(R2.id.txt_bind_we_chat_btn)
public void onBindWeChatClick(View v) {
    bindWeChat();
}

@OnClick(R2.id.txt_bind_phone_btn)
  public void onBIndPhoneClick(View v) {
    bindPhoe();
}

@OnClick(R2.id.back)
public void onBackClick() {
    finish();
}

但是作为一个程序员,怎么能够忍受这种大量的机械修改!!

我的思路就是:是不是可以通过某种方式,对R类和R2类建立起某种映射关系,因为他们的变量名字是相同的。然后我灵机一动,一个骚东西在脑海一闪而过 ---- "反射”
嗯... 我就是要用反射这种骚东西

于是,我写了一个工具类,大体就是,通过反射获取R类和R2类的数据,将他们的变量名字和值建立在两个HashMap里面维护,然后就可以通过变量名搭桥,实现R,R2之间相同变量int值得转化

核心代码就在于,通过反射获取相关变量名和变量值然后存储在HashMap里面

for (Class aClass : classes) {
//            System.out.println(aClass.getSimpleName());
            if (aClass.getSimpleName().equals("id")) {
                Field[] fields = aClass.getFields();
                for (Field field : fields) {
                    field.setAccessible(true);
                    try {
                        int x = (int) field.get(r);
//                        System.out.println(field.getName() + " ----> " + x);
                        r1Map.put(x, field.getName());
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

其他的初始化map之类代码都很容易懂,道理也是蛮简单的,对于反射,经过计时的测试,发现对于相同的class,第二次反射的速度要大幅度快于第一次(推测,JVM对于反射可能是有缓存机制,如果大家有证实或者科学解释,欢迎在评论区发表见解 :smile),对于变量是不是要设置成静态,因为考虑到static内存是application共享,怕影响其他模块就没有设置,至于其他的优化,可以针对自己的项目进行修改.

测试时候的截图 :

      //测试代码
      // 触发的按钮是 bt_home_1
        RCaster caster = new RCaster(R.class,R2.class);
        Logger.d(caster.cast(view.getId()));
Paste_Image.png Paste_Image.png Paste_Image.png

附上工具类的完整代码

package com.company;

import java.lang.reflect.Field;
import java.util.HashMap;

/**
 * Created by retrox on 23/03/2017.
 */
public class RCaster {
    //id取得属性名字
    private HashMap<Integer, String> r1Map = new HashMap<>();
    //属性名字回取id
    private HashMap<String, Integer> r2Map = new HashMap<>();


    private Class R;
    private Class R2;

    public RCaster(Class r, Class r2) {
        R = r;
        R2 = r2;
        initMap1();
        initMap2();
    }
    
    /**
     * R1 id cast to R2
     *
     * @param rid
     * @return
     */
    public int cast(int rid) {
        String name = r1Map.get(rid);
        int id2 = r2Map.get(name);
        return id2;
    }

    /**
     * 初始化r1Map
     */
    @SuppressWarnings("Duplicates")
    private void initMap1() {

        long time = System.currentTimeMillis();

        Class[] classes = R.getClasses();
        Object r = null;
        try {
            r = R.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }

        for (Class aClass : classes) {
//            System.out.println(aClass.getSimpleName());
            if (aClass.getSimpleName().equals("id")) {
                Field[] fields = aClass.getFields();
                for (Field field : fields) {
                    field.setAccessible(true);
                    try {
                        int x = (int) field.get(r);
//                        System.out.println(field.getName() + " ----> " + x);
                        r1Map.put(x, field.getName());
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        long time2 = System.currentTimeMillis();
        long timeCost = time2 - time;

        System.out.println("\nTimecost:" + timeCost + "ms");

    }

    /**
     * 初始化r2Map
     */
    @SuppressWarnings("Duplicates")
    private void initMap2() {

        long time = System.currentTimeMillis();

        Class[] classes = R2.getClasses();
        Object r = null;
        try {
            r = R2.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }

        for (Class aClass : classes) {
            if (aClass.getSimpleName().equals("id")) {
                Field[] fields = aClass.getFields();
                for (Field field : fields) {
                    field.setAccessible(true);
                    try {
                        int x = (int) field.get(r);
//                        System.out.println(field.getName() + " ----> " + x);
//                        r2Map.put(x, field.getName());
                        r2Map.put(field.getName(),x);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }

        }
        long time2 = System.currentTimeMillis();
        long timeCost = time2 - time;

        System.out.println("\nTimecost:" + timeCost + "ms");

    }


}

Enjoy !
觉得有帮助可以点个喜欢也可以转给别人看哦

相关文章

网友评论

      本文标题:butterknife组件化开发library中R类问题的批量解

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