首页 文章

添加View将RecyclerView作为父级,但视图不是真正的孩子

提问于
浏览
3

当RecyclerView的内容发生变化时,我有时会出现问题 . 我有搜索视图,过滤RecyclerView的数据 . 过滤后我调用notifyDataSetChanged();

我使用https://gist.github.com/mheras/0908873267def75dc746作为适配器 .

我当时认为这个问题与添加页脚有关,但删除页脚问题后仍然会出现,但不是经常出现

例外:

java.lang.IllegalStateException:添加了View将RecyclerView作为父级,但视图不是真正的子级 . 未过滤的索引:0,android.support.v7.widget.RecyclerView $ LayoutManager.addViewInt(RecyclerView.java:7048),位于android.support的android.support.v7.widget.RecyclerView $ LayoutManager.addView(RecyclerView.java:7012) .v7.widget.RecyclerView $ LayoutManager.addView(RecyclerView.java:7000)在android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1428)android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager) .java:1377)在Android.support.v7上的android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:578)android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3260) . widget.RecyclerView.dispatchLayout(RecyclerView.java:3069)位于android.view.view.layout(View.java:16636)的android.sview.v7.widget.RecyclerView.onLayout(RecyclerView.java:3518)android.view .ViewGroup.layout(ViewGroup.java:5437)在android.vie的android.support.v4.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:598)在Android.widget.FrameLayout.onLayout的android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)的android.view.ViewGroup.layout(ViewGroup.java:5437)的w.View.layout(View.java:16636) (FrameLayout.java:273)在Android.widget.FrameLayout.layoutChildren(FrameLayout.java)的android.view.View.layout(ViewGroup.java:5437)上的android.view.View.layout(View.java:16636) 336)在android.view.Loutout(ViewLayout.java:273)的android.view.View.layout(View.java:16636)上的android.view.View( . widget.FrameLayout.layoutChildren(FrameLayout.java:336)位于android.view.View.Viewout.layout的android.view.View.layout(View.java:16636)的android.widget.FrameLayout.onLayout(FrameLayout.java:273) (ViewGroup.java:5437)android.widget.FrameLayout.onout中的android.widget.FrameLayout.layoutChildren(FrameLayout.java:336),android.view.layout(View.java):android.widget.FrameLayout.onLayout(FrameLayout.java:273) 16636)在andr的android.view.ViewGroup.layout(ViewGroup.java:5437) oid.support.v7.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:435)在android.view.View.layout(View.java:16636)的android.view.ViewGroup.layout(ViewGroup.java:5437)在android .widget.FrameLayout.layoutChildren(FrameLayout.java:336)位于android.view.View.View的android.view.Routout.onLayout(FrameLayout.java:273)android.view.View.layout(View.java:16636) . android.widget.Line中的android.widget.Linear.ayoutVertical(LinearLayout.java:1586)的android.widget.LinearLayout.onLayout(LinearLayout.java:1586)的android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)布局(ViewGroup.java:5437)(LinearLayout.java) :1495)在android.view.View.layout(View.java:16636)的android.view.ViewGroup.layout(ViewGroup.java:5437)在android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)在android .widget.FrameLayout.onLayout(FrameLayout.java:273)at com.android.internal.policy.PhoneWindow $ DecorView.onLayout(PhoneWindow.java:2678)at android.view.View.layout(View.java:16636)at at android.view.ViewGroup.l ayout(ViewGroup.java:5437)位于android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1917)的android.view.ViewRootImpl.performLversout(ViewRootImpl.java:2171),来自android.view.ViewRootImpl.doTraversal(ViewRootImpl.java) :1107)在Android.view.ChoreIs上运行android.view.ViewRootImpl $ TraversalRunnable.run(ViewRootImpl.java:6013),在android.view.Choreographer.doCallbacks(Choreographer.java)的android.view.Choreographer $ CallbackRecord.run(Choreographer.java:858) 670)在Android.view.Handler.handleCallback(Handler.java:739)的android.view.Choreographer $ FrameDisplayEventReceiver.run(Choreographer.java:844)的android.view.Choreographer.doFrame(Choreographer.java:606) android.os.Handler.dispatchMessage(Handler.java:95)位于android.app.Looper.loop(Looper.java:148)的android.app.ActivityThread.main(ActivityThread.java:5417),位于java.lang.reflect .Method.invoke(NAT

2 回答

  • 0

    我遇到了同样的问题......我通过使用 Contextparent.getContext() 充气 ViewHolder 并在 inflate 的调用中指定 false 解决了这个问题:

    final override fun onCreateViewHolder(parent:ViewGroup,viewType:Int):RecyclerView.ViewHolder
    {
        View view = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.listitem,parent,false);
        return new RecyclerView.ViewHolder(view) {};
    }
    
  • 0

    我们实际通过编写自己的适配器解决它:

    public abstract class BaseRVAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    
        static final int HEADER_VIEW_TYPE = Integer.MAX_VALUE;
        static final int FOOTER_VIEW_TYPE = Integer.MAX_VALUE - 1;
    
        private BaseRVAdapterHeaderImpl adapterHeader;
    
        private BaseRVAdapterFooterImpl adapterFooter;
    
        public void setFooterImpl(BaseRVAdapterFooterImpl footerImpl) {
            adapterFooter = footerImpl;
        }
    
        public void setHeaderImpl(BaseRVAdapterHeaderImpl headerImpl) {
            adapterHeader = headerImpl;
        }
    
        public abstract RecyclerView.ViewHolder onCreateContentItemViewHolder(ViewGroup parent, int viewType);
    
        public abstract void onBindContentItemViewHolder(RecyclerView.ViewHolder holder, int position);
    
        public abstract int getContentItemCount();
    
        public int getContentItemViewType(int position) {
            return 0;
        }
    
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            if (viewType == HEADER_VIEW_TYPE) {
                return new HeaderViewHolder(adapterHeader.getHeaderView());
            }
    
            if (viewType == FOOTER_VIEW_TYPE) {
                return new FooterViewHolder(adapterFooter.getFooterView());
            }
    
            return onCreateContentItemViewHolder(parent, viewType);
        }
    
        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            if (holder instanceof HeaderViewHolder) {
                //bind header view holder
            } else if (holder instanceof FooterViewHolder) {
                adapterFooter.onBind(holder.itemView);
            } else {
                onBindContentItemViewHolder(holder, position - getHeaderItemCount());
            }
        }
    
        @Override
        public int getItemCount() {
            return getContentItemCount() + getHeaderItemCount() + getFooterItemCount();
        }
    
        @Override
        public int getItemViewType(int position) {
            if (hasHeader() && position < getHeaderItemCount()) {
                return HEADER_VIEW_TYPE;
            }
    
            if (position == getItemCount() - 1 && hasFooter()) {
                return FOOTER_VIEW_TYPE;
            }
    
            return getContentItemViewType(position - getHeaderItemCount());
        }
    
        public int getAdapterContentPosition(RecyclerView.ViewHolder holder) {
            return holder.getAdapterPosition() - getHeaderItemCount();
        }
    
        public void notifyContentItemRangeInserted(int positionStart, int itemCount) {
            notifyItemRangeInserted(positionStart + getHeaderItemCount(), itemCount);
        }
    
        public void notifyContentItemRangeRemoved(int positionStart, int itemCount) {
            notifyItemRangeRemoved(positionStart + getHeaderItemCount(), itemCount);
        }
    
        public void notifyContentItemRemoved(int position) {
            notifyItemRemoved(position + getHeaderItemCount());
        }
    
        public void notifyContentItemChanged(int position) {
            notifyItemChanged(position + getHeaderItemCount());
        }
    
        public void notifyFooterItemChanged() {
            notifyItemChanged(getContentItemCount() + getFooterItemCount());
        }
    
        public boolean hasHeader() {
            return adapterHeader != null;
        }
    
        boolean hasFooter() {
            return adapterFooter != null;
        }
    
        public int getHeaderItemCount() {
            return hasHeader() ? 1 : 0;
        }
    
        public int getFooterItemCount() {
            return hasFooter() ? 1 : 0;
        }
    
        public interface BaseRVAdapterHeaderImpl {
            View getHeaderView();
        }
    
        public static abstract class BaseRVAdapterFooterImpl {
            public abstract View getFooterView();
    
            public void onBind(View view) {
    
            }
        }
    
        private class HeaderViewHolder extends RecyclerView.ViewHolder {
            HeaderViewHolder(View itemView) {
                super(itemView);
            }
        }
    
        private class FooterViewHolder extends RecyclerView.ViewHolder {
            FooterViewHolder(View itemView) {
                super(itemView);
            }
        }
    
        public RecyclerView.ItemDecoration getBottomItemDecoration() {
            int marginBottom = App.getContext().getResources().getDimensionPixelSize(R.dimen.dimen_small);
    
            return new RecyclerView.ItemDecoration() {
                @Override
                public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
                    super.getItemOffsets(outRect, view, parent, state);
    
                    int position = parent.getChildAdapterPosition(view);
                    int contentItemCount = getContentItemCount();
                    if (position == contentItemCount) {
                        outRect.bottom = marginBottom;
                    }
                }
            };
        }
    }
    

相关问题