ButterKnife 组件化改造的一次实践

android 开发中写过最多的代码估计就是findViewById了。自从大神JakeWharton开发出了ButterKnife,编码效率大大提升。8.4.0之前的版本在工程分多个模块的时候就不能使用了,后来大神继续修复轮子,在非主模块中我们需要用R2来代替。因为子模块中R不是final 修饰的,资源合并也会变更数值。最近要做组件化,本来使用最新版本的ButterKnife也没什么问题,偏偏我们项目中用的是7.0的旧版本,不支持分业务模块使用。升级版本吧,又有那么多要全局替换,当然也不是难事,不过就是想多思考一下。随便看看源码,其实原来大神要解决的子模块R文件没有final修饰,以及int数值合并后改变的问题是可以规避。只要生成文件不用数字常量,用引用就可以了。

先看看原来的生成类。 我们注意到类似view = finder.findRequiredView(source, 2131299940, “field ‘viewOrderStatusBar’”); 2131299940这都是用R.id.XXX对应的常量,子模块中这样写就行不通了,因为会变啊。。。

package com.tts.scenery.tkpay;

import android.view.View;
import butterknife.ButterKnife.Finder;
import butterknife.ButterKnife.ViewBinder;

public class SceneryPayFinishActivity$$ViewBinder<T extends com.tts.scenery.tkpay.SceneryPayFinishActivity> implements ViewBinder<T> {
  @Override public void bind(final Finder finder, final T target, Object source) {
    View view;
    view = finder.findRequiredView(source, 2131299940, "field 'viewOrderStatusBar'");
    target.viewOrderStatusBar = finder.castView(view, 2131299940, "field 'viewOrderStatusBar'");
    view = finder.findRequiredView(source, 2131299744, "field 'tvStatusTitle'");
    target.tvStatusTitle = finder.castView(view, 2131299744, "field 'tvStatusTitle'");
    view = finder.findRequiredView(source, 2131297756, "field 'layoutStatusTitle'");
    target.layoutStatusTitle = finder.castView(view, 2131297756, "field 'layoutStatusTitle'");
    view = finder.findRequiredView(source, 2131299743, "field 'tvStatusDetail'");
    target.tvStatusDetail = finder.castView(view, 2131299743, "field 'tvStatusDetail'");
    view = finder.findRequiredView(source, 2131297754, "field 'layoutStatusDetail'");
    target.layoutStatusDetail = finder.castView(view, 2131297754, "field 'layoutStatusDetail'");
    view = finder.findRequiredView(source, 2131299386, "field 'tvInfo'");
    target.tvInfo = finder.castView(view, 2131299386, "field 'tvInfo'");
    view = finder.findRequiredView(source, 2131297632, "field 'layoutInfo'");
    target.layoutInfo = finder.castView(view, 2131297632, "field 'layoutInfo'");
    view = finder.findRequiredView(source, 2131296442, "field 'btn1' and method 'onClick'");
    target.btn1 = finder.castView(view, 2131296442, "field 'btn1'");
    view.setOnClickListener(
      new butterknife.internal.DebouncingOnClickListener() {
        @Override public void doClick(
          android.view.View p0
        ) {
          target.onClick(p0);
        }
      });
    view = finder.findRequiredView(source, 2131296444, "field 'btn2' and method 'onClick'");
    target.btn2 = finder.castView(view, 2131296444, "field 'btn2'");
    view.setOnClickListener(
      new butterknife.internal.DebouncingOnClickListener() {
        @Override public void doClick(
          android.view.View p0
        ) {
          target.onClick(p0);
        }
      });
    view = finder.findRequiredView(source, 2131297633, "field 'layoutInfoButtons'");
    target.layoutInfoButtons = finder.castView(view, 2131297633, "field 'layoutInfoButtons'");
    view = finder.findRequiredView(source, 2131297658, "field 'layoutMorePrivilege' and method 'onClick'");
    target.layoutMorePrivilege = finder.castView(view, 2131297658, "field 'layoutMorePrivilege'");
    view.setOnClickListener(
      new butterknife.internal.DebouncingOnClickListener() {
        @Override public void doClick(
          android.view.View p0
        ) {
          target.onClick(p0);
        }
      });
    view = finder.findRequiredView(source, 2131297440, "field 'ivLoading'");
    target.ivLoading = finder.castView(view, 2131297440, "field 'ivLoading'");
    view = finder.findRequiredView(source, 2131299426, "field 'tvLoading'");
    target.tvLoading = finder.castView(view, 2131299426, "field 'tvLoading'");
    view = finder.findRequiredView(source, 2131297648, "field 'layoutLoading'");
    target.layoutLoading = finder.castView(view, 2131297648, "field 'layoutLoading'");
    view = finder.findRequiredView(source, 2131298461, "field 'promotionLV'");
    target.promotionLV = finder.castView(view, 2131298461, "field 'promotionLV'");
    view = finder.findRequiredView(source, 2131296443, "field 'mBtn1Old' and method 'onClick'");
    target.mBtn1Old = finder.castView(view, 2131296443, "field 'mBtn1Old'");
    view.setOnClickListener(
      new butterknife.internal.DebouncingOnClickListener() {
        @Override public void doClick(
          android.view.View p0
        ) {
          target.onClick(p0);
        }
      });
    view = finder.findRequiredView(source, 2131296445, "field 'mBtn2Old' and method 'onClick'");
    target.mBtn2Old = finder.castView(view, 2131296445, "field 'mBtn2Old'");
    view.setOnClickListener(
      new butterknife.internal.DebouncingOnClickListener() {
        @Override public void doClick(
          android.view.View p0
        ) {
          target.onClick(p0);
        }
      });
    view = finder.findRequiredView(source, 2131297634, "field 'mLayoutInfoButtonsOld'");
    target.mLayoutInfoButtonsOld = finder.castView(view, 2131297634, "field 'mLayoutInfoButtonsOld'");
    view = finder.findRequiredView(source, 2131296900, "field 'mDividerLine'");
    target.mDividerLine = view;
  }

