滚动提要时 RecyclerView 跳转到顶部
RecyclerView Jumps to Top when scrolling through feed
我正在开发西班牙语新闻应用程序,请参阅此处:
应用程序的问题是,每当任何用户点击喜欢、播放音频或翻译按钮时,recyclerView 都会跳到顶部。
数据是从 Firebase 实时数据库中提取的片段。请帮忙
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup 容器,
捆绑 savedInstanceState) {
// 膨胀这个片段的布局
mView = inflater.inflate(R.layout.fragment_feed, 容器, false);
MobileAds.initialize(mView.getContext(), "XXXXXXXXX");
mRewardedVideoAd = MobileAds.getRewardedVideoAdInstance(mView.getContext());
mRewardedVideoAd.setRewardedVideoAdListener(this);
loadRewardedVideoAd();
mAuth = FirebaseAuth.getInstance();
feedRecycler = mView.findViewById(R.id.recycler_feed);
feedRecycler.setLayoutManager(new LinearLayoutManager(getContext()));
RecyclerView.Adapter adapter = new FeedAdapter(mView.getContext(),mRecyclerViewItems);
feedRecycler.setAdapter(adapter);
userImage = mView.findViewById(R.id.feed_img);
username = mView.findViewById(R.id.feed_name);
usercomment = mView.findViewById(R.id.feed_edittext);
subMitComment = mView.findViewById(R.id.feed_submit);
mUSerCmt = FirebaseDatabase.getInstance().getReference().child("feeds");
mScoreRef = FirebaseDatabase.getInstance().getReference().child("scores");
if(mAuth.getCurrentUser().getPhotoUrl()!= null) {
Picasso.get().load(mAuth.getCurrentUser().getPhotoUrl().toString()).into(userImage);
username.setText(mAuth.getCurrentUser().getDisplayName());
} else {
startActivity(new Intent(mView.getContext(),UserProfile.class));
}
subMitComment.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String usercmt = usercomment.getText().toString();
if(!usercmt.equals("")){
writeNewPost(usercmt,mAuth.getUid(),mAuth.getCurrentUser().getDisplayName(),mAuth.getCurrentUser().getPhotoUrl().toString());
Toast.makeText(mView.getContext(),"Comment updated!",Toast.LENGTH_SHORT).show();
}
usercomment.setText("");
}
});
mUSerCmt.orderByChild("timestamp").addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
mRecyclerViewItems.clear();
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
Model_Feed epiModel = dataSnapshot1.getValue(Model_Feed.class);
mRecyclerViewItems.add(epiModel);
}
FeedAdapter = new FeedAdapter(mView.getContext(), mRecyclerViewItems);
feedRecycler.setAdapter(FeedAdapter);
FeedAdapter.notifyDataSetChanged();
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
return mView;
}
private void writeNewPost(String sen, String uid, String name, String img) {
// Create new post at /user-posts/$userid/$postid and at
// /posts/$postid simultaneously
String key = mUSerCmt.push().getKey();
long time = System.currentTimeMillis() * (-1);
Model_Feed post = new Model_Feed(sen,time,uid, name, img,key);
Map<String, Object> postValues = post.toMap();
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put(key, postValues);
mUSerCmt.updateChildren(childUpdates);
}
public class FeedAdapter extends RecyclerView.Adapter<FeedAdapter.FeedViewHolder>{
private Context context;
private List<Object> mRecyclerViewItems;
public FeedAdapter(Context context, List<Object> mRecyclerViewItems) {
this.context = context;
this.mRecyclerViewItems = mRecyclerViewItems;
}
@NonNull
@Override
public FeedViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.rec_words,viewGroup,false);
return new FeedViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final FeedViewHolder feedViewHolder, int i) {
final Model_Feed modelFeed = (Model_Feed) mRecyclerViewItems.get(i);
Picasso.get().load(modelFeed.getImg()).into(feedViewHolder.circleImageView);
feedViewHolder.nameWord.setText(modelFeed.getName());
feedViewHolder.statusword.setText(modelFeed.getSen());
feedViewHolder.fireword.setText(String.valueOf(modelFeed.fires.size()));
feedViewHolder.playword.setText(String.valueOf(modelFeed.plays.size()));
if(modelFeed.fires.containsKey(mAuth.getUid())){
feedViewHolder.fireimage.setImageDrawable(getResources().getDrawable(R.drawable.fire));
}
if(modelFeed.plays.containsKey(mAuth.getUid())){
feedViewHolder.playimage.setImageDrawable(getResources().getDrawable(R.drawable.play_button));
}
feedViewHolder.fireLinear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
feedViewHolder.fireimage.setImageDrawable(getResources().getDrawable(R.drawable.fire));
onFireClicked(mUSerCmt.child(modelFeed.getKey()),modelFeed.getUid());
}
});
feedViewHolder.playLinear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
feedViewHolder.playimage.setImageDrawable(getResources().getDrawable(R.drawable.play_button));
sen_sound = modelFeed.getSen();
mScoreRef.child(mAuth.getUid()).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
final Model_Score modelScore = dataSnapshot.getValue(Model_Score.class);
long scoreCheck = modelScore.getScore();
if (scoreCheck < 1 ){
AlertDialog.Builder builder;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder = new AlertDialog.Builder(context, android.R.style.Theme_Material_Dialog_Alert);
} else {
builder = new AlertDialog.Builder(context);
}
builder.setTitle("Insufficient Coins")
.setMessage("You've insufficient coins in your wallet to listen this audio, Watch a reward video complete and get 50 coins.")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
long score = modelScore.getScore() + 5;
Model_Score modelScore1 = new Model_Score(score, modelScore.getReput(), mAuth.getUid());
mScoreRef.child(mAuth.getUid()).setValue(modelScore1);
}
scorez = modelScore.getScore();
reputz = modelScore.getReput();
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(mView.getContext(),"Our Apologies for inconvenience",Toast.LENGTH_SHORT).show();
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}else {
long score = modelScore.getScore() - 10;
Model_Score modelScore1 = new Model_Score(score, modelScore.getReput(), mAuth.getUid());
mScoreRef.child(mAuth.getUid()).setValue(modelScore1);
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
});
}
@Override
public int getItemCount() {
return mRecyclerViewItems.size();
}
public class FeedViewHolder extends RecyclerView.ViewHolder{
CircleImageView circleImageView;
TextView nameWord, statusword,fireword,playword;
LinearLayout fireLinear, playLinear;
ImageView fireimage, playimage;
public FeedViewHolder(@NonNull View itemView) {
super(itemView);
circleImageView = itemView.findViewById(R.id.word_image);
nameWord = itemView.findViewById(R.id.word_name);
statusword = itemView.findViewById(R.id.word_status);
fireword = itemView.findViewById(R.id.word_text_fire);
playword = itemView.findViewById(R.id.word_text_play);
fireLinear = itemView.findViewById(R.id.word_fire_linear);
playLinear = itemView.findViewById(R.id.word_play_linear);
fireimage = itemView.findViewById(R.id.word_img_fire);
playimage = itemView.findViewById(R.id.word_img_play);
}
}
}
void sendReward(long scores, long reputs){
long score = scores + 50;
Model_Score modelScore1 = new Model_Score(score, reputs, mAuth.getUid());
mScoreRef.child(mAuth.getUid()).setValue(modelScore1);
}
void showToast(String msg){
Toast.makeText(mView.getContext(),msg,Toast.LENGTH_SHORT).show();
}
private void onFireClicked(DatabaseReference postRef, final String cr_uid) {
postRef.runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData mutableData) {
Model_Feed p = mutableData.getValue(Model_Feed.class);
if (p == null) {
return Transaction.success(mutableData);
}
if (p.fires.containsKey(mAuth.getUid())) {
// Unstar the post and remove self from stars
p.firecount = p.firecount - 1;
p.fires.remove(mAuth.getUid());
} else {
// Star the post and add self to stars
p.firecount = p.firecount + 1;
p.fires.put(mAuth.getUid(), true);
mScoreRef.child(cr_uid).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
Model_Score modelScore = dataSnapshot.getValue(Model_Score.class);
long reput = modelScore.getReput();
Model_Score modelScore1 = new Model_Score(modelScore.getScore(), reput + 10, cr_uid);
mScoreRef.child(cr_uid).setValue(modelScore1);
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
// Set value and report transaction success
mutableData.setValue(p);
return Transaction.success(mutableData);
}
@Override
public void onComplete(DatabaseError databaseError, boolean b,
DataSnapshot dataSnapshot) {
// Transaction completed
//Log.d(TAG, "postTransaction:onComplete:" + databaseError);
}
});
}
private void onPlayClicked(DatabaseReference postRef) {
postRef.runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData mutableData) {
Model_Feed p = mutableData.getValue(Model_Feed.class);
if (p == null) {
return Transaction.success(mutableData);
}
if (p.plays.containsKey(mAuth.getUid())) {
// Unstar the post and remove self from stars
p.playcount = p.playcount + 1;
p.plays.put(mAuth.getUid() + p.playcount,true);
new readSen().execute();
} else {
// Star the post and add self to stars
p.playcount = p.playcount + 1;
p.plays.put(mAuth.getUid(), true);
}
// Set value and report transaction success
mutableData.setValue(p);
return Transaction.success(mutableData);
}
@Override
public void onComplete(DatabaseError databaseError, boolean b,
DataSnapshot dataSnapshot) {
// Transaction completed
//Log.d(TAG, "postTransaction:onComplete:" + databaseError);
}
});
}
可能的原因是因为更新帖子会触发 ValueEventListener
中的回调,用于填充此行中的 RecyclerView
mUSerCmt.orderByChild("timestamp").addValueEventListener( ... )
由于视图被完全清除并重新加载,它自然看起来好像已滚动到顶部。可以有多种方法来避免这种情况,具体的选择将取决于您的应用程序的更新需求。我能想到的一些是:
最好的选择是使用 DiffUtil 在不清除整个列表的情况下进行就地更新(使用动画),尽管在编码方面有点棘手。您应该能够找到许多关于如何在线使用 class 的简单教程。
使用addListenerForSingleValueEvent
以便对子项的更新不会触发列表的清除。这可能是一个糟糕的选择,因为您的应用显示的新闻可能经常更改。但是,如果用户经常切换屏幕(例如阅读新闻文章),那么刷新将发生足够多次,并且不会那么引人注目。获取文章时的分页也将确保最新的批次是最新的,而旧的可能有未同步的更改。
第一个选项是我推荐的选项,但第二个选项更易于编码,可用于解决问题,同时获得一些时间来正确实施 DiffUtil。
每当您设置新适配器时,RecyclerView
都会移除并分离旧适配器。相反,您可以尝试只更新当前适配器上的数据,一个简单的方法是在您的适配器上创建一个 public 方法来重新分配数据:
public class FeedAdapter extends RecyclerView.Adapter<FeedAdapter.FeedViewHolder> {
// ...
public void setItems(List<Object> items) {
mRecyclerViewItems = items;
}
// ...
}
然后在 onDataChange
回调中更新您的适配器:
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
mRecyclerViewItems.clear();
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
Model_Feed epiModel = dataSnapshot1.getValue(Model_Feed.class);
mRecyclerViewItems.add(epiModel);
}
if (FeedAdapter != null) {
FeedAdapter.setItems(mRecyclerViewItems);
FeedAdapter. notifyDataSetChanged();
} else {
FeedAdapter = new FeedAdapter(mView.getContext(), mRecyclerViewItems);
feedRecycler.setAdapter(FeedAdapter);
}
}
我正在开发西班牙语新闻应用程序,请参阅此处:
应用程序的问题是,每当任何用户点击喜欢、播放音频或翻译按钮时,recyclerView 都会跳到顶部。
数据是从 Firebase 实时数据库中提取的片段。请帮忙
@Override public View onCreateView(LayoutInflater inflater, ViewGroup 容器, 捆绑 savedInstanceState) { // 膨胀这个片段的布局 mView = inflater.inflate(R.layout.fragment_feed, 容器, false);
MobileAds.initialize(mView.getContext(), "XXXXXXXXX"); mRewardedVideoAd = MobileAds.getRewardedVideoAdInstance(mView.getContext()); mRewardedVideoAd.setRewardedVideoAdListener(this); loadRewardedVideoAd(); mAuth = FirebaseAuth.getInstance(); feedRecycler = mView.findViewById(R.id.recycler_feed); feedRecycler.setLayoutManager(new LinearLayoutManager(getContext())); RecyclerView.Adapter adapter = new FeedAdapter(mView.getContext(),mRecyclerViewItems); feedRecycler.setAdapter(adapter); userImage = mView.findViewById(R.id.feed_img); username = mView.findViewById(R.id.feed_name); usercomment = mView.findViewById(R.id.feed_edittext); subMitComment = mView.findViewById(R.id.feed_submit); mUSerCmt = FirebaseDatabase.getInstance().getReference().child("feeds"); mScoreRef = FirebaseDatabase.getInstance().getReference().child("scores"); if(mAuth.getCurrentUser().getPhotoUrl()!= null) { Picasso.get().load(mAuth.getCurrentUser().getPhotoUrl().toString()).into(userImage); username.setText(mAuth.getCurrentUser().getDisplayName()); } else { startActivity(new Intent(mView.getContext(),UserProfile.class)); } subMitComment.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String usercmt = usercomment.getText().toString(); if(!usercmt.equals("")){ writeNewPost(usercmt,mAuth.getUid(),mAuth.getCurrentUser().getDisplayName(),mAuth.getCurrentUser().getPhotoUrl().toString()); Toast.makeText(mView.getContext(),"Comment updated!",Toast.LENGTH_SHORT).show(); } usercomment.setText(""); } }); mUSerCmt.orderByChild("timestamp").addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot dataSnapshot) { mRecyclerViewItems.clear(); for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) { Model_Feed epiModel = dataSnapshot1.getValue(Model_Feed.class); mRecyclerViewItems.add(epiModel); } FeedAdapter = new FeedAdapter(mView.getContext(), mRecyclerViewItems); feedRecycler.setAdapter(FeedAdapter); FeedAdapter.notifyDataSetChanged(); } @Override public void onCancelled(@NonNull DatabaseError databaseError) { } }); return mView; } private void writeNewPost(String sen, String uid, String name, String img) { // Create new post at /user-posts/$userid/$postid and at // /posts/$postid simultaneously String key = mUSerCmt.push().getKey(); long time = System.currentTimeMillis() * (-1); Model_Feed post = new Model_Feed(sen,time,uid, name, img,key); Map<String, Object> postValues = post.toMap(); Map<String, Object> childUpdates = new HashMap<>(); childUpdates.put(key, postValues); mUSerCmt.updateChildren(childUpdates); } public class FeedAdapter extends RecyclerView.Adapter<FeedAdapter.FeedViewHolder>{ private Context context; private List<Object> mRecyclerViewItems; public FeedAdapter(Context context, List<Object> mRecyclerViewItems) { this.context = context; this.mRecyclerViewItems = mRecyclerViewItems; } @NonNull @Override public FeedViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { LayoutInflater inflater = LayoutInflater.from(context); View view = inflater.inflate(R.layout.rec_words,viewGroup,false); return new FeedViewHolder(view); } @Override public void onBindViewHolder(@NonNull final FeedViewHolder feedViewHolder, int i) { final Model_Feed modelFeed = (Model_Feed) mRecyclerViewItems.get(i); Picasso.get().load(modelFeed.getImg()).into(feedViewHolder.circleImageView); feedViewHolder.nameWord.setText(modelFeed.getName()); feedViewHolder.statusword.setText(modelFeed.getSen()); feedViewHolder.fireword.setText(String.valueOf(modelFeed.fires.size())); feedViewHolder.playword.setText(String.valueOf(modelFeed.plays.size())); if(modelFeed.fires.containsKey(mAuth.getUid())){ feedViewHolder.fireimage.setImageDrawable(getResources().getDrawable(R.drawable.fire)); } if(modelFeed.plays.containsKey(mAuth.getUid())){ feedViewHolder.playimage.setImageDrawable(getResources().getDrawable(R.drawable.play_button)); } feedViewHolder.fireLinear.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { feedViewHolder.fireimage.setImageDrawable(getResources().getDrawable(R.drawable.fire)); onFireClicked(mUSerCmt.child(modelFeed.getKey()),modelFeed.getUid()); } }); feedViewHolder.playLinear.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { feedViewHolder.playimage.setImageDrawable(getResources().getDrawable(R.drawable.play_button)); sen_sound = modelFeed.getSen(); mScoreRef.child(mAuth.getUid()).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot dataSnapshot) { final Model_Score modelScore = dataSnapshot.getValue(Model_Score.class); long scoreCheck = modelScore.getScore(); if (scoreCheck < 1 ){ AlertDialog.Builder builder; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { builder = new AlertDialog.Builder(context, android.R.style.Theme_Material_Dialog_Alert); } else { builder = new AlertDialog.Builder(context); } builder.setTitle("Insufficient Coins") .setMessage("You've insufficient coins in your wallet to listen this audio, Watch a reward video complete and get 50 coins.") .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { long score = modelScore.getScore() + 5; Model_Score modelScore1 = new Model_Score(score, modelScore.getReput(), mAuth.getUid()); mScoreRef.child(mAuth.getUid()).setValue(modelScore1); } scorez = modelScore.getScore(); reputz = modelScore.getReput(); }) .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Toast.makeText(mView.getContext(),"Our Apologies for inconvenience",Toast.LENGTH_SHORT).show(); } }) .setIcon(android.R.drawable.ic_dialog_alert) .show(); }else { long score = modelScore.getScore() - 10; Model_Score modelScore1 = new Model_Score(score, modelScore.getReput(), mAuth.getUid()); mScoreRef.child(mAuth.getUid()).setValue(modelScore1); } } @Override public void onCancelled(@NonNull DatabaseError databaseError) { } }); } }); } @Override public int getItemCount() { return mRecyclerViewItems.size(); } public class FeedViewHolder extends RecyclerView.ViewHolder{ CircleImageView circleImageView; TextView nameWord, statusword,fireword,playword; LinearLayout fireLinear, playLinear; ImageView fireimage, playimage; public FeedViewHolder(@NonNull View itemView) { super(itemView); circleImageView = itemView.findViewById(R.id.word_image); nameWord = itemView.findViewById(R.id.word_name); statusword = itemView.findViewById(R.id.word_status); fireword = itemView.findViewById(R.id.word_text_fire); playword = itemView.findViewById(R.id.word_text_play); fireLinear = itemView.findViewById(R.id.word_fire_linear); playLinear = itemView.findViewById(R.id.word_play_linear); fireimage = itemView.findViewById(R.id.word_img_fire); playimage = itemView.findViewById(R.id.word_img_play); } } } void sendReward(long scores, long reputs){ long score = scores + 50; Model_Score modelScore1 = new Model_Score(score, reputs, mAuth.getUid()); mScoreRef.child(mAuth.getUid()).setValue(modelScore1); } void showToast(String msg){ Toast.makeText(mView.getContext(),msg,Toast.LENGTH_SHORT).show(); } private void onFireClicked(DatabaseReference postRef, final String cr_uid) { postRef.runTransaction(new Transaction.Handler() { @Override public Transaction.Result doTransaction(MutableData mutableData) { Model_Feed p = mutableData.getValue(Model_Feed.class); if (p == null) { return Transaction.success(mutableData); } if (p.fires.containsKey(mAuth.getUid())) { // Unstar the post and remove self from stars p.firecount = p.firecount - 1; p.fires.remove(mAuth.getUid()); } else { // Star the post and add self to stars p.firecount = p.firecount + 1; p.fires.put(mAuth.getUid(), true); mScoreRef.child(cr_uid).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot dataSnapshot) { Model_Score modelScore = dataSnapshot.getValue(Model_Score.class); long reput = modelScore.getReput(); Model_Score modelScore1 = new Model_Score(modelScore.getScore(), reput + 10, cr_uid); mScoreRef.child(cr_uid).setValue(modelScore1); } @Override public void onCancelled(@NonNull DatabaseError databaseError) { } }); } // Set value and report transaction success mutableData.setValue(p); return Transaction.success(mutableData); } @Override public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) { // Transaction completed //Log.d(TAG, "postTransaction:onComplete:" + databaseError); } }); } private void onPlayClicked(DatabaseReference postRef) { postRef.runTransaction(new Transaction.Handler() { @Override public Transaction.Result doTransaction(MutableData mutableData) { Model_Feed p = mutableData.getValue(Model_Feed.class); if (p == null) { return Transaction.success(mutableData); } if (p.plays.containsKey(mAuth.getUid())) { // Unstar the post and remove self from stars p.playcount = p.playcount + 1; p.plays.put(mAuth.getUid() + p.playcount,true); new readSen().execute(); } else { // Star the post and add self to stars p.playcount = p.playcount + 1; p.plays.put(mAuth.getUid(), true); } // Set value and report transaction success mutableData.setValue(p); return Transaction.success(mutableData); } @Override public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) { // Transaction completed //Log.d(TAG, "postTransaction:onComplete:" + databaseError); } }); }
可能的原因是因为更新帖子会触发 ValueEventListener
中的回调,用于填充此行中的 RecyclerView
mUSerCmt.orderByChild("timestamp").addValueEventListener( ... )
由于视图被完全清除并重新加载,它自然看起来好像已滚动到顶部。可以有多种方法来避免这种情况,具体的选择将取决于您的应用程序的更新需求。我能想到的一些是:
最好的选择是使用 DiffUtil 在不清除整个列表的情况下进行就地更新(使用动画),尽管在编码方面有点棘手。您应该能够找到许多关于如何在线使用 class 的简单教程。
使用
addListenerForSingleValueEvent
以便对子项的更新不会触发列表的清除。这可能是一个糟糕的选择,因为您的应用显示的新闻可能经常更改。但是,如果用户经常切换屏幕(例如阅读新闻文章),那么刷新将发生足够多次,并且不会那么引人注目。获取文章时的分页也将确保最新的批次是最新的,而旧的可能有未同步的更改。
第一个选项是我推荐的选项,但第二个选项更易于编码,可用于解决问题,同时获得一些时间来正确实施 DiffUtil。
每当您设置新适配器时,RecyclerView
都会移除并分离旧适配器。相反,您可以尝试只更新当前适配器上的数据,一个简单的方法是在您的适配器上创建一个 public 方法来重新分配数据:
public class FeedAdapter extends RecyclerView.Adapter<FeedAdapter.FeedViewHolder> {
// ...
public void setItems(List<Object> items) {
mRecyclerViewItems = items;
}
// ...
}
然后在 onDataChange
回调中更新您的适配器:
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
mRecyclerViewItems.clear();
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
Model_Feed epiModel = dataSnapshot1.getValue(Model_Feed.class);
mRecyclerViewItems.add(epiModel);
}
if (FeedAdapter != null) {
FeedAdapter.setItems(mRecyclerViewItems);
FeedAdapter. notifyDataSetChanged();
} else {
FeedAdapter = new FeedAdapter(mView.getContext(), mRecyclerViewItems);
feedRecycler.setAdapter(FeedAdapter);
}
}