首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何保持FirebaseRecyclerAdapter的滚动位置

如何保持FirebaseRecyclerAdapter的滚动位置
EN

Stack Overflow用户
提问于 2017-08-01 04:02:44
回答 2查看 625关注 0票数 5

当我从另一个活动返回到相同的活动时,我正在尝试保持我的FirebaseRecyclerAdapter的滚动位置。

下面是我的函数,它设置FirebaseRecyclerAdapter

public void setTheScreen(){
   FirebaseRecyclerAdapter<Post,PostViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Post,PostViewHolder>(
           Post.class,
           R.layout.post_display_blueprint,
           PostViewHolder.class,
           postsNode
   ) {
       @Override
       public void onDataChanged() {
           if(dialog != null && dialog.isShowing()){
               dialog.dismiss();
           }
       }

       @Override
       protected void populateViewHolder(final PostViewHolder viewHolder, Post model, int position) {
           final String key = getRef(position).getKey();
           mRefPosts = FirebaseDatabase.getInstance().getReference().child("posts").child(key);
           mLoveNode = mRef.child("loves");
           mRefLoves = mRef.child("loves").child(key);
           viewHolder.setTitle(model.getTitle());
           viewHolder.setLoves(mRefLoves);
           viewHolder.setLoveButton(Uid,key);
           viewHolder.setImage(getApplicationContext(),model.getImageUrl());


           mRefPosts.addValueEventListener(new ValueEventListener() {
               @Override
               public void onDataChange(DataSnapshot dataSnapshot) {

                   String isAnonymous = dataSnapshot.child("anonymous").getValue(String.class);
                   if (isAnonymous != null && isAnonymous.equals("true")) {
                       viewHolder.anonymousButton.setVisibility(View.VISIBLE);
                   }

               }
               @Override
               public void onCancelled(DatabaseError databaseError) {

               }
           });


            viewHolder.mView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    Intent intent = new Intent(MainActivity.this,PostDisplayPageActivity.class);
                    intent.putExtra("Key",key);
                    startActivity(intent);

                }
            });
       }
   };
   mRecyclerView.setAdapter(firebaseRecyclerAdapter);
    firebaseRecyclerAdapter.notifyDataSetChanged();

}

通过单击适配器创建的任何视图,我将从我的MainActivity转到一个名为PostDisplayPageActivity的新活动,然后按下back键,我将完成PostDisplayPageActivity并返回到MainActivity。

当我回到我的MainActivity时,列表从0位置开始

我在onPause和onResume方法中使用了以下代码,但它不起作用。

 @Override
protected void onPause() {
    super.onPause();

    currentVisiblePosition = ((LinearLayoutManager)mRecyclerView.getLayoutManager()).findFirstCompletelyVisibleItemPosition();
    Toast.makeText(MainActivity.this,String.valueOf(currentVisiblePosition),Toast.LENGTH_SHORT).show();

}

@Override
protected void onResume() {
    super.onResume();

    setTheScreen();
    mRecyclerView.getLayoutManager().scrollToPosition(currentVisiblePosition);
    Toast.makeText(MainActivity.this,String.valueOf(currentVisiblePosition),Toast.LENGTH_SHORT).show();
    currentVisiblePosition = 0;


}

从这两个Toasts中,我得到了正确的位置,但视图总是从位置0开始。

对于我的RecyclerView,我使用LinearLayoutManager作为mRecyclerView.setLayoutManager(mLinearLayoutManager);

请有人告诉我我做错了什么,或者给我一个不同的方法。

EN

回答 2

Stack Overflow用户

发布于 2018-10-23 03:32:48

我用一个更简单的解决方案解决了我的问题。我只是在onViewCreated()而不是onStart中调用了adapter.startListening();,并在onDestroyView()中调用了adapter.stopListening();而不是onStop(),这阻止了从下一个活动返回时重新生成整个列表,从而保留了以前的滚动位置。

票数 2
EN

Stack Overflow用户

发布于 2021-08-03 14:15:08

面对同样的问题,我发现许多建议对我都不起作用。因此,我想出了一个解决方法来解决这个问题,即恢复Firebase RecyclerView状态/滚动位置。

在实现Firebase RecyclerView的Activity/Fragment中保留RecyclerView instanceStateFirebaseRecycler的实例状态字段:

private Parcelable instanceStateFirebaseRecycler;

首先,保存Firebase RecyclerView的实例状态instanceStateFirebaseRecycler,它保留了滚动位置信息onPause()

@Override
public void onPause() {
    saveScrollPosition();
    super.onPause();
}

其中saveScrollPosition()方法很简单:

private void saveScrollPosition(){
    instanceStateFirebaseRecycler = firebaseRecyclerView.getLayoutManager().onSaveInstanceState();
}

接下来是棘手的部分,您需要向Firebase Adapter添加一个侦听器,当适配器就绪时,即getItemCount()不为零时,它会通知您。在监听器的回调中,您可以恢复回收器的状态/滚动位置:

firebaseAdapter = new FirebaseAdapter(options, new FirebaseAdapter.OnRestoreRecyclerStateListener() {
        @Override
        public void onRestoreRecyclerState() {
            restoreScrollPosition();
        }
    });
    firebaseRecyclerView.setAdapter(firebaseAdapter);

其中自定义interface只是:

public interface OnRestoreRecyclerStateListener {
    void onRestoreRecyclerState();
}

并且在Firebase Adapter onBindViewHolder (我没有找到更好的地方)中触发callback,以确保适配器项准备就绪:

@Override
protected void onBindViewHolder(@NonNull ViewHolder holder, int position, @NonNull MyModel model) {
    ...
    onRestoreRecyclerStateListener.onRestoreRecyclerState();
}

,以及restoreScrollPosition()方法的位置:

private void restoreScrollPosition(){
    if (instanceStateFirebaseRecycler == null) return;
    firebaseRecyclerView.getRootView().setVisibility(View.GONE);
    final Handler handler = new Handler(Looper.getMainLooper());
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            if (instanceStateFirebaseRecycler == null) return;
            firebaseRecyclerView.getLayoutManager().onRestoreInstanceState(instanceStateFirebaseRecycler);
            instanceStateFirebaseRecycler = null;
            firebaseRecyclerView.getRootView().setVisibility(View.VISIBLE);
        }
    }, 100);
}

restoreScrollPosition()方法中,我检查instanceStateFirebaseRecycler == null以避免不必要的运行。此外,我通过Handler延迟了实例状态恢复,因为items还没有绘制,很快就会绘制。如果没有延迟地调用onRestoreInstanceState,则状态将不会恢复到预期状态。此外,我通过setVisibility()切换了RecyclerView的可见性,以隐藏用户可能会认为是小故障的难看的项目重载和快速滚动。

顺便说一下,@Sanju建议的解决方案在流量和电池效率方面看起来有点危险,因为用户可以将正在运行的应用程序放在后台很长一段时间,而监听器在这段时间内一直处于活动状态。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45424383

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档