5

Tôi đang cố gắng tìm hiểu trong đoạn mã dưới đây, tại sao LiveData của phòng quan sát không cho tôi thay đổi mới khi tôi điền dữ liệu mới vào cơ sở dữ liệu.Room - LiveData Observer không kích hoạt khi cơ sở dữ liệu được cập nhật

này được đưa vào phương pháp onCreate hoạt động của tôi:

shiftsViewModel = ViewModelProviders.of(this).get(ShiftsViewModel.class); 
shiftsViewModel 
      .getShifts() 
      .observe(this, this::populateAdapter); 

Đây là phương pháp populateAdapter:

private void populateAdapter(@NonNull final List<Shift> shifts){ 

    recyclerView.setAdapter(new SimpleItemRecyclerViewAdapter(shifts)); 
} 

Tôi cũng có đoạn mã sau thao tác trên cơ sở dữ liệu (tôi sử dụng RxJava làm làm việc trên một chuỗi IO vì Phòng cần mã của nó để được gọi bên ngoài sợi chính):

@Override 
public Observable<List<Shift>> persistShifts(@NonNull final List<Shift> shifts){ 

    return Observable.fromCallable(() -> { 

     appDatabase.getShiftDao().insertAll(shifts); 
     return shifts; 
    }) 
    .subscribeOn(Schedulers.io()) 
    .observeOn(AndroidSchedulers.mainThread()); 
} 

Vấn đề tôi đã xảy ra khi tôi gọi persistShifts sau khi tôi bắt đầu quan sát shiftsViewModel của tôi. Tôi hy vọng rằng người quan sát của tôi (LiveData) sẽ được kích hoạt với tất cả các ca mới được thêm vào. Hóa ra người quan sát được kích hoạt, nhưng thay vào đó, danh sách thay đổi trống sẽ được trả lại. Cách duy nhất để làm cho nó "làm việc" là nếu tôi rời khỏi hoạt động (do đó phá hủy ViewModel hiện tại) và nhập lại. Lần này, LiveData của viewModel mang lại cho tôi tất cả các thay đổi trước đây vẫn tồn tại, như mong đợi.

Dưới đây là phần còn lại của các mã:

@Entity 
public class Shift{ 

    @PrimaryKey 
    private long id; 

    private String start; 
    private String end; 
    private String startLatitude; 
    private String startLongitude; 
    private String endLatitude; 
    private String endLongitude; 
    private String image; 
    ... 

DAO:

@Dao 
public interface ShiftDAO { 

    @Query("SELECT * FROM shift") 
    LiveData<List<Shift>> getAll(); 

    @Query("SELECT * FROM shift WHERE id = :id") 
    LiveData<Shift> getShiftById(long id); 

    @Insert(onConflict = OnConflictStrategy.REPLACE) 
    void insertAll(List<Shift> shifts); 
} 

ViewModel:

public class ShiftsViewModel extends AndroidViewModel{ 

    private final ISQLDatabase sqlDatabase; 

    private MutableLiveData<Shift> currentShift; 
    private LiveData<List<Shift>> shifts; 
    private boolean firstTimeCreated; 


    public ShiftsViewModel(final Application application){ 

     super(application); 

     this.sqlDatabase = ((ThisApplication) application).getSQLDatabase(); 
     this.firstTimeCreated = true; 
    } 

    public MutableLiveData<Shift> getCurrentlySelectedShift(){ 

     if(currentShift == null){ 
     currentShift = new MutableLiveData<>(); 
     } 

     return currentShift; 
    } 

    public LiveData<List<Shift>> getShifts() { 

     if(shifts == null){ 
     shifts = sqlDatabase.queryAllShifts(); 
     } 

    return shifts; 
    } 

    public void setCurrentlySelectedShift(final Shift shift){ 

     currentShift = getCurrentlySelectedShift(); 

     currentShift.setValue(shift); 
    } 

    public boolean isFirstTimeCreated(){ 
     return firstTimeCreated; 
    } 

    public void alreadyUsed(){ 
     firstTimeCreated = false; 
    } 
} 

Tại sao tôi không nhận được danh sách các thay đổi tôi vẫn tồn tại trong quan sát() gọi lại ngay lập tức?

+0

Bạn có thể hiển thị mã ViewModel của mình và địa điểm/cách bạn gọi getAll() không? – Lyla

+0

Bất kỳ nội dung nào được cung cấp đều tốt, nhưng như được yêu cầu ở trên, hãy đăng ViewModel –

+0

@Lyla ViewMã mã được thêm theo yêu cầu. – Tiago

Trả lời

20

Tôi đã gặp sự cố tương tự khi sử dụng Dagger 2 do có các phiên bản Dao khác nhau, một cho việc cập nhật/chèn dữ liệu và một cá thể khác cung cấp LiveData để quan sát. Một khi tôi cấu hình Dagger để quản lý một trường hợp Singleton, sau đó tôi có thể chèn dữ liệu trong nền (trong trường hợp của tôi trong một Service) trong khi quan sát LiveData trong Activity của tôi - và gọi lại onChange() sẽ được gọi.

Nó xảy ra với trường hợp của người Dao phải là cùng một trường hợp đang chèn/cập nhật dữ liệu và cung cấp LiveData để quan sát.

+0

Có, để nhận các cập nhật trực tiếp, bạn phải đảm bảo rằng phiên bản 'Dao' phải giống nhau trên tất cả các thao tác. –

+0

Tôi phát sinh trong cùng một vấn đề và nhờ anwser của bạn tôi phát hiện ra tôi đã quên '@ Singleton' trên phương pháp cung cấp' RoomDatabase' của tôi. Tôi muốn thêm rằng trong trường hợp của tôi, tôi có 2 khác nhau 'Dao' truy vấn cùng một bảng, trong đó một là liên quan đến một thực thể cổ điển và một đến một lớp wrapper với 2 thực thể nhúng, để tái tạo một truy vấn tham gia. Mặc dù các đối tượng khác nhau, nhưng 'LiveData' được cập nhật một cách chính xác, vì vậy nó có thể là 'RoomDatabase' phải là singleton. – devrocca

+0

Miếng bánh. –

Các vấn đề liên quan