为什么在WordRoomDatabase代码库中插入新词会刷新所有列表



我不明白为什么要刷新整个列表(并跳到顶部(,而不是只刷新新添加的单词。它否定了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将在数据库表中的每个事务之后触发,例如插入一个新词或删除一个。因此,在此之后,将调用ComputableLiveDatainvalidate()方法,从而重新计算整个单词列表。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(

最新更新