You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

API 32以下版本GlanceAppWidget组件刷新失效问题求助

Compose Glance桌面组件API<32版本状态更新不刷新问题

我用Compose Glance开发了一款桌面组件,该组件在API 32版本上运行完全正常,但在所有API<32的版本中,当偏好设置/状态更新时,组件无法刷新。我已尝试深入理解偏好状态与GlanceWidget的数据交互逻辑,但仍未解决问题,查阅Google官方教程、开发者文章及相关教程后也没找到办法。

原始GlanceAppWidget实现代码

class CrTWidget : GlanceAppWidget() {

    override val stateDefinition: GlanceStateDefinition<*> = PreferencesGlanceStateDefinition
    //override val stateDefinition = TickerInfoStateDefinition

    override suspend fun provideGlance(context: Context, id: GlanceId) {
        //Log.v("GlanceAppWidget", "provideGlance")
        provideContent {
            //we're in composable context
            val prefs = currentState<Preferences>()
            var prefsMap =  prefs.asMap()
            //val prefs = currentState<TickerInfo>()
            // create your AppWidget here
            Log.v("GlanceAppWidget", "provideContent")
            MyContent(prefsMap)
        }
    }
    @Composable
    private fun MyContent(mapTickerz : Map<Preferences.Key<*>, Any>) {
        //https://developer.android.com/jetpack/compose/glance/glance-app-widget
        val listTickerz = mutableListOf<String>()
        mapTickerz.forEach{
            listTickerz.add(it.key.toString())
            //Log.v("GlanceAppWidget", "KEY FOUND IS IN PREFS MAP IS ${it.key}")
        }
        Log.v("GlanceAppWidget","PREFS MAP IS $listTickerz")
    }
    SomeCompositionWithmapTickerz(mapTickerz)
}

原始GlanceAppWidgetReceiver实现代码

class CrTWidgetReceiver : GlanceAppWidgetReceiver() {
    override val glanceAppWidget: GlanceAppWidget = CrTWidget()

    override fun onUpdate(
        context: Context,
        appWidgetManager: AppWidgetManager,
        appWidgetIds: IntArray
    ) {
        super.onUpdate(context, appWidgetManager, appWidgetIds)
        Log.v("CrTWidgetReceiver", "onUpdate GlanceAppWidgetReceiver")
        observeData(context)
    }

    override fun onReceive(context: Context, intent: Intent) {
        super.onReceive(context, intent)
        Log.v("CrTWidgetReceiver", "onReceive GlanceAppWidgetReceiver + ${intent.action}")
        if(intent.action == context.packageName + ".UpdateWIDGET"){
            observeData(context)
        }
        /*if(intent.action == "android.appwidget.action.APPWIDGET_UPDATE"){
            observeData(context)
        }*/

    }

    private fun observeData(context: Context) {
        try{
            Log.v("CrTWidgetReceiver", "observeData STARTED")
            val applicationScope = CoroutineScope(SupervisorJob())
            // Using by lazy so the database and the repository are only created when they're needed
            // rather than when the application starts
            val database by lazy { DatabasePT.getDatabase(context, applicationScope) }
            val repository by lazy { RepositoryPT(database.CrTickerDAO(), database.CrPairsDAO()) }
            var mapTickers: MutableMap<String, CrTickerModel> = mutableMapOf()

            //fetch data from repo
            var firstFlowReached = false
            CoroutineScope(SupervisorJob()).launch {
                repository.getAllDataSymbol.takeWhile { !firstFlowReached }.collect {syms ->
                    //Log.v("CrTWidgetReceiver", "collect OCCURENCE")
                    syms.forEach {symbol ->
                        mapTickers[symbol.cryptoTickName] = symbol
                    }
                    GlanceAppWidgetManager(context).getGlanceIds(CrTWidget::class.java).forEach { glanceId ->
                        updateAppWidgetState(context, glanceId) { pref ->
                            pref.clear()
                            mapTickers.forEach { symbol ->
                                Log.v("CrTWidgetReceiver", "LAST PRICE OF ${symbol.value.cryptoTickSymbol} IS ${symbol.value.cryptoTickQuote}")
                                val tick = symbol.value.cryptoTickSymbol
                                val tickQuoter = symbol.value.cryptoTickQuoter
                                val price = symbol.value.cryptoTickQuote
                                val source = symbol.value.cryptoTickSource
                                pref[stringPreferencesKey(symbol.value.cryptoTickName)] = "$tick¤$tickQuoter¤$price¤$source"
                            }
                        }
                        CrTWidget().update(context, glanceId)
                    }
                    firstFlowReached = true
                    Log.v("CrTWidgetReceiver", "EXITING COLLECT")
                }
            }
        }catch (e : Exception){
            var stringWriter = StringWriter()
            e.printStackTrace(PrintWriter(stringWriter))
            Log.e("CrTWidgetReceiver", "observeData ERROR $stringWriter")
        }
    }

}

编辑补充:尝试直接收集Flow的实现

尝试相关建议后,改为在provideGlance中直接收集Flow的方式实现,无需调用CrTWidget().updateAll(context)即可自动更新状态,但问题依旧:API>32版本正常,其他版本首次更新后便停止刷新。

代码如下:

class CrTWidget : GlanceAppWidget() {

    override suspend fun provideGlance(context: Context, id: GlanceId) {
        val applicationScope = CoroutineScope(SupervisorJob())
        // Using by lazy so the database and the repository are only created when they're needed
        // rather than when the application starts
        val database by lazy { DatabasePT.getDatabase(context, applicationScope) }
        val repository by lazy { RepositoryPT(database.CrTickerDAO(), database.CrPairsDAO()) }

        provideContent {
            var watchTickerState = repository.getAllDataSymbol.collectAsState(initial = listOf(
                CrTickerModel(cryptoTickTimestamp = "0", cryptoTickName = "EMPTY", cryptoTickNameAPI = "EMPTY", cryptoTickQuote = "EMPTY", cryptoTickQuoter = "EMPTY", cryptoTickSource = "BINANCE", cryptoTickSymbol = "EMPTY")
            ))
            //we're in composable context
            val prefs = currentState<Preferences>()
            var prefsMap =  prefs.asMap()
            MyContent(watchTickerState)
        }
    }
    @Composable
    private fun MyContent(watchTickerState: State<List<CrTickerModel>>) {
        //https://developer.android.com/jetpack/compose/glance/glance-app-widget
        watchTickerState.value.let { modelList ->
            Log.v("recomposed", modelList.toString())
            SomeCompositionWithList(modelList)
        }
    }
}

寻求解决思路。

内容的提问来源于stack exchange,提问作者PsyTrxOps

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 12:32:02