具有共享ViewPool的多个RecyclerView不会有效地重用/回收视图

时间:2017-02-26 17:02:32

标签: android android-recyclerview recycler-adapter recyclerview-layout

我在RecylerViews中有两个LinearLayoutScrollView内有垂直方向。两个RecyclerViews都希望在TextViews中显示包含6个字符串的列表。这样的安排是,一开始,只有第一个TextViews的{​​{1}}出现,滚动时,第二个RecyclerView的那些出现。

我的期望是,由于第二个RecyclerView的{​​{1}}都不可见,因此不会创建它们,一旦它们进入视野,TextViews将会被调用重用现有的RecyclerView。但是,创建了所有单个onBindViewHolderViewHolders已调用)。难道我做错了什么?因为如果这是预期的,没有必要设置一个常见的ViewPool,是吗?

活动代码

ViewHolders

布局

onCreateView

的TextView

public class MainActivity extends AppCompatActivity {
    private List<String> names = Arrays.asList(
        "Name 1", "Name 2", "Name 3", "Name 4", "Name 5", "Name 6"
    );

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        RecyclerView.RecycledViewPool viewPool = new RecyclerView.RecycledViewPool();

        RecyclerView recycler1 = (RecyclerView) findViewById(R.id.recycler1);
        RecyclerView recycler2 = (RecyclerView) findViewById(R.id.recycler2);

        recycler1.setLayoutManager(new LinearLayoutManager(this));
        recycler2.setLayoutManager(new LinearLayoutManager(this));

        recycler1.setRecycledViewPool(viewPool);
        recycler2.setRecycledViewPool(viewPool);

        recycler1.setNestedScrollingEnabled(false);
        recycler2.setNestedScrollingEnabled(false);

        recycler1.setAdapter(new SampleAdapter(new ArrayList<>(names), 1));
        recycler2.setAdapter(new SampleAdapter(new ArrayList<>(names), 2));
    }

    private class SampleAdapter extends RecyclerView.Adapter {
        private final List<String> mSampleList;
        private final int mRecyclerId;

        SampleAdapter(List<String> sampleList, int recyclerId) {
            mSampleList = sampleList;
            mRecyclerId = recyclerId;
        }

        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            Log.i("TESTING", "creating a new view for parent Id: " + mRecyclerId);
            TextView textView = (TextView) getLayoutInflater().inflate(R.layout.text_view_name, null);
            return new SampleViewHolder(textView);
        }

        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            Log.i("TESTING", "binding existing view for parent Id: " + mRecyclerId + " for position: " +
                position);
            ((SampleViewHolder)holder).bind(mSampleList.get(position));
        }

        public int getItemCount() {
            return mSampleList.size();
        }
    }

    private class SampleViewHolder extends RecyclerView.ViewHolder {
        private TextView mText;
        public SampleViewHolder(TextView itemView) {
            super(itemView);
            mText = itemView;
        }

        public void bind(String s) {
            mText.setText(s);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

首先,在RecyclerView中使用ScrollView绝不是一个好主意。一个ScrollView将布置它的子项,在你的情况下是一个LinearLayout,它也将布局它的子项:2个RecyclerViews。

我将从下往上开始:RecyclerView和父母一样高,或者更低,因为他们被告知wrap_content。它们都得到了布局,并且在LinearLayout中,它们将具有两个RecyclerViews的高度。如果LinearLayout大于屏幕,ScrollView将使所有内容都可滚动。您现在拥有一个高大的布局,可以显示完整内容并且可以滚动。

需要注意的事项:滚动视图回收任何视图。如果一个视图在屏幕外,它可能不会被绘制,但视图本身不会&#34;行为&#34;根据此信息,对于所有视图都知道它当前显示给用户。基本上,两个RecyclerViews都在LinearLayout中正确布局到它们的全高,这将拉伸到所需的高度。 RecyclerViews知道它们是可见的 - 并且需要让所有孩子都受到约束。 这是您的问题&#34;。

  

没有必要设置一个常见的ViewPool,是吗?

由于两个RecyclerViews都是可见的&#34;没有回收利用,也没有再利用。不会滚动的RecyclerView因为它在ScrollView内部将回收其视图。你是对的,没有回收,共享的ViewPool也没用。

使用您描述的布局,您应该完全摆脱ScrollView,并使用单个RecyclerView 来正确滚动和回收视图。无论您需要ScrollView for,您都可以使用RecyclerView完成相同的操作。 ScrollView用于静态布局,RecyclerView用于列表。

如果您有多个片段或类似ViewPagers的内容,则可以使用共享ViewPools,在不同的屏幕上有很多相同的视图。