Я реализовал LiveData & ViewModel для имитации AsyncTaskLoader.
Я загружаю имена файлов из каталога камеры в DCIM, а затем прикрепляю fileObserver, чтобы Наблюдать, когда файл (изображение) удаляется, а затем обратный вызов сообщает LiveData о необходимости повторного получения fileNames при удалении события.происходит
Проблема:
Приведенный ниже код должен извлекать имена файлов из DCIM / Pictures асинхронно с помощью LiveData, а затем к каталогу присоединяется FileObserver (DCIM / Pictures), чтобы отслеживать, когда файл удален и реализован обратный вызов с подклассом LiveData для перезагрузки файлов, как показано в коде.
хорошо, это работает в первый раз, то естьфайлы загружаются в первый раз, вызывая setValue()
и передавая fileNames, вызванные onChange, для вызова в наблюдающей операции / фрагменте.Но когда файл удален, функция обратного вызова вызывает функцию loadFiles () для повторной загрузки файлов, но при вызове setValue и передаче в FileNames не запускается OnChange в наблюдаемой операции / фрагменте на этот раз.
В соответствии с официальной документацией LiveData
Вы должны вызвать метод setValue (T) для обновления объекта LiveData из основного потока.
Мне любопытно узнать, почему LiveData не обновляет свое значение после первого вызова.
Код
MyLiveData
class MyLiveData() : MutableLiveData<MutableList<String>>(), PictureDelete {
override fun onPicDelete() {
loadFileNames()
}
val TAG = "MyLiveData"
val fileNamesList: MutableList<String> = ArrayList()
val fileWatcher : MyFileWatcher
init {
loadFileNames()
val pathToWatch = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM + "/Camera").getAbsolutePath()
fileWatcher = MyFileWatcher(pathToWatch, this)
fileWatcher.startWatching()
}
private fun loadFileNames() {
val fileDir: File
try {
fileDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM + "/Camera")
} catch (e: Exception) {
Log.e(TAG, e.message)
return
}
Log.d(TAG, "Actively Loading Files in Status LiveData")
val arrayOfFiles = fileDir.listFiles()
if (arrayOfFiles == null || arrayOfFiles.size < 1) return
Log.d(TAG, "Actively Loading Files. Size: ${arrayOfFiles.size}")
setValue(fileNamesList)
}
}
MyViewModel
class MyViewModel() : ViewModel() {
val myLiveData: MyLiveData
val TAG = "WhatsAppFragment-VModel"
init {
myLiveData = MyLiveData()
}
}
MyFragment
class MyFragment : Fragment() {
private val TAG = "MyFragment"
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_layout, container, false)
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val viewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)
viewModel.myLiveData.observe(this, androidx.lifecycle.Observer { fileNames ->
Log.d(TAG, "New Live Data Dispatch")
for ((index, name) in fileNames.withIndex()) {
Log.d(TAG, "the element at $index is $name")
}
})
}
}
MyFileObserver
class MyFileWatcher(pathToWatch: String, val picDelete: PictureDelete) : FileObserver(pathToWatch, DELETE) {
val TAG = "MyFileWatcher"
init {
Log.d(TAG, "Initialization")
}
override fun onEvent(event: Int, path: String?) {
if (event = FileObserver.DELETE) { // EventCode 512 == Delete
Log.d(TAG, "OnEvent. Event: $event Path: $path")
picDelete.onPicDelete()
}
}
}
Интерфейс PictureDelete
interface PictureDelete {
fun onPicDelete()
}
Что не так с моей реализацией?