LiveData
についての私の理解は、データの一連の履歴状態変化ではなく、データの現在の状態変化でオブザーバーをトリガーするということです。
現在、MainFragment
書き込み操作を実行するRoom
を使用して、non-trashed dataをtrashed dataに変更しています。
trashed dataを監視する別のTrashFragment
も使用します。
次のシナリオを検討してください。
MainFragment
は現在アクティブなフラグメントです。 TrashFragment
はまだ作成されていません。MainFragment
が追加されました1 ゴミ箱に入れられたデータ。MainFragment
をTrashFragment
に置き換えます。TrashFragment
のオブザーバーは最初にonChanged
を0とともに受け取りますゴミ箱に入れられたデータTrashFragment
のオブザーバーは、2番目にonChanged
を受け取り、1 trashed data私の期待から外れているのは、項目(6)が起こらないことです。 TrashFragment
は最新のtrashed dataのみを受信する必要があります。これは1です。
これが私のコードです
public class TrashFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
noteViewModel = ViewModelProviders.of(getActivity()).get(NoteViewModel.class);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
...
noteViewModel.getTrashedNotesLiveData().removeObservers(this);
noteViewModel.getTrashedNotesLiveData().observe(this, notesObserver);
public class MainFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
noteViewModel = ViewModelProviders.of(getActivity()).get(NoteViewModel.class);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
...
noteViewModel.getNotesLiveData().removeObservers(this);
noteViewModel.getNotesLiveData().observe(this, notesObserver);
public class NoteViewModel extends ViewModel {
private final LiveData<List<Note>> notesLiveData;
private final LiveData<List<Note>> trashedNotesLiveData;
public LiveData<List<Note>> getNotesLiveData() {
return notesLiveData;
}
public LiveData<List<Note>> getTrashedNotesLiveData() {
return trashedNotesLiveData;
}
public NoteViewModel() {
notesLiveData = NoteplusRoomDatabase.instance().noteDao().getNotes();
trashedNotesLiveData = NoteplusRoomDatabase.instance().noteDao().getTrashedNotes();
}
}
public enum NoteRepository {
INSTANCE;
public LiveData<List<Note>> getTrashedNotes() {
NoteDao noteDao = NoteplusRoomDatabase.instance().noteDao();
return noteDao.getTrashedNotes();
}
public LiveData<List<Note>> getNotes() {
NoteDao noteDao = NoteplusRoomDatabase.instance().noteDao();
return noteDao.getNotes();
}
}
@Dao
public abstract class NoteDao {
@Transaction
@Query("SELECT * FROM note where trashed = 0")
public abstract LiveData<List<Note>> getNotes();
@Transaction
@Query("SELECT * FROM note where trashed = 1")
public abstract LiveData<List<Note>> getTrashedNotes();
@Insert(onConflict = OnConflictStrategy.REPLACE)
public abstract long insert(Note note);
}
@Database(
entities = {Note.class},
version = 1
)
public abstract class NoteplusRoomDatabase extends RoomDatabase {
private volatile static NoteplusRoomDatabase INSTANCE;
private static final String NAME = "noteplus";
public abstract NoteDao noteDao();
public static NoteplusRoomDatabase instance() {
if (INSTANCE == null) {
synchronized (NoteplusRoomDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(
NoteplusApplication.instance(),
NoteplusRoomDatabase.class,
NAME
).build();
}
}
}
return INSTANCE;
}
}
同じデータに対してonChanged
が2回受信されないようにするにはどうすればよいですか?
この問題を示すためにデモプロジェクトを作成しました。
ご覧のとおり、MainFragment
で書き込み操作([ADD TRASHED NOTEボタンをクリック)]を実行した後、TrashFragment
に切り替えると、onChanged
のTrashFragment
が1回だけ呼び出されることを期待しています。ただし、2回呼び出されています。
デモプロジェクトは https://github.com/yccheok/live-data-problem からダウンロードできます。
PopUpでの複数のトリガーを回避するソリューションを探している場合、宛先フラグメントから元のフラグメントへのバックスタック
私の解決策は、フラグメントライフサイクルのonCreate()でLiveDataを観察することですライフサイクルの所有者をActivityとして、フラグメントライフサイクルのonDestroy()でオブザーバーを削除します