RecyclerView in React Native: notifyItemInserted() and notifyDataSetChanged() have no effect

后端 未结 2 498
深忆病人
深忆病人 2021-01-15 12:52

I am experimenting with integrating a Firebase-backed RecyclerView in a React Native app. With hardcoded data it works well, but upon inserting rows loaded dynamically and c

相关标签:
2条回答
  • 2021-01-15 13:39

    The root view in ReactNative is ReactRootView which onlayout is an empty method.

    when call notifyDatasetChanged in RecyclerView, it's actually request layout to relayout its children. And the layout method will call super.layout to travel the whole view tree first. So that't a problem when the root view is ReactRootView.

    You can manually call RecyclerView.onlayout(boolean changed, int l, int t, int r, int b) to trigger its children relayout to make notifyDatasetChanged work.

    0 讨论(0)
  • 2021-01-15 13:40

    The problem is that requestLayout does not work well when the RecyclerView is a native UI component.

    The following hack made all those issues go away:

    I now overwrite the requestLayout method inside my RecyclerView. Then before any notify* method, or even scrollToPosition calls or any method that invokes a re-layout, I allow my custom requestLayout method to force a re-layout.

    The end result looks like this:

    private boolean mRequestedLayout = false;
    
    
    public void aMethodThatUpdatesStuff(int indexToUpdate, ReadableMap updatedChild) {
        final SPAdapter adapter = (SPAdapter) getAdapter();
        mRequestedLayout = false;
        adapter.updateDataAtIndex(indexToUpdate, updatedChild); // <-- this runs notifyItemChanged inside
    }
    
    @Override
    public void requestLayout() {
        super.requestLayout();
        // We need to intercept this method because if we don't our children will never update
        // Check https://stackoverflow.com/questions/49371866/recyclerview-wont-update-child-until-i-scroll
        if (!mRequestedLayout) {
            mRequestedLayout = true;
            this.post(new Runnable() {
                @SuppressLint("WrongCall")
                @Override
                public void run() {
                    mRequestedLayout = false;
                    layout(getLeft(), getTop(), getRight(), getBottom());
                    onLayout(false, getLeft(), getTop(), getRight(), getBottom());
                }
            });
        }
    }
    
    0 讨论(0)
提交回复
热议问题