gpt4 book ai didi

android - 如何使用LiveData在ViewModel中启动Kotlin Coroutine

转载 作者:行者123 更新时间:2023-12-02 13:27:48 26 4
gpt4 key购买 nike

我试图从ViewModel异步获取所有可启动的已安装应用程序。
这是我的ViewModel类的样子:

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>>
}
}
加载应用列表没有问题。但是,似乎我的代码仍然不能异步运行,因为在进入应用程序已安装列表 Activity 之前,它仍然冻结了几秒钟。
这是我用来观察 LiveData的代码:
appInstalledViewModel.getAppInstalledLiveData().observe(this, Observer { appInstalledItem ->
if (appInstalledItem.size > 0) {
appInstalledAdapter.appInstalled.addAll(appInstalledItem)
app_list_progressbar.visibility = View.GONE
}
})
尝试在Android Development上使用Kotlin让我感到困惑。这是我第一次使用Kotlin开发应用程序。我什至不知道我上面编写的代码在Kotlin风格的背景下是否是一个好的代码。
请帮我!谢谢!

最佳答案

这是因为在Main调度程序中执行了长时间运行的作业。我强烈建议您看看Coroutines Dispatchers
因此,如果将调度程序更改为Dispatchers.Default,从而导致获取已安装的应用程序在后台线程中执行,因此,UI将永远不会冻结。

appInstalledLiveData = liveData(Dispatchers.Default) {
...
}

更多:
如果要实现更好的结构,最好不通过调用函数来访问 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()即可,应用程序列表将得到更新。

关于android - 如何使用LiveData在ViewModel中启动Kotlin Coroutine,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63205710/

26 4 0