美文网首页IT界的日子Android开发Android开发经验谈
ButterKnife 的简易替代品,不为findViewByI

ButterKnife 的简易替代品,不为findViewByI

作者: 我的小白大人 | 来源:发表于2018-02-13 00:53 被阅读393次

    为什么要造轮子

    自己平常写代码一直用ButterKnife,功能太强大了有木有!但是最近有个需要在匿名内部类中去findView的时候却发现ButterKnife好像不支持在匿名内部类中进行find,(我也不确定支不支持,反正没找到相应的方法)编译后没有生成相应的ViewBinder类,应该是编译时故意忽略了匿名内部类吧。所以此时也很无奈啊。。。只能自己动手丰衣足食了。

    内容为原创,希望能给需要的人帮助,不喜勿喷

    一、思路

    将需要查找的View包装成WrapView对象放到查找队列中,指定View的类型和id,在容器(activity,fragment等)初始化完View以后再调用ViewFinder的findFrom方法进行查找。
    需要使用View时调用WrapView的get()方法将View取出。

    使用起来确实稍微有点麻烦。。。不过作为强迫症患者,这样的代码↓↓↓能把我逼疯

    public class MainActivity extends Activity{
        private TextView nameTv;
        private TextView ageTv;
        private TextView sexTv;
        private TextView nationTv;
        private TextView addressTv;
        private Button confirmBtn;
        private Button cancelBtn;
        private Button closeBtn;
        private LinearLayout mainLayout;
        private LinearLayout loadingLayout;
        private LinearLayout errorLayout;
        
        onCreate(){
            supper.onCreate();
            setConentView(R.layout.activity_main);
            findViews();
            initView();
        }
    
        public void findViews(){
            nameTv = (TextView) findViewById(R.id.tv_name);
            ageTv= (TextView) findViewById(R.id.tv_age);
            sexTv= (TextView) findViewById(R.id.tv_sex);
            nationTv = (TextView) findViewById(R.id.tv_nation);
            addressTv= (TextView) findViewById(R.id.tv_address);
            confirmBtn = (Button) findViewById(R.id.btn_confirm);
            cancelBtn= (Button) findViewById(R.id.btn_cancel);
            closeBtn = (Button) findViewById(R.id.btn_close);
            mainLayout= (LinearLayout) findViewById(R.id.layout_main);
            loadingLayout= (LinearLayout) findViewById(R.id.layout_loading);
            errorLayout= (LinearLayout) findViewById(R.id.layout_error);
        }
    
        public void initView(){
            nameTv.setText("张三");    
            ageTv.setText("26");      
            sexTv.setText("男");     
            ...
        }
        ...
    
    }
    
    

    经过改进后的代码是这样的

    
    public class MainActivity extends Activity{
    
        private ViewFinder finder = new ViewFinder();
        private WrapView<TextView> nameTv= finder.apply(R.id.tv_name);
        private WrapView<TextView> ageTv= finder.apply(R.id.tv_age);
        private WrapView<TextView> sexTv= finder.apply(R.id.tv_sex);
        private WrapView<TextView> nationTv= finder.apply(R.id.tv_nation);
        private WrapView<TextView> addressTv= finder.apply(R.id.tv_address);
        private WrapView<Button> confirmBtn= finder.apply(R.id.btn_confirm);
        private WrapView<Button> cancelBtn= finder.apply(R.id.btn_cancel);
        private WrapView<Button> closeBtn= finder.apply(R.id.btn_close);
        private WrapView<LinearLayout > mainLayout= finder.apply(R.id.layout_main);
        private WrapView<LinearLayout > loadingLayout= finder.apply(R.id.layout_loading);
        private WrapView<LinearLayout > errorLayout= finder.apply(R.id.layout_error);
        
        onCreate(){
            supper.onCreate();
            setConentView(R.layout.activity_main);
            finder.findFrom(this);
            initView();
        }
    
        public void initView(){
            nameTv.get().setText("张三");    
            ageTv.get()..setText("26");      
            sexTv.get()..setText("男");   
            confirmBtn.get().setOnclickListener(this);  
            ...
        }
        ...
    
    }
    

    二、WrapView 和 ViewFinder的代码

    WrapView

    /**
     * Wapper class to maintain View.
     * Created by Leo on 2018/2/12.
     */
    public class WrapView<T extends View> {
        private T view;
        @IdRes
        private int id;
    
        WrapView(@IdRes int id) {
            this.id = id;
        }
    
        public T get() {
            return view;
        }
    
        void setView(T view) {
            this.view = view;
        }
    
        void find(View from) {
            if (from == null) throw new NullPointerException("find view from a null object.");
            view = (T) from.findViewById(id);
            if (view == null) throw new ViewNotFoundException("View not found for id : " + id);
        }
    
        void find(Activity from) {
            if (from == null) throw new NullPointerException("find view from a null object.");
            view = (T) from.findViewById(id);
            if (view == null) throw new ViewNotFoundException("View not found for id : " + id);
        }
    }
    

    ViewFinder

    /**
     * Helper class to maintain finding tasks.
     * Created by Leo on 2018/2/12.
     */
    public class ViewFinder {
        private HashMap<Integer, WrapView<?>> views = new HashMap<>();
    
        public <T extends View> WrapView<T> apply(@IdRes int id){
            WrapView<T> wrapper = (WrapView<T>) views.get(id);
            if (wrapper == null){
                wrapper = new WrapView<>(id);
                views.put(id,wrapper);
            }
            return wrapper;
        }
    
        public void findFrom(View from) {
            Collection<WrapView<?>> wrapViews = views.values();
            for (WrapView<?> wrapView : wrapViews) {
                wrapView.find(from);
            }
        }
    
        public void findFrom(Activity from) {
            Collection<WrapView<?>> wrapViews = views.values();
            for (WrapView<?> wrapView : wrapViews) {
                wrapView.find(from);
            }
        }
    }
    

    代码量很少,需要的童鞋可以直接拿去用,祝大家新年快乐!

    相关文章

      网友评论

      • 乘风破浪的程序员:kotlin 是真清爽
      • mrzhqiang:不记得是从24还是25开始,fvb不需要显式地转换类型。然后谷歌官方说过,替代butterknife的最佳框架就是,databinding。或者你也可以用kotlin,瞬间清爽很多。
        紫木冰枫:@我的小白大人 ButterKnife麻烦。
        mrzhqiang:@我的小白大人 官方文档写复杂了,并且官方的样例也做得不友好
        我的小白大人:我感觉DataBinding使用起来是真麻烦...kotlin还没试过:smile:

      本文标题:ButterKnife 的简易替代品,不为findViewByI

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