支持RecyclerView在触摸之前不会显示任何内容

时间:2015-01-15 02:08:07

标签: android android-recyclerview

我在我的应用程序中使用了RecyclerView支持,我看到了最奇怪的事情。在我触摸滚动之前,它不会显示任何项目。然后,突然之间,RecyclerView会自行填充。我已经确认填充了支持适配器的列表,并且在触摸事件之前永远不会调用onCreatViewHolder和onBindViewHolder。

以下是我如何设置recyclerview:

    @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);
     }

这是我的适配器的要点:

public class InboxAdapter extends RecyclerView.Adapter<InboxAdapter.ViewHolder> {
    List<Conversation> mConversations; //initialized in contructor

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = mInflater.inflate(R.layout.inbox_item, parent, false);
        ViewHolder holder = new ViewHolder(v);
        Log.d(LOG_TAG, "oncreateviewholder : " + viewType); //never called when I first bind the adapter
        return holder;
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
        final Conversation item = mConversations.get(position);
        Log.d(LOG_TAG, "binding " + position);
        ...
    }

    @Override
    public int getItemCount() {
        Log.d(LOG_TAG, "item count: " + mConversations.size());
        return mConversations.size();
    }

    /**
     * Empties out the whole and optionally notifies
     */
    public void clear(boolean notify) {
        mConversations.clear();
        if (notify) {
            notifyDataSetChanged();
        }
    }

    public void addAll(List<Conversation> conversations) {
        mConversations.addAll(conversations);
        notifyDataSetChanged();
    }


}

这是布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:app="http://schemas.android.com/apk/res-auto"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:paddingTop="?attr/actionBarSize">


    <android.support.v7.widget.RecyclerView
        android:id="@+id/lv_inbox"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        ></android.support.v7.widget.RecyclerView>
</RelativeLayout>

我正在使用版本4.4.4的Moto X上运行的recyclelerview-v7:21.0.3。

修改 onPostExecute末尾的平滑滚动似乎解决了这个问题:

if (mInboxList.getAdapter().getItemCount() > 0) {
    mInboxList.smoothScrollToPosition(0);
}

9 个答案:

答案 0 :(得分:8)

如果其他人在使用RxJava和Retrofit时遇到此问题,我通过在订阅之前将.observeOn(AndroidSchedulers.mainThread())运算符添加到我的方法链中来解决此问题。我读过这个是默认处理的,因此没有明确的必要,但我猜不是。希望这会有所帮助。

示例:

public void loadPhotos() {
    mTestPhotoService.mServiceAPI.getPhotos()
                                 .subscribeOn(Schedulers.io())
                                 .observeOn(AndroidSchedulers.mainThread())
                                 .subscribe(photoList -> mRecyclerActivity.OnPhotosLoaded(photoList));
}

答案 1 :(得分:1)

因此,起初,就像我刚刚添加的其他人一样:

recyclerView.smoothScrollToPosition(0)

,它已经足够好用了,但是它不是很好,您必须记住每次都添加它。 然后我跟随@SudoPlz注释和answer处理另一个问题,它也起作用,您必须扩展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年后解决此问题,但是,这是一个很好的解决方法,您不会忘记它们。

答案 2 :(得分:0)

在我看来,这仅适用于

    var transformControls = new THREE.TransformControls(camera3d, renderer3d.domElement);
    transformControls.addEventListener('change', renderer3d);
    console.log(object);

    try {
        transformControls.attach(object);
    }
    catch (err) {
        console.log(err); 
    }


    scene3d.add(transformControls);


    transformControls.addEventListener('mouseDown', function () {
        controls3d.enabled = false;
    });
    transformControls.addEventListener('mouseUp', function () {
        controls3d.enabled = true;
    });

RecyclerView仅在我滚动数据时显示数据。因此,代替用户手动滚动,我在上面添加了一行,它将以编程方式滚动recyclerView。

答案 3 :(得分:0)

我也遇到同样的问题2天了,添加此行后就完成了。

adapter.notifyDataSetChanged()// //通知适配器后,添加此一个 mRecyclerView.smoothScrollToPosition(list.size-1)

答案 4 :(得分:0)

就我而言,它仅发生在Android 6上。在此版本之上,我没有任何问题。 因此,我发现可以使用recyclerView.scrollBy(0,0)。 检查它也许也对您有用。

答案 5 :(得分:0)

由于这种情况仍在发生,因此,这里有一个特定的固定实例,以防它帮助某人:

  • 仅当单元格视图包含WebView时发生。

解决方法:

  • 从ViewHolder调用setIsRecyclable(false)

答案 6 :(得分:0)

这有点晚了,但就我而言,我在另一个viewpager内的viewpager(TabView)内有一个recylerview(使用BottomNavigationView),平滑滚动没有任何改变。

但是,我注意到在绘制布局时,我已使用Visibility GONE设置了recylerview,因此解决方案是:

  1. 在xml布局上将recyclerview设置为Visibility VISIBLE(以便在设置TabView时完全绘制);
  2. 设置适配器(链接到可观察到的房间)后,我会这样做:
new Handler(Looper.getMainLooper()).postDelayed(() -> {

     binding.recyclerView.scrollToPosition(0);

}, getResources().getInteger(android.R.integer.config_shortAnimTime));

答案 7 :(得分:-1)

您必须在UI线程上运行onPostExecute中的内容,以便重新绘制RecyclerView。这就是平滑滚动的原因,因为它在UI线程上运行,因此导致视图重绘。

答案 8 :(得分:-2)

这很可能是因为您没有调用RecyclerView.Adapter的正确通知方法。你有一个比以前在ListAdapters中更精细的界面。例如,在addAll()中,您应该调用notifyItemRangeInserted(oldConversationsSize, conversations.size())而不是notifyDataSetChanged