Android封裝單選與多選

平時(shí)開(kāi)發(fā)的時(shí)候我們總會(huì)碰到這樣的需求。

image.png

有時(shí)是多選,有時(shí)是單選,這樣的頁(yè)面基本都是用RecyclerView來(lái)做的,而如果每次做操作的時(shí)候都要去寫(xiě)這個(gè)單選框/多選框的邏輯,那就太麻煩了,所以我就想把這樣的單選/多選列表功能給封裝起來(lái)。

一.思路

這種功能的基本布局頁(yè)面都是這樣

image.png

或者有些需要把選擇框放在右邊

image.png

我的思路是外層還是用RecyclerView來(lái)做,里層(就是實(shí)線內(nèi))我打算用ViewModel來(lái)做,這樣既能封裝外層的選擇框邏輯,對(duì)內(nèi)層也低耦合。

二.效果展示

1.單選模式
15063446875651506344674549.gif
2.多選模式
15063446848301506344654342.gif

PS:左邊的布局是個(gè)ViewModel可以自由定義,因?yàn)闀r(shí)間的問(wèn)題我沒(méi)時(shí)間再寫(xiě)另外的布局來(lái)展示。

三.調(diào)用方法

調(diào)用方法很簡(jiǎn)單:

1.定義自己的ViewModel
2.調(diào)用
 checkRecyclerView = new CheckRecyclerView.Builder<ChoseShopEntity>(this,"com.berchina.o2omerchant.ui.viewModel.shop.ChoseShopViewModel")
                .setItemDecoration(new XXXItemDecoration(10))
                .setBackgroupColorResID(R.color.divider_grey)
//                .setCheckboxResID(R.drawable.cb_shop_create)
                .setIsRadio(false)
                .builder();
        framelayout.addView(checkRecyclerView.getContentView());

Builder中的第二個(gè)參數(shù)我傳的就是ViewModel的類名。

3.設(shè)置數(shù)據(jù)
checkRecyclerView.setAdapter(datalist);

封裝好了用起來(lái)就是快,不會(huì)每次都要重復(fù)去寫(xiě)單選和復(fù)選的邏輯。

四.CheckRecyclerView內(nèi)的操作

我這里把RecyclerView、Adapter和ViewHolder都寫(xiě)在一個(gè)類中,仿照RecyclerView源碼的寫(xiě)法,當(dāng)然分開(kāi)寫(xiě)也行。

先貼全部代碼吧

public class CheckRecyclerView<T extends CheckRecyclerView.CheckRecyclerEntity> {

    protected Context context;
    protected RecyclerView recyclerView;
    protected static CheckRecyclerAdapter adapter;
    // 0 表示都不顯示,1表示顯示左邊,2表示顯示右邊
    protected static int isShow;
    protected static String vmName;
    protected static int checkboxResID;
    protected static boolean isRadio;
    protected static RadioObserver radioObserver; // 監(jiān)聽(tīng)單選
    protected static MultiObserver multiObserver; // 監(jiān)聽(tīng)多選

    protected Builder builder;
    // 單選情況下的觀察者
    private static Action1<Integer> observer1 = new Action1<Integer>() {
        @Override
        public void call(Integer integer) {
            if (adapter != null){
                adapter.checkChange(integer);
            }
        }
    };
    // 多選情況下的觀察者
    private static Action1<Integer> observer2 = new Action1<Integer>() {
        @Override
        public void call(Integer integer) {
            if (adapter != null){
                adapter.multiChose(integer);
            }
        }
    };

    private CheckRecyclerView(Context context,Builder builder){
        this.context = context;
        this.builder = builder;

        this.isShow = builder.isShow;
        this.vmName = builder.vmName;
        this.checkboxResID = builder.checkboxResID;
        this.isRadio = builder.isRadio;
        this.radioObserver = builder.radioObserver;
        this.multiObserver = builder.multiObserver;

        initView();
    }