  @Override public void unbind(T target) {
    target.viewOrderStatusBar = null;
    target.tvStatusTitle = null;
    target.layoutStatusTitle = null;
    target.tvStatusDetail = null;
    target.layoutStatusDetail = null;
    target.tvInfo = null;
    target.layoutInfo = null;
    target.btn1 = null;
    target.btn2 = null;
    target.layoutInfoButtons = null;
    target.layoutMorePrivilege = null;
    target.ivLoading = null;
    target.tvLoading = null;
    target.layoutLoading = null;
    target.promotionLV = null;
    target.mBtn1Old = null;
    target.mBtn2Old = null;
    target.mLayoutInfoButtonsOld = null;
    target.mDividerLine = null;
  }
}

折腾了一下午,改写了常用的Bind,和OnClick等相关类,注解处理器,以及对用的代码生成插件。同样功能的类我都加C前缀做了区别。其中遇到的困难大概就是在不同模块时,插件要找到对应的包名做id的前缀,我就是从项目文件BuildConfig.java中找到APPLICATION_ID。大功告成。下面就是新的生成形式。

package com.tts.hybird.train.home.view;

import android.view.View;
import com.tts.trip.bind.CButterKnife.Finder;
import com.tts.trip.bind.CButterKnife.ViewBinder;

