当前位置: 首页 > 知识库问答 >
问题:

如何将普通数据(从房间返回)转换为ViewModel图层上的LiveData

朱鸿畅
2023-03-14

我正在使用带有MVVM模式的干净体系结构,所以房间部分进入数据层,我将观察结果从那里返回到域层,并通过将它们包装在LiveData中在表示层中使用它们。现在的问题是,在插入/删除/更新列表之后,UI中的列表不会立即更新。

演示层中的Viewmodel:

public class WordViewModel extends BaseViewModel<WordNavigator> {

//get all the use cases here
private GetAllWords getAllWords;
private InsertWord insertWord;
private DeleteThisWord deleteThisWord;
private UpdateThisWord updateThisWord;
private GetTheIndexOfTopWord getTheIndexOfTopWord;

//data
public MutableLiveData<List<Word>> allWords;


public WordViewModel(GetAllWords getAllWords, InsertWord insertWord, DeleteThisWord deleteThisWord, UpdateThisWord updateThisWord, GetTheIndexOfTopWord getTheIndexOfTopWord) {
    this.getAllWords = getAllWords;
    this.insertWord = insertWord;
    this.deleteThisWord = deleteThisWord;
    this.updateThisWord = updateThisWord;
    this.getTheIndexOfTopWord = getTheIndexOfTopWord;
}

public void getAllWords() {
    getAllWords.execute(new DisposableObserver<List<Word>>() {
        @Override
        public void onNext(List<Word> words) {
            allWords.setValue(words);
        }

        @Override
        public void onError(Throwable e) {

        }

        @Override
        public void onComplete() {

        }
    }, GetAllWords.Params.getAllWords());
}


public void insertWord(Word word) {
    insertWord.execute(new DisposableObserver<Boolean>() {
        @Override
        public void onNext(Boolean aBoolean) {
            if (aBoolean)
                Log.e("ganesh", "word inserted successfully!!!");
        }

        @Override
        public void onError(Throwable e) {
            e.printStackTrace();
        }

        @Override
        public void onComplete() {

        }
    }, InsertWord.Params.insertWord(word));

}

public void getTheIndexOfTopWord(final String action) {
    getTheIndexOfTopWord.execute(new DisposableObserver<Word>() {
        @Override
        public void onNext(Word word) {
            if (word != null)
                getNavigator().updateTopIndex(word.getWordId(), action);
        }

        @Override
        public void onError(Throwable e) {
            e.printStackTrace();
        }

        @Override
        public void onComplete() {

        }
    }, GetTheIndexOfTopWord.Params.getTheIndexOfTopWord());
}

public void deleteThisWord(int wordId) {
    deleteThisWord.execute(new DisposableObserver<Boolean>() {
        @Override
        public void onNext(Boolean aBoolean) {
            if (aBoolean)
                Log.e("ganesh", "word deleted successfully!!!");
        }

        @Override
        public void onError(Throwable e) {
            e.printStackTrace();
        }

        @Override
        public void onComplete() {

        }
    }, DeleteThisWord.Params.deleteThisWord(wordId));
}

public void updateThisWord(int wordId, String newWord) {
    updateThisWord.execute(new DisposableObserver<Boolean>() {
        @Override
        public void onNext(Boolean aBoolean) {
            if (aBoolean)
                Log.e("ganesh", "word updated successfully!!!");
        }

        @Override
        public void onError(Throwable e) {
            e.printStackTrace();
        }

        @Override
        public void onComplete() {

        }
    }, UpdateThisWord.Params.updateThisWord(wordId, newWord));
}

public MutableLiveData<List<Word>> getWords() {
    if (allWords == null) {
        allWords = new MutableLiveData<>();
    }
    return allWords;
}

@Override
protected void onCleared() {
    super.onCleared();

    if (getAllWords != null)
        getAllWords = null;
    if (deleteThisWord != null)
        deleteThisWord = null;
    if (insertWord != null)
        insertWord = null;
    if (updateThisWord != null)
        updateThisWord = null;
    if (getTheIndexOfTopWord != null)
        getTheIndexOfTopWord = null;

}
}

数据层中的DAO:

@Dao
public interface WordDao {
@Insert
void insertThisWord(Word word);

@Query("delete from word_table")
void deleteAll();

@Query("select * from word_table order by word_id asc")
List<Word> getAllWords();

@Query("delete from word_table where word_id = :wordId")
void deleteThisWord(int wordId);

@Query("update word_table set word = :newWord where word_id = :wordId")
void updateThisWord(int wordId, String newWord);

@Query("select * from word_table order by word_id asc limit 1")
Word getTheIndexOfTopWord();
}

数据层中的存储库:

