Ma compréhension de LiveData
est que cela déclenchera l'observateur sur le changement d'état actuel des données, et non sur une série de changements d'état des données d'historique.
Actuellement, j'ai un MainFragment
, qui effectue une opération d'écriture Room
, pour changer les données non supprimées , en données supprimées .
J'ai aussi un autre TrashFragment
, qui observe les données trashed .
Considérez le scénario suivant.
MainFragment
est le fragment actif actuel. TrashFragment
n'est pas encore créé.MainFragment
a ajouté 1 données supprimées .MainFragment
par TrashFragment
.TrashFragment
recevra d'abord onChanged
, avec 0 données trashées TrashFragment
recevra en second lieu onChanged
, avec 1 données trashées Ce qui est hors de mon attente, c'est que le point (6) ne devrait pas se produire. TrashFragment
ne devrait recevoir que les dernières données trashed , qui est 1.
Voici mes codes
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;
}
}
Une idée comment je peux empêcher de recevoir onChanged
deux fois, pour une même donnée?
J'ai créé un projet de démonstration pour illustrer ce problème.
Comme vous pouvez le voir, après avoir effectué une opération d'écriture (cliquez sur le bouton ADD TRASHED NOTE ) dans MainFragment
, lorsque je passe à TrashFragment
, je attendez que onChanged
dans TrashFragment
ne sera appelé qu'une seule fois. Cependant, il est appelé deux fois.
Le projet de démonstration peut être téléchargé à partir de https://github.com/yccheok/live-data-problem
Si vous cherchez une solution pour éviter les déclencheurs multiples sur popUp la pile arrière du fragment de destination au fragment d'origine
Ma solution consiste à observer les données en direct sur onCreate () du cycle de vie du fragment avec le propriétaire du cycle de vie comme activité et de supprimer l'observateur sur onDestroy () du cycle de vie du fragment