30

LiveData の値が明らかに変更されていなくても、DB で行が更新されるたびに、Dao によって返される LiveData がそのオブザーバーを呼び出すことがわかりました。

次の例のような状況を考えてみましょう:

エンティティの例

@Entity
public class User {
    public long id;
    public String name;
    // example for other variables
    public Date lastActiveDateTime;
}

例のダオ

@Dao
public interface UserDao {
    // I am only interested in the user name
    @Query("SELECT name From User")
    LiveData<List<String>> getAllNamesOfUser();

    @Update(onConflict = OnConflictStrategy.REPLACE)
    void updateUser(User user);
}

バックグラウンドスレッドのどこかに

UserDao userDao = //.... getting the dao
User user = // obtain from dao....
user.lastActiveDateTime = new Date(); // no change to user.name
userDao.updateUser(user);

UIのどこかに

// omitted ViewModel for simplicity
userDao.getAllNamesOfUser().observe(this, new Observer<List<String>> {
    @Override
    public void onChanged(@Nullable List<String> userNames) {
        // this will be called whenever the background thread called updateUser. 
        // If user.name is not changed, it will be called with userNames 
        // with the same value again and again when lastActiveDateTime changed.
    }
});

この例では、UI はユーザー名のみに関心があるため、LiveData のクエリには名前フィールドのみが含まれます。ただし、他のフィールドのみが更新されたとしても、observer.onChanged は Dao Update で呼び出されます。(実際、User エンティティに変更を加えずに UserDao.updateUser を呼び出しても、observer.onChanged は引き続き呼び出されます)

これは Room の Dao LiveData の設計された動作ですか? 選択したフィールドが更新されたときにのみオブザーバーが呼び出されるように、これを回避できる可能性はありますか?


編集: 次のクエリを使用して、コメントの KuLdip PaTel が示唆するように lastActiveDateTime 値を更新するように変更しました。ユーザー名の LiveData のオブザーバーは引き続き呼び出されます。

@Query("UPDATE User set lastActiveDateTime = :lastActiveDateTime where id = :id")
void updateLastActiveDateTime(Date lastActiveDateTime, int id);
4

5 に答える 5

17

TransformationsメソッドdistinctUntilChangedには、データが変更された場合にのみ新しいデータを公開するという簡単な解決策があります。

この場合、ソースで変更された場合にのみデータを取得します。

LiveData<YourType> getData(){
    return Transformations.distinctUntilChanged(LiveData<YourType> source));
}

ただし、イベントの場合はこれを使用することをお勧めします: https://stackoverflow.com/a/55212795/9381524

于 2019-03-18T15:30:29.213 に答える
2

現在、Observer.onChanged のトリガーを停止する方法がないため、いくつかの結合を使用しているほとんどのクエリで LiveData は役に立たないと思います。@Pinakin が述べたように MediatorLiveData がありますが、これは単なるフィルターであり、変更のたびにデータが読み込まれます。1 つのクエリに 3 つの左結合があり、それらの結合から 1 つまたは 2 つのフィールドのみが必要であると想像してください。これら 4 つのテーブル (メイン + 3 つの結合テーブル) のレコードが更新されるたびに PagedList を実装すると、クエリが再度呼び出されます。これは、少量のデータを含む一部のテーブルでは問題ありませんが、大きなテーブルの場合はこれが悪いので、間違っている場合は修正してください。

于 2019-02-28T07:20:19.933 に答える