public class WordRepositoryImpl implements WordRepository {

private ApiInterface apiInterface;
private SharedPreferenceHelper sharedPreferenceHelper;
private Context context;

private WordDao wordDao;
private WordRoomDatabase db;

public WordRepositoryImpl(ApiInterface apiInterface, SharedPreferenceHelper sharedPreferenceHelper, WordRoomDatabase db, Context context) {
    this.apiInterface = apiInterface;
    this.sharedPreferenceHelper = sharedPreferenceHelper;
    this.context = context;
    this.db = db;
    wordDao = db.wordDao();
}


@Override
public Observable<Integer> sum(final int a, final int b) {
    return Observable.fromCallable(new Callable<Integer>() {
        @Override
        public Integer call() throws Exception {
            return (a + b);
        }
    });
}

@Override
public Observable<List<Word>> getAllWords() {
    return Observable.fromCallable(new Callable<List<Word>>() {
        @Override
        public List<Word> call() throws Exception {
            List<Word> list = new ArrayList<>();
            List<com.example.data.models.Word> listWords = db.wordDao().getAllWords();
            for (com.example.data.models.Word item : listWords) {
                list.add(new Word(item.getWordId(), item.getWord(), item.getWordLength()));
            }
            return list;
        }
    });
}

@Override
public Observable<Boolean> insertThisWord(final Word word) {
    return Observable.fromCallable(new Callable<Boolean>() {
        @Override
        public Boolean call() throws Exception {
            com.example.data.models.Word item = new com.example.data.models.Word(word.getWord(), word.getWordLength());
            db.wordDao().insertThisWord(item);
            return true;
        }
    });
}

@Override
public Observable<Boolean> deleteThisWord(final int wordId) {
    return Observable.fromCallable(new Callable<Boolean>() {
        @Override
        public Boolean call() throws Exception {
            db.wordDao().deleteThisWord(wordId);
            return true;
        }
    });
}

@Override
public Observable<Boolean> updateThisWord(final int wordId, final String newWord) {
    return Observable.fromCallable(new Callable<Boolean>() {
        @Override
        public Boolean call() throws Exception {
            db.wordDao().updateThisWord(wordId, newWord);
            return true;
        }
    });
}

@Override
public Observable<Word> getTheIndexOfTopWord() {
    return Observable.fromCallable(new Callable<Word>() {
        @Override
        public Word call() throws Exception {
            com.example.data.models.Word item = db.wordDao().getTheIndexOfTopWord();
            Word word = new Word(item.getWordId(), item.getWord(), item.getWordLength());
            return word;
        }
    });
}
}

域层中的GetAllWordsUseCase:

public class GetAllWords extends UseCase<List<Word>, GetAllWords.Params> {

private WordRepository wordRepository;

public GetAllWords(PostExecutionThread postExecutionThread, WordRepository wordRepository) {
    super(postExecutionThread);
    this.wordRepository = wordRepository;
}

@Override
public Observable<List<Word>> buildUseCaseObservable(Params params) {
    return wordRepository.getAllWords();
}

public static final class Params {
    private Params() {
    }

    public static GetAllWords.Params getAllWords() {
        return new GetAllWords.Params();
    }
}
}

域层中的UseCase基类:

public abstract class UseCase<T, Params> {

private final PostExecutionThread postExecutionThread;
private final CompositeDisposable compositeDisposable;

public UseCase(PostExecutionThread postExecutionThread) {
    this.postExecutionThread = postExecutionThread;
    this.compositeDisposable = new CompositeDisposable();
}

/**
 * Builds an {@link Observable} which will be used when executing the current {@link UseCase}.
 */
public abstract Observable<T> buildUseCaseObservable(Params params);

/**
 * Dispose from current {@link CompositeDisposable}.
 */
public void dispose() {
    if (!compositeDisposable.isDisposed()) {
        compositeDisposable.dispose();
    }
}

/**
 * Executes the current use case.
 *
 * @param observer {@link DisposableObserver} which will be listening to the observable build
 *                 by {@link #buildUseCaseObservable(Params)} ()} method.
 * @param params   Parameters (Optional) used to build/execute this use case.
 */
public void execute(DisposableObserver<T> observer, Params params) {
    if (observer != null) {
        final Observable<T> observable = this.buildUseCaseObservable(params)
                .subscribeOn(Schedulers.io())
                .observeOn(postExecutionThread.getScheduler());
        addDisposable(observable.subscribeWith(observer));
    }
}

/**
 * Dispose from current {@link CompositeDisposable}.
 */
private void addDisposable(Disposable disposable) {
    if (disposable != null && compositeDisposable != null)
        compositeDisposable.add(disposable);
}
}

最后,表示层中的单词活动