    private void initView(){
        recyclerView = new RecyclerView(context);
        recyclerView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        recyclerView.setBackgroundResource(builder.backgroupColorResID);
        recyclerView.setLayoutManager(builder.layoutManager);
        if (builder.itemDecoration != null) {
            recyclerView.addItemDecoration(builder.itemDecoration);
        }
    }

    /**
     *  設(shè)置適配器
     */
    public void setAdapter(){
        List<T> datalist = builder.datalist;
        if (datalist == null){
            datalist = new ArrayList<T>();
        }
        adapter = new CheckRecyclerAdapter(context,datalist);

        recyclerView.setAdapter(adapter);
    }

    /**
     *  設(shè)置適配器
     */
    public void setAdapter(List<T> datalist){
        adapter = new CheckRecyclerAdapter(context,datalist);

        recyclerView.setAdapter(adapter);
    }

    /**
     * get and set 方法
     */
    public RecyclerView getContentView() {
        return recyclerView;
    }
    public static CheckRecyclerAdapter getAdapter() {
        return adapter;
    }
    public void setIsShow(int isShow) {
        this.isShow = isShow;
    }
    public static void setVmName(String vmName) {
        CheckRecyclerView.vmName = vmName;
    }

    /**
     *  獲取到選擇的結(jié)果
     *  規(guī)則:-1表示沒(méi)有選擇
     */
    // 單選左
    public int getLeftRadio(){
        if (adapter != null && adapter.getDatas() != null && adapter.getDatas().size() > 0){
            return adapter.getLeftRadio();
        }
        return  -1;
    }
    // 單選右
    public int getRightRadio(){
        if (adapter != null && adapter.getDatas() != null && adapter.getDatas().size() > 0){
            return adapter.getRightRadio();
        }
        return  -1;
    }
    // 多選左   返回被選中的數(shù)組
    public List<Integer> getLeftMulti(){
        List<Integer> multiList = new ArrayList<>();
        if (adapter != null && adapter.getDatas() != null && adapter.getDatas().size() > 0){
            for (int i = 0; i < adapter.getDatas().size(); i++) {
                if (((CheckRecyclerEntity)adapter.getDatas().get(i)).leftCheck == true) {
                    multiList.add(i);
                }
            }
        }
        return multiList;
    }
    // 多選右   返回被選中的數(shù)組
    public List<Integer> getRightMulti(){
        List<Integer> multiList = new ArrayList<>();
        if (adapter != null && adapter.getDatas() != null && adapter.getDatas().size() > 0){
            for (int i = 0; i < adapter.getDatas().size(); i++) {
                if (((CheckRecyclerEntity)adapter.getDatas().get(i)).rightCheck == true) {
                    multiList.add(i);
                }
            }
        }
        return multiList;
    }

    /**
     *  判斷在多選的情況下是否全部選擇
     */
    public boolean isAllChose(){
        Boolean isAllChose = true;
        if (adapter != null && adapter.getDatas() != null && adapter.getDatas().size() > 0) {
            if (isShow == 1) {
                for (int i = 0; i < adapter.getDatas().size(); i++) {
                    if (((CheckRecyclerEntity)adapter.getDatas().get(i)).leftCheck == false){
                        return false;
                    }
                }
            } else if (isShow == 2) {
                for (int i = 0; i < adapter.getDatas().size(); i++) {
                    if (((CheckRecyclerEntity)adapter.getDatas().get(i)).rightCheck == false){
                        return false;
                    }
                }
            } else {
                return false;
            }
        }else {
            isAllChose = false;
        }
        return isAllChose;
    }

    /**
     *  外部控制內(nèi)部進(jìn)行單選的操作
     */
    public void setRadio(int position){
        if (adapter != null){
            adapter.checkChange(position);
        }
    }
    /**
     *  設(shè)置全選/全不選
     *  規(guī)則:true表示全選 false表示全不選
     */
    public void setAllMulti(Boolean bol){
        if (adapter != null){
            adapter.setAllMulti(bol);
        }
    }

    /**
     *  recycelerView 的 adapter
     */
    public static class CheckRecyclerAdapter<T extends CheckRecyclerEntity> extends XXXRecyclerViewBaseAdapter<T>{
        // 記錄單選的選項(xiàng)(用空間換時(shí)間)
        private int leftRadio = -1;
        private int rightRadio = -1;

        public CheckRecyclerAdapter(Context context, List dataSource) {
            super(context, dataSource);
        }

        @Override
        protected BerRecyclerViewHolder getViewHolder(ViewGroup parent) {
            return new CheckRecyclerViewHolder(LayoutInflater.from(context).inflate(R.layout.item_check_recycler,parent,false),context);
        }

        /**
         * 單選
         */
        public void checkChange(int position){
            if (position < dataSource.size()) {
                // 先將所有都設(shè)為未點(diǎn)擊
                for (int i = 0; i < dataSource.size(); i++) {
                    dataSource.get(i).leftCheck = false;
                    dataSource.get(i).rightCheck = false;
                }
                // 再設(shè)置點(diǎn)擊的Item
                if (isShow == 1) {
                    dataSource.get(position).leftCheck = true;
                    leftRadio = position;
                }else if (isShow == 2){
                    dataSource.get(position).rightCheck = true;
                    rightRadio = position;
                }

                // 做響應(yīng)
                if (radioObserver != null) {
                    radioObserver.radioClick(position, isShow);
                }

                this.notifyDataSetChanged();
            }
        }

        /**
         *  多選
         */
        public void multiChose(int position){
            // 點(diǎn)擊后展示相反的情況
            if (isShow == 1) {
                dataSource.get(position).leftCheck = !dataSource.get(position).leftCheck;
            }else if (isShow == 2){
                dataSource.get(position).rightCheck = !dataSource.get(position).rightCheck;
            }

            // 做響應(yīng)
            if (multiObserver != null) {
                multiObserver.multiClick(position, isShow);
            }

            this.notifyDataSetChanged();
        }

        /**
         * 設(shè)置全選
         */
        public void setAllMulti(Boolean bol){
            if (isShow == 1) {
                for (int i = 0; i < dataSource.size(); i++) {
                    dataSource.get(i).leftCheck = bol;
                }
                this.notifyDataSetChanged();
            }else if (isShow == 2){
                for (int i = 0; i < dataSource.size(); i++) {
                    dataSource.get(i).rightCheck = bol;
                }
                this.notifyDataSetChanged();
            }
        }

        // get and set
        public int getLeftRadio() {return leftRadio;}
        public int getRightRadio() {return rightRadio;}
    }

    /**
     *  recycelerView 的 viewholder
     */
    public static class CheckRecyclerViewHolder<T extends CheckRecyclerEntity> extends XXXRecyclerViewHolder<T>{

        @InjectView(R.id.cb_left)
        CheckBox cbLeft;
        @InjectView(R.id.cb_right)
        CheckBox cbRight;
        @InjectView(R.id.fl_content)
        FrameLayout flContent;

        private BaseViewModel viewmodel;


        public CheckRecyclerViewHolder(View itemView, Context context) {
            super(itemView, context);
            ButterKnife.inject(this,itemView);

            if (isShow == 0){
                cbLeft.setVisibility(View.GONE);
                cbRight.setVisibility(View.GONE);
            }else if (isShow == 1){
                cbLeft.setVisibility(View.VISIBLE);
                cbRight.setVisibility(View.GONE);
            }else if (isShow == 2){
                cbLeft.setVisibility(View.GONE);
                cbRight.setVisibility(View.VISIBLE);
            }
            // 設(shè)置CheckBox的樣式
            if (checkboxResID != 0) {
                cbLeft.setButtonDrawable(checkboxResID);
                cbRight.setButtonDrawable(checkboxResID);
            }
            // 應(yīng)反射創(chuàng)建viewmodel對(duì)象
            try {
                Class<?> myClass = Class.forName(vmName);//完整類名
                Class[] paramTypes = { Context.class };
                Object[] params = {context};
                Constructor con = myClass.getConstructor(paramTypes);
                viewmodel = (BaseViewModel) con.newInstance(params);
                flContent.addView(viewmodel.getContentView());
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }

        }

        @Override
        public void setDataToView() {
            super.setDataToView();
            // 處理選擇框的點(diǎn)擊 , 只做數(shù)據(jù)展示,邏輯放在外邊處理
            cbLeft.setChecked(data.leftCheck);
            cbRight.setChecked(data.rightCheck);
            //為viewmodel添加數(shù)據(jù)
            viewmodel.setData(data);
        }

        /**
         *  接下來(lái)做 單選 和 多選 的操作  todo 先測(cè)試單選看看能不能用
         */
        @OnClick({R.id.cb_left,R.id.cb_right})
        public void itemClick(View v){
            switch (v.getId()){
                case R.id.cb_left:
                    if (isRadio) {
                        // 單選
                        Observable.just(getAdapterPosition()).subscribe(observer1);
                    }else {
                        // 多選
                        Observable.just(getAdapterPosition()).subscribe(observer2);
                    }
                    break;
                case R.id.cb_right:
                    if (isRadio) {
                        Observable.just(getAdapterPosition()).subscribe(observer1);
                    }else {
                        Observable.just(getAdapterPosition()).subscribe(observer2);
                    }
                    break;
            }
        }

    }

    /**
     *  定義兩個(gè)數(shù)據(jù)來(lái)記錄是否點(diǎn)擊選擇框
     *  規(guī)則:調(diào)用封裝的數(shù)據(jù)類要繼承這個(gè)類
     */
    public static class CheckRecyclerEntity{
        public boolean leftCheck;
        public boolean rightCheck;
    }

    /**
     *  =======================================================================
     *   Builder方法
     *  ========================================================================
     */
    public static class Builder<T extends CheckRecyclerView.CheckRecyclerEntity>{

        private Context context;
        private int isShow = 1; // 默認(rèn)為顯示左邊的
        private String vmName;
        private List<T> datalist;
        //RecyclerView相關(guān)
        private RecyclerView.ItemDecoration itemDecoration;
        private RecyclerView.LayoutManager layoutManager;
        private int backgroupColorResID; //RecyclerView背景顏色,默認(rèn)為白色
        // checkbox相關(guān)
        private int checkboxResID = 0;
        private boolean isRadio = true;// 定義單選(true)和多選(true)
        private RadioObserver radioObserver; // 監(jiān)聽(tīng)單選
        private MultiObserver multiObserver; // 監(jiān)聽(tīng)多選

        // 這個(gè)一定要傳完整 包名+類名
        public Builder(Context context,String vmName){
            this.context = context;
            this.vmName = vmName;

            layoutManager = new LinearLayoutManager(context);
            backgroupColorResID = R.color.white;
        }

        public Builder setIsShow(int isShow) {
            this.isShow = isShow;
            return this;
        }

        public Builder setDatalist(List<T> datalist) {
            this.datalist = datalist;
            return this;
        }

        public Builder setItemDecoration(RecyclerView.ItemDecoration itemDecoration) {
            this.itemDecoration = itemDecoration;
            return this;
        }

        public Builder setLayoutManager(RecyclerView.LayoutManager layoutManager) {
            this.layoutManager = layoutManager;
            return this;
        }

        public Builder setCheckboxResID(int checkboxResID) {
            this.checkboxResID = checkboxResID;
            return this;
        }

        public Builder setBackgroupColorResID(int backgroupColorResID) {
            this.backgroupColorResID = backgroupColorResID;
            return this;
        }

        public Builder setIsRadio(boolean radio) {
            isRadio = radio;
            return this;
        }

        public Builder setRadioObserver(RadioObserver radioObserver) {
            this.radioObserver = radioObserver;
            return this;
        }

        public Builder setMultiObserver(MultiObserver multiObserver) {
            this.multiObserver = multiObserver;
            return this;
        }

        public CheckRecyclerView builder(){
           return new CheckRecyclerView(context,this);
        }

    }

    /**
     *  單選時(shí)的響應(yīng)
     */
    public interface RadioObserver{
        public void radioClick(int position,int isShow);
    }
    /**
     *  多選時(shí)的響應(yīng)
     */
    public interface MultiObserver{
        public void multiClick(int position,int isShow);
    }

}

代碼也不能說(shuō)長(zhǎng),500行這樣,其實(shí)還好。也只封裝了一些基本的功能操作,之后還可以擴(kuò)展。其實(shí)我還算挺良心的,加了很多注解,我個(gè)人習(xí)慣先寫(xiě)注解再寫(xiě)方法。

基類的XXXRecyclerViewBaseAdapter和XXXRecyclerViewHolder是我自己寫(xiě)的Adapter和ViewHolder的基類


1.基本的流程

我有注解也不一行一行解釋,主要是用了Builder模式,在外邊使用時(shí)可以addView,用自定義寫(xiě)XML控件也行。

定義單選和多選的規(guī)則:

(1)protected static int isShow; 0 表示都不顯示,1表示顯示左邊,2表示顯示右邊,默認(rèn)為1
(2)protected static boolean isRadio; 表示單選/多選,true表示單選,false表示多選

定義RecyclerView

private void initView(){
        recyclerView = new RecyclerView(context);
        recyclerView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        recyclerView.setBackgroundResource(builder.backgroupColorResID);
        recyclerView.setLayoutManager(builder.layoutManager);
        if (builder.itemDecoration != null) {
            recyclerView.addItemDecoration(builder.itemDecoration);
        }
    }

數(shù)據(jù)要繼承

 public static class CheckRecyclerEntity{
        public boolean leftCheck;
        public boolean rightCheck;
    }

表示左邊是否點(diǎn)擊和右邊是否點(diǎn)擊

最關(guān)鍵是ViewHolder的兩個(gè)方法:
(1)initView

