Я реализовал LiveData и ViewModel для имитации AsyncTaskLoader.
Я загружаю имена файлов из каталога камеры в DCIM, а затем прикрепляю fileObserver для наблюдения за удалением файла (изображения), а затем обратный вызов сообщает LiveData повторно получить имена файлов при возникновении события удаления.
Проблема:
Приведенный ниже код должен асинхронно извлекать имена файлов из DCIM / Pictures с помощью LiveData, а затем к каталогу (DCIM / Pictures) присоединяется FileObserver, чтобы отслеживать, когда файл удаляется, и выполняется обратный вызов с помощью подгруппы LiveData. класс, чтобы перезагрузить файлы, как показано в коде.
хорошо, он работает в первый раз, то есть файлы загружаются в первый раз, вызывая setValue()
и передавая имена файлов, запускаемые onChange для вызова в наблюдаемом Activity / Fragment. Но когда файл удаляется, функция обратного вызова вызывает функцию loadFiles () для повторной загрузки файлов, но вызов setValue и передача FileNames на этот раз не запускают OnChange в наблюдаемой Activity / Fragment.
Согласно официальной документации 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()
}
Что не так с моей реализацией?
MyFileWatcher
прослушивается, но мы не видим этого, не так ли? - person EpicPandaForce   schedule 30.01.2019if (event == FileObserver.DELETE)
, но, видимо, это кажется правильным. Хм. Код кажется правильным, поэтому я готов поспорить, что с FileObserver что-то не так, но я не понимаю, почему он не работает. : | - person EpicPandaForce   schedule 30.01.2019