如何使用刷新按钮正确更新主屏幕小部件? (Android - 科特林)
How do I correctly update a home screen widget using a refresh button? (Android - Kotlin)
我创建了一个主屏幕小部件,它将显示比特币的当前价格,并带有一个刷新按钮,供用户手动获取价格数据。我将 Okhttp 用于 HTTP 请求,这部分工作正常。
但是,当将小部件添加到我的主屏幕时,它只响应按钮的某些次按下。我可以直观地看到按钮被按下,但没有任何反应。其他时候,它可以完美运行。我很好奇是什么导致了这种行为?
这是我的 AppWidgetProvider 的 onUpdate() 函数 class。
override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray
) {
// There may be multiple widgets active, so update all of them
for (appWidgetId in appWidgetIds) {
val intent = Intent(context, PriceWidget::class.java)
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0)
val views = RemoteViews(context.packageName, R.layout.price_widget)
views.setOnClickPendingIntent(R.id.refresh_button, pendingIntent)
appWidgetManager.updateAppWidget(appWidgetId, views)
}
}
按下按钮时,它会创建一个调用 AppWidgetProvider 函数 onReceive() 的 PendingIntent:
override fun onReceive(context: Context?, intent: Intent?) {
super.onReceive(context, intent)
println("Refresh button pressed!")
if (intent!!.extras != null) {
val appWidgetManager = AppWidgetManager.getInstance(context)
val thisAppWidget = ComponentName(context!!.packageName, PriceWidget::class.java.name)
val appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget)
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
这是我的 updateAppWidget 函数:
internal fun updateAppWidget(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetId: Int
) {
val views = RemoteViews(context.packageName, R.layout.price_widget)
views.setTextViewText(R.id.appwidget_text, "Loading...")
views.setTextViewText(R.id.price_change_widget, "24h: Loading...")
appWidgetManager.updateAppWidget(appWidgetId, views)
getWidgetData(views, appWidgetManager, appWidgetId)
}
最后,我的函数 getWidgetData 发出 HTTP GET 请求。根据响应,JSON 字符串使用 Gson 转换为 Data() 对象。此代码使用 RemoteView 更改文本并调用 appWidhetManager.updateAppWidget 函数。
// sets textView to current price
views.setTextViewText(R.id.appwidget_text, data.price())
views.setTextViewText(R.id.price_change_widget, data.change24h())
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, views)
我关注了 Whosebug 的其他答案,none 似乎解决了这个问题。我注意到将两个小部件添加到主屏幕只能解决问题,直到删除其中一个小部件。
乐于接受所有建议 and/or 任何形式的帮助!如果我可以提供任何其他信息,请告诉我!
2021 年 10 月 27 日 -
我找到了一个可以用新信息刷新小部件的解决方案。
我从 AppWidgetProvider 的 onUpdate() 方法中删除了登录,所以现在它只有样板代码:
override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray
) {
// There may be multiple widgets active, so update all of them
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
现在,updateAppWidget()
方法具有所有逻辑。我创建了一个 RemoteView()
链接到主屏幕小部件的布局,使用 setTextViewText()
修改了小部件上的一些文本,然后调用 appWidgetManager.updateAppWidget(appWidgetId, views)
.
在同一个函数中,我通过创建一个 PendingIntent()
来继续逻辑,当按下刷新按钮时,我调用一个单独的函数来处理 HTTP GET 请求。
返回并处理数据后,我再次调用 appWidgetManager.updateAppWidget(appWidgetId, views)
。由于这是从一个单独的函数发生的,因此我必须将 appWidgetManager 和 appWidgetId 作为变量传递。
我希望这可以帮助别人。按钮刷新现在基本上有 99% 的时间有效。它很少见,但我认为这与 Android 手机上的低功耗模式有关。这是我的 GitHub 的源代码:PriceWidget.kt
我创建了一个主屏幕小部件,它将显示比特币的当前价格,并带有一个刷新按钮,供用户手动获取价格数据。我将 Okhttp 用于 HTTP 请求,这部分工作正常。
但是,当将小部件添加到我的主屏幕时,它只响应按钮的某些次按下。我可以直观地看到按钮被按下,但没有任何反应。其他时候,它可以完美运行。我很好奇是什么导致了这种行为?
这是我的 AppWidgetProvider 的 onUpdate() 函数 class。
override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray
) {
// There may be multiple widgets active, so update all of them
for (appWidgetId in appWidgetIds) {
val intent = Intent(context, PriceWidget::class.java)
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0)
val views = RemoteViews(context.packageName, R.layout.price_widget)
views.setOnClickPendingIntent(R.id.refresh_button, pendingIntent)
appWidgetManager.updateAppWidget(appWidgetId, views)
}
}
按下按钮时,它会创建一个调用 AppWidgetProvider 函数 onReceive() 的 PendingIntent:
override fun onReceive(context: Context?, intent: Intent?) {
super.onReceive(context, intent)
println("Refresh button pressed!")
if (intent!!.extras != null) {
val appWidgetManager = AppWidgetManager.getInstance(context)
val thisAppWidget = ComponentName(context!!.packageName, PriceWidget::class.java.name)
val appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget)
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
这是我的 updateAppWidget 函数:
internal fun updateAppWidget(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetId: Int
) {
val views = RemoteViews(context.packageName, R.layout.price_widget)
views.setTextViewText(R.id.appwidget_text, "Loading...")
views.setTextViewText(R.id.price_change_widget, "24h: Loading...")
appWidgetManager.updateAppWidget(appWidgetId, views)
getWidgetData(views, appWidgetManager, appWidgetId)
}
最后,我的函数 getWidgetData 发出 HTTP GET 请求。根据响应,JSON 字符串使用 Gson 转换为 Data() 对象。此代码使用 RemoteView 更改文本并调用 appWidhetManager.updateAppWidget 函数。
// sets textView to current price
views.setTextViewText(R.id.appwidget_text, data.price())
views.setTextViewText(R.id.price_change_widget, data.change24h())
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, views)
我关注了 Whosebug 的其他答案,none 似乎解决了这个问题。我注意到将两个小部件添加到主屏幕只能解决问题,直到删除其中一个小部件。
乐于接受所有建议 and/or 任何形式的帮助!如果我可以提供任何其他信息,请告诉我!
2021 年 10 月 27 日 -
我找到了一个可以用新信息刷新小部件的解决方案。
我从 AppWidgetProvider 的 onUpdate() 方法中删除了登录,所以现在它只有样板代码:
override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray
) {
// There may be multiple widgets active, so update all of them
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
现在,updateAppWidget()
方法具有所有逻辑。我创建了一个 RemoteView()
链接到主屏幕小部件的布局,使用 setTextViewText()
修改了小部件上的一些文本,然后调用 appWidgetManager.updateAppWidget(appWidgetId, views)
.
在同一个函数中,我通过创建一个 PendingIntent()
来继续逻辑,当按下刷新按钮时,我调用一个单独的函数来处理 HTTP GET 请求。
返回并处理数据后,我再次调用 appWidgetManager.updateAppWidget(appWidgetId, views)
。由于这是从一个单独的函数发生的,因此我必须将 appWidgetManager 和 appWidgetId 作为变量传递。
我希望这可以帮助别人。按钮刷新现在基本上有 99% 的时间有效。它很少见,但我认为这与 Android 手机上的低功耗模式有关。这是我的 GitHub 的源代码:PriceWidget.kt