RecyclerView的超強(qiáng)輔助Graywater——綜合實操篇

關(guān)于Graywater的系列文章

  1. RecyclerView的超強(qiáng)輔助Graywater——理論篇
  2. RecyclerView的超強(qiáng)輔助Graywater——基礎(chǔ)實操篇
  3. RecyclerView的超強(qiáng)輔助Graywater——點(diǎn)擊事件
  4. RecyclerView的超強(qiáng)輔助Graywater——綜合實操篇

看到上一篇Graywater文章是11月8日寫的,也是拖很久了,這篇是Graywater系列文章最后一篇完結(jié)篇,把自己挖的坑給填了。

這篇文章是Graywater綜合練習(xí)文章,包括了復(fù)雜視圖、基本增刪改功能的實現(xiàn),文末附有Demo地址,同樣Demo也只是起一個拋磚引玉的作用,實際上還有很大的延展空間。

先上Demo效果圖:

GraywaterDemo綜合.gif

老規(guī)矩,還是先說說本文目錄:

1. 復(fù)雜視圖的實現(xiàn)
2. 數(shù)據(jù)的插入
3. 數(shù)據(jù)的刪除
4. 數(shù)據(jù)的更新
5. 注意點(diǎn)

1. 復(fù)雜視圖的實現(xiàn)

從GIF圖中可以看到,該RecyclerView分為2大模塊,娛樂新聞模塊和體育新聞模塊,每個模塊對應(yīng)一個數(shù)據(jù)源Primitive和一個管理器ItemBinder,數(shù)據(jù)源就對應(yīng)了該模塊所有數(shù)據(jù)內(nèi)容,管理器對該模塊所有視圖進(jìn)行管理。

比如娛樂新聞模塊對應(yīng)了一個EntertainPrimitive和EntertainItemBinder,包含了該模塊的所有數(shù)據(jù),同時還包含了娛樂新聞標(biāo)題Binder和娛樂新聞內(nèi)容的Binder(娛樂新聞內(nèi)容的Binder使用List集合保存)。

GraywaterDemo模塊圖.png

接著往下看,在RecyclerView里有3種視圖:標(biāo)題視圖、娛樂新聞視圖、體育新聞視圖。每種視圖都有一組自己對應(yīng)的Binder、ViewHolder和ViewHolderCreator以及自己的布局文件。

看看實現(xiàn)娛樂新聞視圖的核心代碼:
EntertainItemBinder.java

    @NonNull
    @Override
    public List<GraywaterAdapter.Binder<? super EntertainPrimitive, ? extends PrimitiveViewHolder>> getBinderList(@NonNull final EntertainPrimitive model, int position) {
        return new ArrayList<GraywaterAdapter.Binder<? super EntertainPrimitive, ? extends PrimitiveViewHolder>>() {{
            add(titleBinder);  //添加娛樂新聞標(biāo)題
            for (EntertainItem entertainItem : model.getEntertainItems()) {
                add(entertainBinder);    //添加娛樂新聞內(nèi)容
            }
        }};
    }

所以在ItemBinder中可以添加多種類型的binder,就可以實現(xiàn)不同的視圖了。

2. 數(shù)據(jù)的插入

插入娛樂新聞的核心代碼:

      @Override
    public void onClickaddNews(String type) {
        Toast.makeText(this, "add " + type + " success", Toast.LENGTH_SHORT).show();
        switch (type) {
            case TYPE_ENTERTAIN:
                addEntertainNews();
                mPrimitiveAdapter.remove(POS_ENTERTAIN);
                mPrimitiveAdapter.add(POS_ENTERTAIN, mEntertainPrimitive);
                //不需要mPrimitiveAdapter.notifyDataSetChanged();在add()方法中已經(jīng)包含了更新操作
                break;
            case TYPE_SPORT:
                addSportNews();
                mPrimitiveAdapter.remove(POS_SPORT);
                mPrimitiveAdapter.add(POS_SPORT, mSportPrimitive);
                break;
        }
    }    

    private void addEntertainNews() {
        if (entertainItems == null) {
            entertainItems = new ArrayList<>();
        }

        EntertainItem entertain = new EntertainItem();
        entertain.setId("" + (entertainItems.size() + 1));
        entertain.setUrl("https://img8.ccnxs.cn/uploadfile/hbase/201901/0129/HBC5C4FABFA51855.png");
        entertain.setTitle("item " + (entertainItems.size() + 1) + " : " + "胡海泉獨(dú)自現(xiàn)身麗江 面帶微笑任拍照");
        entertainItems.add(entertain);
    }

3. 數(shù)據(jù)的刪除