public CheckRecyclerViewHolder(View itemView, Context context) {
            super(itemView, context);
            ButterKnife.inject(this,itemView);

            if (isShow == 0){
                cbLeft.setVisibility(View.GONE);
                cbRight.setVisibility(View.GONE);
            }else if (isShow == 1){
                cbLeft.setVisibility(View.VISIBLE);
                cbRight.setVisibility(View.GONE);
            }else if (isShow == 2){
                cbLeft.setVisibility(View.GONE);
                cbRight.setVisibility(View.VISIBLE);
            }
            // 設(shè)置CheckBox的樣式
            if (checkboxResID != 0) {
                cbLeft.setButtonDrawable(checkboxResID);
                cbRight.setButtonDrawable(checkboxResID);
            }
            // 應(yīng)反射創(chuàng)建viewmodel對(duì)象
            try {
                Class<?> myClass = Class.forName(vmName);//完整類名
                Class[] paramTypes = { Context.class };
                Object[] params = {context};
                Constructor con = myClass.getConstructor(paramTypes);
                viewmodel = (BaseViewModel) con.newInstance(params);
                flContent.addView(viewmodel.getContentView());
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }

首先判斷isShow 是單選/多選/隱藏 來(lái)展示頁(yè)面。然后設(shè)置CheckBox的樣式。
最后創(chuàng)建ViewModel對(duì)象添加到最上邊圖中實(shí)線的區(qū)域中。但是我們展示的頁(yè)面并不是固定的,也就是說(shuō)我們會(huì)在不同的情況創(chuàng)建不同的viewmodel對(duì)象,所以這里不能直接寫(xiě),我用了反射來(lái)添加viewmodel,所以在上邊調(diào)用的地方傳了viewmodel的包名+類名,是為了用類名創(chuàng)建相應(yīng)的viewmodel對(duì)象添加到區(qū)域中。

(2)setDataToView

@Override
        public void setDataToView() {
            super.setDataToView();
            // 處理選擇框的點(diǎn)擊 , 只做數(shù)據(jù)展示,邏輯放在外邊處理
            cbLeft.setChecked(data.leftCheck);
            cbRight.setChecked(data.rightCheck);
            //為viewmodel添加數(shù)據(jù)
            viewmodel.setData(data);
        }

這個(gè)就很簡(jiǎn)單了,根據(jù)leftCheck和rightCheck的值設(shè)置左右checkbox的展示,然后給viewmodel設(shè)置數(shù)據(jù)。

2.點(diǎn)擊時(shí)的處理

做完展示時(shí)的處理之后就要做點(diǎn)擊時(shí)的邏輯處理。

@OnClick({R.id.cb_left,R.id.cb_right})
        public void itemClick(View v){
            switch (v.getId()){
                case R.id.cb_left:
                    if (isRadio) {
                        // 單選
                        Observable.just(getAdapterPosition()).subscribe(observer1);
                    }else {
                        // 多選
                        Observable.just(getAdapterPosition()).subscribe(observer2);
                    }
                    break;
                case R.id.cb_right:
                    if (isRadio) {
                        Observable.just(getAdapterPosition()).subscribe(observer1);
                    }else {
                        Observable.just(getAdapterPosition()).subscribe(observer2);
                    }
                    break;
            }
        }

先判斷點(diǎn)左還是點(diǎn)右,再判斷是單選模式還是多選模式,我這里用了觀察者模式。

 // 單選情況下的觀察者
    private static Action1<Integer> observer1 = new Action1<Integer>() {
        @Override
        public void call(Integer integer) {
            if (adapter != null){
                adapter.checkChange(integer);
            }
        }
    };
    // 多選情況下的觀察者
    private static Action1<Integer> observer2 = new Action1<Integer>() {
        @Override
        public void call(Integer integer) {
            if (adapter != null){
                adapter.multiChose(integer);
            }
        }
    };

點(diǎn)擊之后會(huì)在adapter中做響應(yīng)操作。

/**
         * 單選
         */
        public void checkChange(int position){
            if (position < dataSource.size()) {
                // 先將所有都設(shè)為未點(diǎn)擊
                for (int i = 0; i < dataSource.size(); i++) {
                    dataSource.get(i).leftCheck = false;
                    dataSource.get(i).rightCheck = false;
                }
                // 再設(shè)置點(diǎn)擊的Item
                if (isShow == 1) {
                    dataSource.get(position).leftCheck = true;
                    leftRadio = position;
                }else if (isShow == 2){
                    dataSource.get(position).rightCheck = true;
                    rightRadio = position;
                }

                // 做響應(yīng)
                if (radioObserver != null) {
                    radioObserver.radioClick(position, isShow);
                }

                this.notifyDataSetChanged();
            }
        }

        /**
         *  多選
         */
        public void multiChose(int position){
            // 點(diǎn)擊后展示相反的情況
            if (isShow == 1) {
                dataSource.get(position).leftCheck = !dataSource.get(position).leftCheck;
            }else if (isShow == 2){
                dataSource.get(position).rightCheck = !dataSource.get(position).rightCheck;
            }

            // 做響應(yīng)
            if (multiObserver != null) {
                multiObserver.multiClick(position, isShow);
            }

            this.notifyDataSetChanged();
        }

注釋都有,算法也不難,不用詳細(xì)去講了。主要封裝的邏輯其實(shí)也就這些,而其他的方法基本都是和外邊交互時(shí)用到的方法,我都寫(xiě)了注釋。
比如

/**
     *  外部控制內(nèi)部進(jìn)行單選的操作
     */
    public void setRadio(int position){
        if (adapter != null){
            adapter.checkChange(position);
        }
    }

這個(gè)就是外面要求里面單選哪個(gè)。比如說(shuō)有些需求是要默認(rèn)選第一個(gè),所以可以在外面調(diào)用checkRecyclerView.setRadio(0);

/**
     *  設(shè)置全選/全不選
     *  規(guī)則:true表示全選 false表示全不選
     */
    public void setAllMulti(Boolean bol){
        if (adapter != null){
            adapter.setAllMulti(bol);
        }
    }

這是設(shè)置全選,比如外面點(diǎn)擊哪個(gè)按鈕后里面顯示全選,那就在外面調(diào)用checkRecyclerView.setAllMulti(true);

其它的什么我都加了注釋,就不都說(shuō)了。

3.Builder的屬性

簡(jiǎn)單介紹在Builder中定義的屬性吧
(1)isShow 顯示選擇框在左還是右
(2)datalist需要適配的數(shù)據(jù)
(3)itemDecoration RecyclerView的分割線
(4)layoutManager RecyclerView的布局
(5)backgroupColorResID RecyclerView的顏色
(6)checkboxResID Checkbox的樣式ID
(7)isRadio 單選還是多選
(8)radioObserver 單選的監(jiān)聽(tīng),要實(shí)現(xiàn)這個(gè)接口
(9)multiObserver 多選的監(jiān)聽(tīng)
(10)vmName viewmodel的包名+類名
注意要傳包名+類名,只傳類名不行嗎?不行,因?yàn)椴煌陌驴梢杂邢嗤念惷?,我怎么懂是要哪個(gè)。