public class TrainSelectDateActivity$$CCViewBinder<T extends com.tts.hybird.train.home.view.TrainSelectDateActivity> implements ViewBinder<T> {
  @Override public void bind(final Finder finder, final T target, Object source) {
    View view;
    view = finder.findRequiredView(source, com.tts.hybird.train.R.id.tv_TitleBarText, "field 'tvTitleBarText'");
    target.tvTitleBarText = finder.castView(view, com.tts.hybird.train.R.id.tv_TitleBarText, "field 'tvTitleBarText'");
    view.setOnClickListener(
      new com.tts.trip.bind.CDebouncingOnClickListener("com.tts.hybird.train.R.id.tv_TitleBarText") {
        @Override public void doClick(
          android.view.View p0,
          java.lang.String p1
        ) {
          target.onViewClicked(p0, p1);
        }
      });
    view = finder.findRequiredView(source, com.tts.hybird.train.R.id.tv_TitleBarTextSmall, "field 'tvTitleBarTextSmall'");
    target.tvTitleBarTextSmall = finder.castView(view, com.tts.hybird.train.R.id.tv_TitleBarTextSmall, "field 'tvTitleBarTextSmall'");
    view.setOnClickListener(
      new com.tts.trip.bind.CDebouncingOnClickListener("com.tts.hybird.train.R.id.tv_TitleBarTextSmall") {
        @Override public void doClick(
          android.view.View p0,
          java.lang.String p1
        ) {
          target.onViewClicked(p0, p1);
        }
      });
    view = finder.findRequiredView(source, com.tts.hybird.train.R.id.iv_TitleBarBack, "field 'ivTitleBarBack'");
    target.ivTitleBarBack = finder.castView(view, com.tts.hybird.train.R.id.iv_TitleBarBack, "field 'ivTitleBarBack'");
    view.setOnClickListener(
      new com.tts.trip.bind.CDebouncingOnClickListener("com.tts.hybird.train.R.id.iv_TitleBarBack") {
        @Override public void doClick(
          android.view.View p0,
          java.lang.String p1
        ) {
          target.onViewClicked(p0, p1);
        }
      });
    view = finder.findRequiredView(source, com.tts.hybird.train.R.id.iv_TitleBarRightBtn, "field 'ivTitleBarRightBtn'");
    target.ivTitleBarRightBtn = finder.castView(view, com.tts.hybird.train.R.id.iv_TitleBarRightBtn, "field 'ivTitleBarRightBtn'");
    view.setOnClickListener(
      new com.tts.trip.bind.CDebouncingOnClickListener("com.tts.hybird.train.R.id.iv_TitleBarRightBtn") {
        @Override public void doClick(
          android.view.View p0,
          java.lang.String p1
        ) {
          target.onViewClicked(p0, p1);
        }
      });
    view = finder.findRequiredView(source, com.tts.hybird.train.R.id.tv_TitleBarRightText, "field 'tvTitleBarRightText'");
    target.tvTitleBarRightText = finder.castView(view, com.tts.hybird.train.R.id.tv_TitleBarRightText, "field 'tvTitleBarRightText'");
    view.setOnClickListener(
      new com.tts.trip.bind.CDebouncingOnClickListener("com.tts.hybird.train.R.id.tv_TitleBarRightText") {
        @Override public void doClick(
          android.view.View p0,
          java.lang.String p1
        ) {
          target.onViewClicked(p0, p1);
        }
      });
    view = finder.findRequiredView(source, com.tts.hybird.train.R.id.layout_TitleBarRight, "field 'layoutTitleBarRight'");
    target.layoutTitleBarRight = finder.castView(view, com.tts.hybird.train.R.id.layout_TitleBarRight, "field 'layoutTitleBarRight'");
    view = finder.findRequiredView(source, com.tts.hybird.train.R.id.root_title_rl, "field 'rootTitleRl'");
    target.rootTitleRl = finder.castView(view, com.tts.hybird.train.R.id.root_title_rl, "field 'rootTitleRl'");
    view = finder.findRequiredView(source, com.tts.hybird.train.R.id.m_train_tv_pre_sale_day_count, "field 'mTrainTvPreSaleDayCount'");
    target.mTrainTvPreSaleDayCount = finder.castView(view, com.tts.hybird.train.R.id.m_train_tv_pre_sale_day_count, "field 'mTrainTvPreSaleDayCount'");
    view = finder.findRequiredView(source, com.tts.hybird.train.R.id.m_train_layout_notice, "field 'mTrainLayoutNotice'");
    target.mTrainLayoutNotice = finder.castView(view, com.tts.hybird.train.R.id.m_train_layout_notice, "field 'mTrainLayoutNotice'");
    view = finder.findRequiredView(source, com.tts.hybird.train.R.id.m_train_vs_cal_one, "field 'mTrainVsCalOne'");
    target.mTrainVsCalOne = finder.castView(view, com.tts.hybird.train.R.id.m_train_vs_cal_one, "field 'mTrainVsCalOne'");
    view = finder.findRequiredView(source, com.tts.hybird.train.R.id.m_train_vs_cal_two, "field 'mTrainVsCalTwo'");
    target.mTrainVsCalTwo = finder.castView(view, com.tts.hybird.train.R.id.m_train_vs_cal_two, "field 'mTrainVsCalTwo'");
    view = finder.findRequiredView(source, com.tts.hybird.train.R.id.m_train_vs_cal_three, "field 'mTrainVsCalThree'");
    target.mTrainVsCalThree = finder.castView(view, com.tts.hybird.train.R.id.m_train_vs_cal_three, "field 'mTrainVsCalThree'");
  }

