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

过时: 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 !
觉得有帮助可以点个喜欢也可以转给别人看哦

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容