我不明白为什么要刷新整个列表(并跳到顶部(,而不是只刷新新添加的单词。它否定了SubmitList((的目的。
我试图更改存储库以管理本地LiveData<列表<Word>gt;getAllWords没有空间,效果很好。
房间里有什么东西导致LiveData<列表<Word>gt;getAllWords以完全刷新?如果是这样该如何避免,那就太难看了。
单词库
class WordRepository { private WordDao mWordDao; private LiveData<List<Word>> mAllWords; WordRepository(Application application) { WordRoomDatabase db = WordRoomDatabase.getDatabase(application); mWordDao = db.wordDao(); mAllWords = mWordDao.getAlphabetizedWords(); } LiveData<List<Word>> getAllWords() { return mAllWords; } void insert(Word word) { WordRoomDatabase.databaseWriteExecutor.execute(() -> { mWordDao.insert(word); }); } }
WORD VIEWMODEL
public class WordViewModel extends AndroidViewModel { private WordRepository mRepository; private final LiveData<List<Word>> mAllWords; public WordViewModel(Application application) { super(application); mRepository = new WordRepository(application); mAllWords = mRepository.getAllWords(); } LiveData<List<Word>> getAllWords() { return mAllWords; } void insert(Word word) { mRepository.insert(word); } }
WORD DAO
public interface WordDao { @Query("SELECT * FROM word_table ORDER BY word ASC") LiveData<List<Word>> getAlphabetizedWords(); @Insert(onConflict = OnConflictStrategy.IGNORE) void insert(Word word); @Query("DELETE FROM word_table") void deleteAll(); }
字适配器
public class WordListAdapter extends ListAdapter<Word, WordViewHolder> { public WordListAdapter(@NonNull DiffUtil.ItemCallback<Word> diffCallback) { super(diffCallback); } @Override public WordViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return WordViewHolder.create(parent); } @Override public void onBindViewHolder(WordViewHolder holder, int position) { Word current = getItem(position); holder.bind(current.getWord()); } static class WordDiff extends DiffUtil.ItemCallback<Word> { @Override public boolean areItemsTheSame(@NonNull Word oldItem, @NonNull Word newItem) { return oldItem == newItem; } @Override public boolean areContentsTheSame(@NonNull Word oldItem, @NonNull Word newItem) { return oldItem.getWord().equals(newItem.getWord()); } } }
主要活动
public class MainActivity extends AppCompatActivity { public static final int NEW_WORD_ACTIVITY_REQUEST_CODE = 1; private WordViewModel mWordViewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); RecyclerView recyclerView = findViewById(R.id.recyclerview); final WordListAdapter adapter = new WordListAdapter(new WordListAdapter.WordDiff()); recyclerView.setAdapter(adapter); recyclerView.setLayoutManager(new LinearLayoutManager(this)); mWordViewModel = new ViewModelProvider(this).get(WordViewModel.class); mWordViewModel.getAllWords().observe(this, new Observer<List<Word>>() { @Override public void onChanged(List<Word> list) { adapter.submitList(list); } }); FloatingActionButton fab = findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(MainActivity.this, NewWordActivity.class); MainActivity.this.startActivityForResult(intent, NEW_WORD_ACTIVITY_REQUEST_CODE); } }); } public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == NEW_WORD_ACTIVITY_REQUEST_CODE && resultCode == RESULT_OK) { Word word = new Word(data.getStringExtra(NewWordActivity.EXTRA_REPLY)); mWordViewModel.insert(word); } else { Toast.makeText( getApplicationContext(), R.string.empty_not_saved, Toast.LENGTH_LONG).show(); } } }
首先,由房间库代码生成的检查
@Override
public LiveData<List<Word>> getAlphabetizedWords() {
// ...
return new ComputableLiveData<List<Word>>() {
private Observer _observer;
@Override
protected List<Word> compute() {
if (_observer == null) {
_observer = new Observer("word_table") {
@Override
public void onInvalidated(@NonNull Set<String> tables) {
invalidate();
}
};
__db.getInvalidationTracker().addWeakObserver(_observer);
}
final Cursor cursor = __db.query(_statement);
final List<Word> _result = new ArrayList<Word>(cursor.getCount());
while (cursor.moveToNext()) {
final Word item = createNewWordInstanceFromCursorData(cursor);
_result.add(item);
}
// ...
}
}.getLiveData();
}
在第一次执行getAlphabetizedWords()
方法之后,将添加新的表无效观察器。这个Observer
将在数据库表中的每个事务之后触发,例如插入一个新词或删除一个。因此,在此之后,将调用ComputableLiveData
的invalidate()
方法,从而重新计算整个单词列表。CCD_ 5值将被设置为具有CCD_ 7项的新实例的CCD_。
在WordDiff
类中,实现了areItemsTheSame()
方法来检查对象引用。但在这种情况下,我们将获得新的Word
实例,并且此实现将返回false。这将导致列表的完全刷新。在这种情况下,您可能会将实现更改为以下
static class WordDiff extends DiffUtil.ItemCallback<Word> {
@Override
public boolean areItemsTheSame(@NonNull Word oldItem, @NonNull Word newItem) {
return oldItem.getWord().equals(newItem.getWord());
}
// ...
}
在更复杂的情况下,您可能会检查每个元素的唯一数据,例如项id。查看更多信息:https://developer.android.com/reference/androidx/recyclerview/widget/DiffUtil.ItemCallback#areItemsTheSame(T,T(