LiveData is not updating its value after first call

前端 未结 4 864
谎友^
谎友^ 2020-12-08 21:34

I have been beating my head against the wall and I cannot understand why this is happening. I am working with the new Architectural Components for Android and I am having pr

4条回答
  •  再見小時候
    2020-12-08 21:42

    Well, I have reached a solution for this issue and found out how this LiveData things works.

    Thanks to @MartinMarconcini for all his help is debugging ;)

    So apparently, the observers are linked to the object you first set it up to. You cannot replace the object (by attribution) or otherwise it will not work. Also, if the value of your variable is going to change then you should use MutableLiveData

    So the change necessary were:

    1. Change from LiveData to MutableLiveData and pass that MutableLiveData to the repository when you need to update it

    public class StatesViewModel extends ViewModel {
    
    private MutableLiveData> states; ;;CHANGED
    private StatesRepository repo;
    
    @Inject
    public StatesViewModel(StatesRepository repository){
        this.repo = repository;
    }
    
    
    public void init(String token){
    
        states = repo.getStates(token);
    }
    
    public void getStatesFromCountry(String countryID){
    
        repo.getStatesFromCountry(this.states, countryID); ;;CHANGED
    }
    
    public LiveData> getStates(){
    
        return this.states;
    }
    }
    

    2. In the repository, update the MutableLiveData using setValue

    @Singleton
    public class StatesRepository {
    
    private final WebServices services;
    private final StateDao stateDao;
    private final Executor executor;
    
    @Inject
    public StatesRepository(Executor executor, StateDao stateDao, WebServices services) {
        this.services = services;
        this.stateDao = stateDao;
        this.executor = executor;
    }
    
    
    public MutableLiveData> getStates(String token){
        refreshStates(token);
    
        final MutableLiveData> data = new MutableLiveData<>();
    
        data.setValue(stateDao.getAllStates());
    
        return data;
    
    }
    
    ;; CHANGED
    public void getStatesFromCountry(MutableLiveData states, final String countryID){
    
        states.setValue(stateDao.getStatesFromCountry(countryID));
    
    }
    
    private void refreshStates(final String token){
    
        executor.execute(() -> {
    
            if(stateDao.getNrStates() == 0){
    
                try {
                    Response> response = services.getStates("Bearer "+token).execute();
    
                    stateDao.insertAll(response.body());
    
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }
    }
    

    3. Changed the DAO to return List instead of LiveData>

    @Dao
    public interface StateDao {
    
    @Query("SELECT * FROM states")
    List getAllStates();
    
    @Query("SELECT * FROM states WHERE ctrId = :countryID")
    List getStatesFromCountry(String countryID);
    
    @Query("SELECT COUNT(*) FROM states")
    int getNrStates();
    
    @Query("SELECT COUNT(*) FROM states WHERE ctrId = :countryID")
    int getNrStatesByCountry(String countryID);
    
    @Insert(onConflict = IGNORE)
    void insertAll(List states);
    
    @Delete
    void delete(State state);
    }
    

    4.Finally allow to perform queries in the main thread

    AppModule.java

    @Singleton @Provides
    AppDatabase provideDb(Application app) {
        return Room.databaseBuilder(app, AppDatabase.class,"unitail.db")
                .allowMainThreadQueries()
                .fallbackToDestructiveMigration()
                .build();
    }
    

提交回复
热议问题