[英]How to start Kotlin Coroutine in ViewModel with LiveData
我試圖從ViewModel
異步獲取所有可啟動的已安裝應用程序。
這是我的ViewModel
class 看起來像:
class AppInstalledViewModel(application: Application) : AndroidViewModel(application) {
private var appInstalledLiveData: LiveData<ArrayList<AppInstalled>>? = null
fun getAppInstalledLiveData(): LiveData<ArrayList<AppInstalled>> {
if (appInstalledLiveData == null) {
appInstalledLiveData = liveData {
val appInstalled = ArrayList<AppInstalled>()
val pm: PackageManager =
getApplication<Application>().applicationContext.packageManager
val main = Intent(Intent.ACTION_MAIN, null).addCategory(Intent.CATEGORY_LAUNCHER)
// Get launchable installed apps
val launchAble = pm.queryIntentActivities(main, 0)
// Sort the installed app list
Collections.sort(launchAble, ResolveInfo.DisplayNameComparator(pm))
// Iterate over each launchable app and
// add it to AppInstalled ArrayList
for (l in launchAble) {
val activityInfo = l.activityInfo
activityInfo.run {
appInstalled.add(
AppInstalled(
loadLabel(pm).toString(),
applicationInfo.packageName,
loadIcon(pm)
)
)
}
}
emit(appInstalled)
}
}
return appInstalledLiveData as LiveData<ArrayList<AppInstalled>>
}
}
加載應用列表沒有問題。 但是,我的代碼似乎仍然沒有異步運行,因為它在移動到應用程序安裝列表活動之前仍然凍結了幾秒鍾。
這是我用來觀察LiveData
的代碼:
appInstalledViewModel.getAppInstalledLiveData().observe(this, Observer { appInstalledItem ->
if (appInstalledItem.size > 0) {
appInstalledAdapter.appInstalled.addAll(appInstalledItem)
app_list_progressbar.visibility = View.GONE
}
})
嘗試在 Android 開發中使用 Kotlin 讓我很困惑。 這是我第一次使用 Kotlin 開發應用程序。 我什至不知道我上面寫的代碼在 Kotlin 風格的上下文中是否是一個好的代碼。
請幫我! 謝謝!
這是因為在Main
調度程序中執行了長時間運行的作業。 我強烈推薦看看Coroutines Dispatchers 。
因此,如果您將調度程序更改為Dispatchers.Default
,導致獲取已安裝的應用程序在后台線程中執行,因此,UI 將永遠不會被凍結。
appInstalledLiveData = liveData(Dispatchers.Default) {
...
}
更多的:
如果您想獲得更好的結構,最好不要通過調用 function 來訪問LiveData
:
class AppInstalledViewModel(application: Application) : AndroidViewModel(application) {
private val reloadLiveData = MutableLiveData<Unit>()
val installedAppsLiveData: LiveData<ArrayList<AppInstalled>> =
reloadLiveData.switchMap {
liveData(Dispatchers.Default) {
emit(fetchInstalledApps())
}
}
fun reloadApps() {
reloadLiveData.postValue(Unit)
}
private fun fetchInstalledApps(): ArrayList<AppInstalled> {
val appInstalled = ArrayList<AppInstalled>()
val pm: PackageManager = getApplication<Application>().applicationContext.packageManager
val main = Intent(Intent.ACTION_MAIN, null).addCategory(Intent.CATEGORY_LAUNCHER)
// Get launchable installed apps
val launchAble = pm.queryIntentActivities(main, 0)
// Sort the installed app list
Collections.sort(launchAble, ResolveInfo.DisplayNameComparator(pm))
// Iterate over each launchable app and
// add it to AppInstalled ArrayList
for (l in launchAble) {
val activityInfo = l.activityInfo
activityInfo.run {
appInstalled.add(
AppInstalled(
loadLabel(pm).toString(),
applicationInfo.packageName,
loadIcon(pm)
)
)
}
}
return appInstalled
}
}
現在,在片段中:
appInstalledViewModel.installedAppsLiveData.observe(this, Observer { appInstalledItem ->
if (appInstalledItem.size > 0) {
appInstalledAdapter.appInstalled.addAll(appInstalledItem)
app_list_progressbar.visibility = View.GONE
}
})
appInstalledViewModel.reloadApps()
使用這種結構,如果要刷新加載的數據,只需調用appInstalledViewModel.reloadApps()
,然后更新應用列表。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.