![](/img/trans.png)
[英]Android Room with LiveData + ViewModel Refresh Question
[英]Android - dynamically change a list with an edittext error - LiveData + Room + ViewModel
我想根據編輯文本的文本動態更改列表。 下面的技術有效,但是當我在同一活動中多次更改時,我收到錯誤消息。 我認為隨着變化的增加,我需要觀察的倍數過多,但我還沒有替代方案的想法。 我指定我的列表視圖顯示照片,它是一個畫廊。 我不想要一個搜索按鈕,我希望它可以實時完成。
還有一個問題,當我進行搜索時,大約十分之一的顯示照片與其來源不匹配,當我顯示它時(打開一個顯示單張照片的活動),原始來源會顯示,或者當我在編輯文本里改了一個字母,原來的源又回來了,真的很奇怪。
先感謝您
帶有編輯文本的活動:
// RecyclerView
RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(getApplicationContext(), 3);
recyclerView = findViewById(R.id.photo_album_recycler_view);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter);
// ViewModel
PhotoViewModel photoViewModel = new ViewModelProvider.AndroidViewModelFactory(getApplication()).create(PhotoViewModel.class);
photoViewModel.getAllPhotos().observe(PhotoAlbumActivity.this, new Observer<List<Photo>>() {
@Override
public void onChanged(List<Photo> photos) {
mAdapter.submitList(photos);
}
});
edtSearch.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
search = charSequence.toString().replaceAll(" ", "%");
photoViewModel.getSearchPhotos(search).observe(PhotoAlbumActivity.this, photos -> mAdapter.submitList(photos));
}
@Override
public void afterTextChanged(Editable editable) {
}
});
和錯誤:
W/oehpad.visiopa: Throwing OutOfMemoryError "Failed to allocate a 2132760 byte allocation with 2030720 free bytes and 1983KB until OOM, max allowed footprint 536870912, growth limit 536870912" (VmSize 2779292 kB)
E/AndroidRuntime: FATAL EXCEPTION: arch_disk_io_0
Process: fr.visioehpad.visiopad, PID: 20843
java.lang.RuntimeException: Exception while computing database live data.
at androidx.room.RoomTrackingLiveData$1.run(RoomTrackingLiveData.java:92)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
Caused by: android.database.sqlite.SQLiteException: unknown error (code 0 SQLITE_OK[0]): Native could not create new byte[]
at android.database.CursorWindow.nativeGetBlob(Native Method)
at android.database.CursorWindow.getBlob(CursorWindow.java:430)
at android.database.AbstractWindowedCursor.getBlob(AbstractWindowedCursor.java:45)
at fr.visioehpad.visiopad.data.repository.PhotoDao_Impl$6.call(PhotoDao_Impl.java:375)
at fr.visioehpad.visiopad.data.repository.PhotoDao_Impl$6.call(PhotoDao_Impl.java:354)
at androidx.room.RoomTrackingLiveData$1.run(RoomTrackingLiveData.java:90)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
I/Process: Sending signal. PID: 20843 SIG: 9
編輯 :
最后,我發現了一個問題,我使用彈出窗口進行搜索,但如果我使用 EditText 動態地使用它也是一樣的:
活動 :
// Get photos with the filter
photoViewModel.getPhotos().observe(this, new Observer<List<Photo>>() {
@Override
public void onChanged(List<Photo> photos) {
mAdapter.submitList(photos);
}
});
btnSearch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
searchPopup = new SearchPopup(PhotoAlbumActivity.this, search, "test");
searchPopup.setOnBtnClickListener(new SearchPopup.OnBtnClickListener() {
@Override
public void OnValidClick(String texte) {
// On vérifie si on laisse affiche le bouton pour annuler la recherche
if (texte.isEmpty()){
btnRemoveSearch.setVisibility(View.INVISIBLE);
} else {
btnRemoveSearch.setVisibility(View.VISIBLE);
}
search = texte;
photoViewModel.refreshData(search);
searchPopup.dismiss();
}
});
}
});
視圖模型:
private MutableLiveData<List<Photo>> photos = new MutableLiveData<>();
public MutableLiveData<List<Photo>> getPhotos(){
return photos;
}
/**
* Actualisation des données lors d'une nouvelle recherche.
* @param words les mots à rechercher
*/
public void refreshData(String words) {
ExecutorService service = Executors.newSingleThreadExecutor();
service.submit(new Runnable() {
@Override
public void run() {
List<Photo> freshPhotosList = mRepository.getSearchPhotos(DataSearchUtils.getTextForSearch(words));
photos.postValue(freshPhotosList);
}
});
}
用於在房間中查詢的實用程序(我沒有在 SQL (LIKE + IN) 中找到等效的 CONTAINS):
public static String getTextForSearch(String search) {
// init with percent to search all first or if search is empty
String str = "%";
if (!search.trim().isEmpty()) {
str += search.replaceAll(" ", "%");
str += "%";
}
return str;
}
存儲庫:
public List<Photo> getSearchPhotos(String chaine) {
return mPhotoDao.getSearchPhotos(userId, chaine);
}
道:
@Query("SELECT * FROM photo_table " +
"WHERE userId = :userId " +
"AND ( (description LIKE :chaine) " +
"OR (dateForSearch LIKE :chaine) " +
"OR (contactFrom LIKE :chaine)) " +
"ORDER BY date DESC")
List<Photo> getSearchPhotos(Long userId, String chaine);
您必須添加兩個函數,一個在視圖模型類中並從視圖或活動(observe)調用它並命名(refreshAllPhotos()),另一個在回收器視圖適配器類中調用(updateAllPhotos()),以及每次在編輯文本中搜索時,此函數都應清除所有照片列表,但每次運行活動時都應調用刷新函數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.