Android 支持RecyclerView&x27;在触摸之前不要显示任何内容
我在我的应用程序中使用了支持回收视图,我看到了最奇怪的事情。它不会显示任何项目,直到我触摸滚动。然后,一下子,RecyclerView就出现了。我已经验证了支持适配器的列表是否已填充,并且在发生触摸事件之前,不会调用onCreatViewHolder和onBindViewHolder 下面是我如何设置recyclerview的:Android 支持RecyclerView&x27;在触摸之前不要显示任何内容,android,android-recyclerview,Android,Android Recyclerview,我在我的应用程序中使用了支持回收视图,我看到了最奇怪的事情。它不会显示任何项目,直到我触摸滚动。然后,一下子,RecyclerView就出现了。我已经验证了支持适配器的列表是否已填充,并且在发生触摸事件之前,不会调用onCreatViewHolder和onBindViewHolder 下面是我如何设置recyclerview的: @Override public void onViewCreated(View view, @Nullable Bundle savedInstanc
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
Drawable divider = new ColorDrawable(ProfileInfo.getCurrentProfileColor());
mInboxList.addItemDecoration(new DividerItemDecoration(getActivity(), divider, false));
mInboxList.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
mInboxList.setAdapter(new InboxAdapter(getActivity(), new ArrayList<Conversation>()));
new AsyncTask<Void, Void, List<Conversation>{
public List<Conversation> doInBackground(...){
//load the conversations
return conversations;
}
public void onPostExecute(List<Conversation> conversations){
((InboxAdapter) mInboxList.getAdapter()).clear(false);
((InboxAdapter) mInboxList.getAdapter()).addAll(conversations);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
这很可能是因为您没有调用RecyclerView.Adapter的正确通知方法。与以前在ListAdapters中的接口相比,您有一个更细粒度的接口。例如,在addAll()中,您应该调用
notifyItemRangeSerted(oldConversationsSize,conversations.size())
,而不是notifyDataSetChanged
,您必须在UI线程上运行在onPostExecute中执行的操作,以便重新绘制RecyclerView。这就是平滑滚动工作的原因,因为它在UI线程上运行,因此导致视图重新绘制。如果其他人使用RxJava和改型遇到此问题,我在订阅之前将.observeOn(AndroidSchedulers.mainThread())
操作符添加到我的方法链中,从而解决了此问题。我已经读到这是默认的,因此没有明确的必要,但我想没有。希望这有帮助
例如:
public void loadPhotos() {
mTestPhotoService.mServiceAPI.getPhotos()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(photoList -> mRecyclerActivity.OnPhotosLoaded(photoList));
}
就我而言,只有这样做有效:
recyclerView.smoothScrollToPosition(arrayModel.size-1); // I am passing last position here you can pass any existing position
RecyclerView仅在我滚动数据时才显示数据。因此,我没有让用户手动滚动,而是在上面添加了一行,它将以编程方式滚动recyclerView 我也有同样的问题2天了,添加这一行后就解决了 adapter.notifyDataSetChanged()//在通知适配器之后添加此适配器
mRecyclerView.smoothScrollToPosition(list.size-1)在我的例子中,它只发生在Android 6上。在这个版本之上,我没有任何问题。 所以我发现有效的方法是使用recyclerView.scrollBy(0,0)。
检查一下,也许它也会对你有用。所以首先,就像我刚才添加的其他人一样:
recyclerView.smoothScrollToPosition(0)
它的效果非常好,但是它并不好,你必须记住每次都要添加它。
然后我跟随了@SudoPlz注释和另一个问题,它也起了作用,您必须扩展RecyclerView并覆盖requestLayout:
private boolean mRequestedLayout = false;
@SuppressLint("WrongCall")
@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(() -> {
mRequestedLayout = false;
layout(getLeft(), getTop(), getRight(), getBottom());
onLayout(false, getLeft(), getTop(), getRight(), getBottom());
});
}
}
尽管如此,我还是希望在4、5年后修复此问题,但是,这是一个很好的解决方法,在您看来,您不会忘记它们。由于这种情况仍在发生,下面是一个特定的修复实例,以防它对某人有所帮助:
- 只有当单元视图包含WebView时才会发生这种情况
- 从ViewHolder调用setIsRecyclable(false)
- 将recyclerview设置为在xml布局上可见(因此在设置TabView时完全绘制)李>
- 设置适配器时(链接到observable with room),我会:
- 这有点晚了,但在我的例子中,我在另一个viewpager(使用BottomNavigationView)中的一个viewpager(选项卡视图)中有一个recylerview,平滑滚动并没有改变任何东西
但是,我注意到在绘制布局时,我设置了recylerview,但可见性消失了,因此解决方案是:
您是否建议notifyDataSetChange不会更新UI?notifyItemRangeInserted(oldConversationsSize,conversations.size())没有解决此问题。因为正在后台线程上调用subscribe方法。这是根本原因,没错。为了更好地说明这一点,我在链中添加了.subscribeOn()。感谢您给出的答案,逻辑性很强,但我忽略了它。您的“编辑”应该是答案:)smoothScrollToPosition不是答案,它是一种变通方法。我仍然有这个问题,而且我真的负担不起每次更新数据时的平滑滚动定位。你知道问题背后的真正原因吗?我有点明白了。它是
requestLayout
没有做任何事情。我覆盖了requestLayout,强制调用onLayout,现在它可以工作了。悲伤。对我来说,循环视图。平滑滚动位置(0);这应该是一个公认的答案。这可能和smoothScrollToPosition一样草率,但它涵盖了适配器中有0项的情况。
recyclerView.smoothScrollToPosition(arrayModel.size-1); // I am passing last position here you can pass any existing position
recyclerView.smoothScrollToPosition(0)
private boolean mRequestedLayout = false;
@SuppressLint("WrongCall")
@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(() -> {
mRequestedLayout = false;
layout(getLeft(), getTop(), getRight(), getBottom());
onLayout(false, getLeft(), getTop(), getRight(), getBottom());
});
}
}
new Handler(Looper.getMainLooper()).postDelayed(() -> {
binding.recyclerView.scrollToPosition(0);
}, getResources().getInteger(android.R.integer.config_shortAnimTime));