Android RecyclerView createViewHolder異常

項(xiàng)目用的是這個(gè)人的框架
https://github.com/CymChad/BaseRecyclerViewAdapterHelper

測(cè)試發(fā)現(xiàn)rv底層拋出了一個(gè)異常,不斷滑動(dòng)加載更多出現(xiàn)的

ViewHolder views must not be attached when created. Ensure that you are not passing 'true' to the attachToRoot parameter of LayoutInflater.inflate(..., boolean attachToRoot)

看了下大佬的框架好像沒(méi)人解決過(guò)這個(gè)問(wèn)題


image.png

錯(cuò)誤異常如下代碼

java.lang.IllegalStateException: ViewHolder views must not be attached when created. Ensure that you are not passing 'true' to the attachToRoot parameter of LayoutInflater.inflate(..., boolean attachToRoot)
    at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:6687)
    at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5869)
    at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5752)
    at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5748)
    at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2232)
    at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1559)
    at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1519)
    at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1333)
    at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:1077)
    at android.support.v7.widget.RecyclerView.scrollByInternal(RecyclerView.java:1815)
    at android.support.v7.widget.RecyclerView.onTouchEvent(RecyclerView.java:3076)
    at android.view.View.dispatchTouchEvent(View.java:9939)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2663)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2344)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358)
    at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:411)
    at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1810)

百度搜了幾篇文章都說(shuō)

image.png

可是我看了作者的代碼本來(lái)就這樣寫

image.png

懷著好奇的跟蹤了下源碼,源碼路徑
/frameworks/support/v7/recyclerview/src/main/java/androidx/recyclerview/widget/RecyclerView.java

/**
6739         * This method calls {@link #onCreateViewHolder(ViewGroup, int)} to create a new
6740         * {@link ViewHolder} and initializes some private fields to be used by RecyclerView.
6741         *
6742         * @see #onCreateViewHolder(ViewGroup, int)
6743         */
6744        @NonNull
6745        public final VH createViewHolder(@NonNull ViewGroup parent, int viewType) {
6746            try {
6747                TraceCompat.beginSection(TRACE_CREATE_VIEW_TAG);
6748                final VH holder = onCreateViewHolder(parent, viewType);
6749                if (holder.itemView.getParent() != null) {
6750                    throw new IllegalStateException("ViewHolder views must not be attached when"
6751                            + " created. Ensure that you are not passing 'true' to the attachToRoot"
6752                            + " parameter of LayoutInflater.inflate(..., boolean attachToRoot)");
6753                }
6754                holder.mItemViewType = viewType;
6755                return holder;
6756            } finally {
6757                TraceCompat.endSection();
6758            }
6759        }

從代碼來(lái)看holder.itemView.getParent() 不為null就會(huì)拋出這個(gè)異常,然后我再看了看final VH holder = onCreateViewHolder(parent, viewType);
可能我很久沒(méi)寫代碼,發(fā)現(xiàn)onCreateViewHolder是要自己去實(shí)現(xiàn)邏輯的

 /**
6659         * Called when RecyclerView needs a new {@link ViewHolder} of the given type to represent
6660         * an item.
6661         * <p>
6662         * This new ViewHolder should be constructed with a new View that can represent the items
6663         * of the given type. You can either create a new View manually or inflate it from an XML
6664         * layout file.
6665         * <p>
6666         * The new ViewHolder will be used to display items of the adapter using
6667         * {@link #onBindViewHolder(ViewHolder, int, List)}. Since it will be re-used to display
6668         * different items in the data set, it is a good idea to cache references to sub views of
6669         * the View to avoid unnecessary {@link View#findViewById(int)} calls.
6670         *
6671         * @param parent The ViewGroup into which the new View will be added after it is bound to
6672         *               an adapter position.
6673         * @param viewType The view type of the new View.
6674         *
6675         * @return A new ViewHolder that holds a View of the given view type.
6676         * @see #getItemViewType(int)
6677         * @see #onBindViewHolder(ViewHolder, int)
6678         */
6679        @NonNull
6680        public abstract VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType);

然后我又看了下作者封裝的這個(gè)方法

image.png

好奇按百度出來(lái)的博客跟了下源碼LayoutInflater源碼,的確如此

image.png

又看了下RecyclerView的ViewHolder,創(chuàng)建ViewHolder的時(shí)候會(huì)傳遞itemView

image.png

問(wèn)題可能是復(fù)用的時(shí)候調(diào)用了onCreateViewHolder,onCreateViewHolder出現(xiàn)神經(jīng)病,認(rèn)為itemView有parent,或者是rv緩存問(wèn)題,或者我分析方向不對(duì)

因?yàn)槲揖蛷?fù)現(xiàn)過(guò)2次,后面就沒(méi)復(fù)現(xiàn)了就按大佬說(shuō)緩存下,原本項(xiàng)目中沒(méi)設(shè)置setOffscreenPageLimit,后面有時(shí)間再研究,可能我比較菜

fragment在viewpager容器里來(lái)回切換,如果沒(méi)有設(shè)置,會(huì)導(dǎo)致重復(fù)實(shí)例化,重復(fù)加載數(shù)據(jù),
建議在設(shè)置一個(gè)緩存,
解決方式:給page



mViewPager.setOffscreenPageLimit(3);
為什么重復(fù)實(shí)例化會(huì)出現(xiàn)這個(gè)問(wèn)題,現(xiàn)在我的需求就是需要重新刷新這個(gè)fragment,怎么處理?
最后編輯于
?著作權(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)容

  • RecyclerView Item 布局寬高無(wú)效問(wèn)題探究 前言 這個(gè)問(wèn)題很早之前就碰到過(guò),后來(lái)通過(guò)google找到...
    TinyMen閱讀 466評(píng)論 0 0
  • 緣由 最近項(xiàng)目我在項(xiàng)目中使用了RecyclerView代替了ListView。其實(shí),怎么說(shuō)呢?就是懶,想少寫代碼,...
    比薩u閱讀 875評(píng)論 0 12
  • 初識(shí)Android時(shí),我對(duì)ListView、GradView中的Adapter一直半懂非懂,每次寫Adapter都...
    blink_dagger閱讀 6,091評(píng)論 4 10
  • 生活本來(lái)就不容易,而我們的不努力只會(huì)讓生活變得更加無(wú)賴 前幾天依據(jù)《Android群英傳》的學(xué)習(xí)寫了一篇筆記是關(guān)于...
    AmatorLee閱讀 3,837評(píng)論 7 23
  • https://mp.weixin.qq.com/s/D-GfuHip5R_wI7SwqBWciA
    另一個(gè)我nn閱讀 121評(píng)論 0 0

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