我正在使用带有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!
谁能帮我检查一下吗!
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