public class WordActivity extends BaseActivity<WordViewModel> implements 
View.OnClickListener, WordNavigator {

@Inject
WordViewModel wordViewModel;

private Button deleteButton, updateButton, addButton;
private EditText editTextWord;
private WordListAdapter adapter;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_word);
    ((MainApplication) getApplicationContext()).getComponent().inject(this);
    editTextWord = findViewById(R.id.activity_word_et_word);
    deleteButton = findViewById(R.id.activity_main_delete_button);
    updateButton = findViewById(R.id.activity_main_update_button);
    addButton = findViewById(R.id.activity_word_btn_add_word);

    deleteButton.setOnClickListener(this);
    updateButton.setOnClickListener(this);
    addButton.setOnClickListener(this);


    RecyclerView recyclerView = findViewById(R.id.recyclerview);
    adapter = new WordListAdapter(this);
    recyclerView.setAdapter(adapter);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));

    getViewModel().setNavigator(this);

    getViewModel().getAllWords();

    getViewModel().getWords().observe(this, new Observer<List<Word>>() {
        @Override
        public void onChanged(@android.support.annotation.Nullable List<Word> words) {
            adapter.setWords(words);
        }
    });

}

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.activity_main_delete_button:
            getViewModel().getTheIndexOfTopWord(TOP_INDEX_ACTION_DELETE);
            break;
        case R.id.activity_main_update_button:
            getViewModel().getTheIndexOfTopWord(TOP_INDEX_ACTION_UPDATE);
            break;
        case R.id.activity_word_btn_add_word:
            handleAddButtonClick();
            break;
    }
}

public void handleAddButtonClick() {
    String text = editTextWord.getText().toString();
    if (text.equals("")) {
        Toast.makeText(getApplicationContext(), R.string.empty_not_saved, Toast.LENGTH_LONG).show();
    } else {
        Word word = new Word(text, text.length());
        getViewModel().insertWord(word);
        editTextWord.setText("");
        editTextWord.clearFocus();
    }
}

@Override
public void updateTopIndex(Integer wordId, String action) {
    if (action.equals(TOP_INDEX_ACTION_DELETE))
        getViewModel().deleteThisWord(wordId);
    else
        getViewModel().updateThisWord(wordId, "dsakagdad");
}

@Override
public WordViewModel getViewModel() {
    return wordViewModel;
}
}


**getViewModel().getWords().observe(this, new Observer<List<Word>>() {
    @Override
    public void onChanged(@android.support.annotation.Nullable List<Word> words) {
        adapter.setWords(words);
    }
});**

//This portion is getting called only once but not when I 
  insert/update/delete words from room database!

谁能帮我检查一下吗!

共有1个答案

葛承嗣
2023-03-14

DAO中的此方法将查询列表,并像正常的SQL查询一样返回它:

@Query("select * from word_table order by word_id asc")
List<Word> getAllWords();

如果您想观察更改,您可能需要考虑使用RxJava2Flowable/可观察LiveData

由于我更喜欢RxJava方法,它将如下所示:

@Query("select * from word_table order by word_id asc")
Flowable<List<Word>> getAllWords();
// or
Observable<List<Word>> getAllWords();

流动性和可观察性之间的差异

完成后,您可能需要更改存储库中的getAllWords方法,以返回可流动/可观察的

注意:无论是使用可观察的还是可流动的,都将首先发出查询结果一次,然后开始观察进一步的更改,直到取消订阅。

阅读更多关于房间与RxJava

 类似资料:
  • 问题内容: 由于某种原因,我无法在MDN文档中找到这个简单的东西(也许我只是想念它)。 我希望这可以工作: …但是第一行抛出 如何从普通对象制作地图?我真的必须首先将其转换为键值对数组的数组吗? 问题答案: 是的,构造函数采用键值对数组。 是ES2017(19.1.2.5)中可用的新的Object静态方法。 如果您需要支持较旧的环境,并且不适合使用Transpilation,请使用polyfill

  • 我的数据库正在返回Flux,我需要将其转换为Mono 如果调用方方法的返回类型只有Mono,我可以很容易地将其映射如下,但由于它是Mono //期望将水果的流量转换为水果列表的单声道并返回给调用者 }

  • 问题内容: 我正在尝试检索JSON对象(我已验证的文件格式正确)中的数据,并将数据输出到firebug控制台中。我使用JSONLint(http://jsonlint.com/)验证了JSON,并且知道数据没有在JSON对象中返回,因为当我记录它时,它是以文本而不是对象的形式记录的。当我查看ajax帖子时,有一个JSON选项卡,其中显示了该对象,出于某种原因,我只是无法检索它。 我的ajax电话是

  • 2.Select query返回具有正确结构的JSON以转换为pojo 在mysql shell上执行查询将返回预期的JSON: 在camel中运行查询时,我遇到了一个问题,对此我无法找到解释或解决方案。 null 提前致谢

  • 在viewmodel类中获取数据方法

  • 问题内容: 我有一个猫鼬的文档,我想在JSON编码之前进行扩展并作为响应发送出去。如果我尝试向文档添加属性,则将其忽略。该属性不会出现无法进行正常扩展的情况。奇怪的是,它可以正常工作并返回具有所有正确属性的对象。有一个更好的方法吗? 问题答案: 猫鼬继承自s,后者有一个方法。我相信您要寻找的应该是的结果。 http://mongoosejs.com/docs/api.html#document_D