Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/234.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 支持RecyclerView&x27;在触摸之前不要显示任何内容_Android_Android Recyclerview - Fatal编程技术网

Android 支持RecyclerView&x27;在触摸之前不要显示任何内容

Android 支持RecyclerView&x27;在触摸之前不要显示任何内容,android,android-recyclerview,Android,Android Recyclerview,我在我的应用程序中使用了支持回收视图,我看到了最奇怪的事情。它不会显示任何项目,直到我触摸滚动。然后,一下子,RecyclerView就出现了。我已经验证了支持适配器的列表是否已填充,并且在发生触摸事件之前,不会调用onCreatViewHolder和onBindViewHolder 下面是我如何设置recyclerview的: @Override public void onViewCreated(View view, @Nullable Bundle savedInstanc

我在我的应用程序中使用了支持回收视图,我看到了最奇怪的事情。它不会显示任何项目,直到我触摸滚动。然后,一下子,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);
     }

这很可能是因为您没有调用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)

    • 这有点晚了,但在我的例子中,我在另一个viewpager(使用BottomNavigationView)中的一个viewpager(选项卡视图)中有一个recylerview,平滑滚动并没有改变任何东西

      但是,我注意到在绘制布局时,我设置了recylerview,但可见性消失了,因此解决方案是:

    • 将recyclerview设置为在xml布局上可见(因此在设置TabView时完全绘制)
    • 设置适配器时(链接到observable with room),我会:

    • 您是否建议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));