  @Override public void unbind(T target) {
    target.tvTitleBarText = null;
    target.tvTitleBarTextSmall = null;
    target.ivTitleBarBack = null;
    target.ivTitleBarRightBtn = null;
    target.tvTitleBarRightText = null;
    target.layoutTitleBarRight = null;
    target.rootTitleRl = null;
    target.mTrainTvPreSaleDayCount = null;
    target.mTrainLayoutNotice = null;
    target.mTrainVsCalOne = null;
    target.mTrainVsCalTwo = null;
    target.mTrainVsCalThree = null;
  }
}

新插件生成的代码。

public class TrainSelectDateActivity
        extends TrainBaseActivity<TrainSelectDatePresenter>
        implements ITrainSelectDateView {

    @CBind("com.tts.hybird.train.R.id.tv_TitleBarText")
    TextView tvTitleBarText;
    @CBind("com.tts.hybird.train.R.id.tv_TitleBarTextSmall")
    TextView tvTitleBarTextSmall;
    @CBind("com.tts.hybird.train.R.id.iv_TitleBarBack")
    ImageView ivTitleBarBack;
    @CBind("com.tts.hybird.train.R.id.iv_TitleBarRightBtn")
    ImageView ivTitleBarRightBtn;
    @CBind("com.tts.hybird.train.R.id.tv_TitleBarRightText")
    TextView tvTitleBarRightText;
    @CBind("com.tts.hybird.train.R.id.layout_TitleBarRight")
    LinearLayout layoutTitleBarRight;
    @CBind("com.tts.hybird.train.R.id.root_title_rl")
    RelativeLayout rootTitleRl;
    @CBind("com.tts.hybird.train.R.id.m_train_tv_pre_sale_day_count")
    TextView mTrainTvPreSaleDayCount;
    @CBind("com.tts.hybird.train.R.id.m_train_layout_notice")
    LinearLayout mTrainLayoutNotice;
    @CBind("com.tts.hybird.train.R.id.m_train_vs_cal_one")
    ViewStub mTrainVsCalOne;
    @CBind("com.tts.hybird.train.R.id.m_train_vs_cal_two")
    ViewStub mTrainVsCalTwo;
    @CBind("com.tts.hybird.train.R.id.m_train_vs_cal_three")
    ViewStub mTrainVsCalThree;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.m_train_activity_select_date)
        CButterKnife.bind(this);

    }

 

    @COnClick({"com.tts.hybird.train.R.id.tv_TitleBarText", "com.tts.hybird.train.R.id.tv_TitleBarTextSmall", "com.tts.hybird.train.R.id.iv_TitleBarBack", "com.tts.hybird.train.R.id.iv_TitleBarRightBtn", "com.tts.hybird.train.R.id.tv_TitleBarRightText"})
    public void onViewClicked(View view, final String idName) {
        switch (idName) {
            case "com.tts.hybird.train.R.id.tv_TitleBarText":
                break;
            case "com.tts.hybird.train.R.id.tv_TitleBarTextSmall":
                break;
            case "com.tts.hybird.train.R.id.iv_TitleBarBack":
                break;
            case "com.tts.hybird.train.R.id.iv_TitleBarRightBtn":
                break;
            case "com.tts.hybird.train.R.id.tv_TitleBarRightText":
                break;
        }
    }

现在主模块和子模块可以无差别的使用,尽量依靠生成,改写时候要注意下。今天太晚了,就先不贴源码了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值