其實(shí)我覺(jué)得代碼也不算多,也不難理解,最近沒(méi)時(shí)間也沒(méi)能寫(xiě)個(gè)demo放到github上,之后閑下來(lái)再弄吧。然后也沒(méi)經(jīng)過(guò)嚴(yán)格的測(cè)試,可能一些地方寫(xiě)得不是很好。


更新

后來(lái)我用這個(gè)東西發(fā)現(xiàn)一個(gè)錯(cuò)的地方,就是內(nèi)部類和成員都不要使用static,不然在多處使用的時(shí)候會(huì)出錯(cuò)。當(dāng)初習(xí)慣性的會(huì)下意思使用靜態(tài)內(nèi)部類,后來(lái)發(fā)現(xiàn)用著用著就有問(wèn)題了。還是太粗心了。
把代碼中的靜態(tài)內(nèi)部類和靜態(tài)成員改成非靜態(tài)的就行。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,745評(píng)論 25 709
  • 這篇文章分三個(gè)部分,簡(jiǎn)單跟大家講一下 RecyclerView 的常用方法與奇葩用法;工作原理與ListView比...
    LucasAdam閱讀 4,687評(píng)論 0 27
  • 前言: 有感畢淑敏老師的巜我所喜愛(ài)的女人》,云煙亦寫(xiě)下了巜我喜歡的女人》,可能內(nèi)容有部分雷同,可能人人喜歡的女...
    當(dāng)代詩(shī)人云煙閱讀 365評(píng)論 2 1
  • 你是天空中的一滴雨 投影在我心里 你不必感嘆 也不必詫異 一瞬間 你打濕了我 相逢在雨中 你輕輕飄來(lái) 我用身體身體...
    閣樓書(shū)生閱讀 336評(píng)論 3 5
  • 諾維斯基堅(jiān)守達(dá)拉斯19年,高峰低谷一路走來(lái)不離不棄,他從來(lái)不是某些人口中的軟蛋,現(xiàn)在他是一個(gè)真正的城市英雄。 達(dá)拉...
    西科南麥閱讀 1,037評(píng)論 6 5

友情鏈接更多精彩內(nèi)容