当我从另一个活动返回相同的活动时,我正在努力保持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 的新活动,然后按下我正在完成 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);
有人请告诉我我做错了什么或建议我采取不同的方式来做这件事。
答案 0 :(得分:1)
我用一个更简单的解决方案解决了我的问题。我只是叫adapter.startListening();在onViewCreated()而不是onStart中,并称为adapter.stopListening();。在onDestroyView()中而不是onStop()中 这阻止了整个列表在下一次活动返回时重新生成,因此将滚动位置保留在以前的位置。
答案 1 :(得分:0)
遇到同样的问题,我发现了许多对我不起作用的建议。因此,我想出了一个解决方法来解决恢复 Firebase RecyclerView
状态/滚动位置的问题。
在实现 instanceStateFirebaseRecycler
的 Activity/Fragment 中保留 RecyclerView Firebase RecyclerView
的实例状态字段:
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();
}
并且在 callback
Firebase Adapter
中触发 onBindViewHolder
(我没有找到更好的地方)以确保适配器项目准备就绪:
@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
,状态将不会按预期恢复。此外,我通过 RecyclerView
切换 setVisibility()
的可见性以隐藏丑陋的项目重新加载和快速滚动,用户可以将其解释为故障。
顺便说一下,@Sanju 建议的解决方案在流量和电池效率方面看起来有点危险,因为用户可以将正在运行的应用程序长时间置于后台,而监听器一直处于活动状态。