刪除娛樂新聞的核心代碼:

    @Override
    public void onClickDeleteEntertain(EntertainItem entertain) {
        boolean needRefresh = false;
        Iterator iterator = entertainItems.iterator();
        while (iterator.hasNext()) {
            EntertainItem entertainItem = (EntertainItem) iterator.next();
            if (entertainItem.getId().equals(entertain.getId())) {
                iterator.remove();
                needRefresh = true;
                break;
            }
        }

        if (needRefresh) {
            mPrimitiveAdapter.remove(POS_ENTERTAIN);
            mPrimitiveAdapter.add(POS_ENTERTAIN, mEntertainPrimitive);
        }
    }

4. 數(shù)據(jù)的更新

更新娛樂新聞的核心代碼:

點(diǎn)擊娛樂新聞跳轉(zhuǎn)到編輯頁進(jìn)行編輯,編輯成功返回MainActivity,在onActivityResult()方法中進(jìn)行處理,實際上娛樂新聞和體育新聞的編輯是不應(yīng)該放在同一個編輯頁的,我這里圖方便就寫在一起了。

    @Override
    public void onClickEditEntertain(EntertainItem entertain) {
        Intent intent = new Intent(this, EditActivity.class);
        intent.putExtra("type", TYPE_ENTERTAIN);
        intent.putExtra("obj", entertain);
        startActivityForResult(intent, 11);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (resultCode) {
            case 100:
                String type = data.getStringExtra("type");
                if (MainActivity.TYPE_ENTERTAIN.equals(type)) {
                    updateEntertainItem((EntertainItem) data.getSerializableExtra("obj"));
                } else {
                    updateSportItem((SportItem) data.getSerializableExtra("obj"));
                }
                break;
        }
    }

    private void updateEntertainItem(EntertainItem item) {
        boolean needRefresh = false;
        Iterator iterator = entertainItems.iterator();
        while (iterator.hasNext()) {
            EntertainItem entertainItem = (EntertainItem) iterator.next();
            if (entertainItem.getId().equals(item.getId())) {
                entertainItem.setTitle(item.getTitle());
                needRefresh = true;
                break;
            }
        }

        if (needRefresh) {
            mPrimitiveAdapter.remove(POS_ENTERTAIN);
            mPrimitiveAdapter.add(POS_ENTERTAIN, mEntertainPrimitive);
        }
    }

5. 注意點(diǎn)

· binderIndex

看一下娛樂新聞內(nèi)容EntertainBinder中的關(guān)鍵代碼

    @Override
    public void bind(@NonNull EntertainPrimitive model, @NonNull EntertainViewHolder holder, @NonNull List<GraywaterAdapter.Binder<? super EntertainPrimitive, ? extends EntertainViewHolder>>
            binders, int binderIndex, @NonNull GraywaterAdapter.ActionListener<EntertainPrimitive, EntertainViewHolder> actionListener) {
        EntertainItem entertain = model.getEntertainItems().get(binderIndex - 1);  //因為第一個數(shù)據(jù)是新聞標(biāo)題,所以新聞內(nèi)容數(shù)據(jù)獲取時要減一

        Picasso.get().load(entertain.getUrl()).placeholder(R.mipmap.ic_launcher).into(holder.getImg());
        holder.getTitle().setText(entertain.getTitle());

        holder.getmActionListenerDelegate().update(actionListener, model, holder, binders, binderIndex, null);
        holder.getMainLayoutView().setOnClickListener(holder.getmActionListenerDelegate());
        holder.getDelete().setOnClickListener(holder.getmActionListenerDelegate());
    }

注意這句代碼:

EntertainItem entertain = model.getEntertainItems().get(binderIndex - 1);

有沒有疑惑為什么要binderIndex要減1?上文也提到EntertainItemBinder是對標(biāo)題和內(nèi)容統(tǒng)一進(jìn)行管理,而binderIndex返回的是binder的下標(biāo)??匆幌聰帱c(diǎn)截圖就明白了:

斷點(diǎn).png

因為包含了標(biāo)題TitleBinder,所以第一條新聞內(nèi)容對應(yīng)的binderIndex對應(yīng)的下標(biāo)是1,但新聞內(nèi)容的數(shù)據(jù)集合與新聞標(biāo)題的數(shù)據(jù)是相互獨(dú)立,沒有關(guān)系的,所以第一條新聞內(nèi)容在數(shù)據(jù)集合中的位置是0,所以binderIndex需要減1。

補(bǔ)充:

如果對你有幫助的話,點(diǎn)贊、評論、贊賞都是對我的鼓勵,也是支持我寫下去的動力,謝謝!

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

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