質問のために、Github で簡単で実用的な例を用意しました:
サンプル アプリは、okhttp を使用してゲームの上位 30 人のプレーヤーを含む JSON 配列をダウンロードし、それらを SQLite Room に保存します。フラグメントで、対応するオブジェクトを観察しLiveData<List<TopEntity>>
、FastAdapter インスタンスを更新します。
public class TopFragment extends Fragment {
private final ItemAdapter<TopItem> mItemAdapter = new ItemAdapter<>();
private final FastAdapter<TopItem> mFastAdapter = FastAdapter.with(mItemAdapter);
private TopViewModel mViewModel;
private ProgressBar mProgressBar;
private RecyclerView mRecyclerView;
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
mViewModel = ViewModelProviders.of(this).get(TopViewModel.class);
mViewModel.getTops().observe(this, tops -> {
mItemAdapter.clear();
for (TopEntity top: tops) {
TopItem item = new TopItem(top);
mItemAdapter.add(item);
}
});
View v = inflater.inflate(R.layout.top_fragment, container, false);
mProgressBar = v.findViewById(R.id.progressBar);
mRecyclerView = v.findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mRecyclerView.setAdapter(mFastAdapter);
fetchJsonData();
return v;
}
私の問題は、データがダウンロードされるたびに、リサイクラー ビューが 1 回ちらつくことです。
上位 30 位は頻繁に変更されるわけではありませんが、データは同じままです。
Penz 氏による優れたFastAdapterライブラリのサンプル アプリを見ると、ちらつきは見られません。
アップデート:
ちらつきは明らかにメソッドの呼び出しによって引き起こされているというヒントがあり、代わりに DiffUtil クラスを使用する必要があります。mItemAdapter.clear();
onChanged
だから私は新しいクラスを追加しました:
public class DiffCallback extends DiffUtil.Callback {
private final List<TopItem> mOldList;
private final List<TopItem> mNewList;
public DiffCallback(List<TopItem> oldStudentList, List<TopItem> newStudentList) {
this.mOldList = oldStudentList;
this.mNewList = newStudentList;
}
@Override
public int getOldListSize() {
return mOldList.size();
}
@Override
public int getNewListSize() {
return mNewList.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
TopItem oldItem = mOldList.get(oldItemPosition);
TopItem newItem = mNewList.get(newItemPosition);
return oldItem.uid == newItem.uid;
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
TopItem oldItem = mOldList.get(oldItemPosition);
TopItem newItem = mNewList.get(newItemPosition);
return oldItem.elo == newItem.elo &&
oldItem.given.equals(newItem.given) &&
//oldItem.photo != null && oldItem.photo.equals(newItem.photo) &&
oldItem.avg_time != null && oldItem.avg_time.equals(newItem.avg_time) &&
oldItem.avg_score == newItem.avg_score;
}
@Nullable
@Override
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
return super.getChangePayload(oldItemPosition, newItemPosition);
}
}
そして、onChanged
呼び出すだけでなくメソッドで使用しようとしてmItemAdapter.clear()
いますが、 RecyclerView にtops
は要素があっても空のままです:
mViewModel = ViewModelProviders.of(this).get(TopViewModel.class);
mViewModel.getTops().observe(this, tops -> {
List<TopItem> oldList = mItemAdapter.getAdapterItems();
List<TopItem> newList = new ArrayList<>();
for (TopEntity top: tops) {
TopItem item = new TopItem(top);
newList.add(item);
}
DiffCallback diffCallback = new DiffCallback(oldList, newList);
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);
mItemAdapter.getAdapterItems().clear();
mItemAdapter.getAdapterItems().addAll(newList);
diffResult.dispatchUpdatesTo(mFastAdapter);
});
私の問題の短い要約:
私の実際のアプリはいくつかの理由で使用しており、データが HTTPS 経由でダウンロードされて Room で更新されるときの 1 回限りのちらつきをなくすために、 DiffUtilFastAdapter
と「結合」する方法を探しています。