簡體   English   中英

如何使用 LiveData 在 ViewModel 中啟動 Kotlin 協程

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM