JMR*_*ies 8 android android-appwidget
我的小部件由2个按钮和一个显示数据的列表视图组成.大多数情况下,当调用窗口小部件提供程序的onUpdate方法时,一切都正常加载,每个人都很高兴.
但是我注意到有时在调用update方法之后,widget完全无法加载其数据.列表视图为空,并且所有按钮都没有响应.就像我将布局初始化到窗口小部件中一样,但没有设置挂起的意图和列表的适配器.
我记录了一切,发现事实并非如此.每次都会创建挂起的意图,以及列表适配器,包括失败时的随机时间.很长一段时间以来,我认为它与列表数据如何填充到适配器中有关,但每次都看到它工作,再加上按钮意图不能正常工作的事实让我相信方法updateAppWidget (ComponentName,RemoteViews)是失败的.但是,没有错误堆栈可以帮助我确认这一点.
以下是在AppWidgetProvider的onUpdate方法调用的单独服务中运行的代码:
@SuppressWarnings("deprecation")
private void updateWidget(int[] ids) {
AppWidgetManager widgetManager = AppWidgetManager.getInstance(this);
int[] widgetIds = widgetManager.getAppWidgetIds(new ComponentName(this, WidgetReceiver.class));
for (int currentWidgetId : widgetIds) {
RemoteViews widget = new RemoteViews(this.getPackageName(), R.layout.widget_layout);
Intent intent = new Intent(this, WidgetService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, currentWidgetId);
intent.putExtra("random", randomNumber);
randomNumber++;
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
widget.setRemoteAdapter(currentWidgetId, android.R.id.list, intent);
Intent clickIntent = new Intent(this, DetailsActivity.class);
PendingIntent pending = PendingIntent.getActivity(this, 0, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
widget.setPendingIntentTemplate(android.R.id.list, pending);
Intent settingsIntent = new Intent(this, WidgetSettingsActivity.class);
settingsIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
settingsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent settingsPending = PendingIntent.getActivity(this, 0, settingsIntent, PendingIntent.FLAG_UPDATE_CURRENT);
widget.setOnClickPendingIntent(R.id.widget_settings, settingsPending);
Intent mainIntent = new Intent(this, MainActivity.class);
PendingIntent mainPending = PendingIntent.getActivity(this, 0, mainIntent, PendingIntent.FLAG_UPDATE_CURRENT);
widget.setOnClickPendingIntent(R.id.widget_logo, mainPending);
ComponentName widgetCompName = new ComponentName(this, WidgetReceiver.class);
widgetManager.updateAppWidget(widgetCompName, widget);
}
}
Run Code Online (Sandbox Code Playgroud)
对这个bug最令人沮丧的是我无法可靠地重新创建它.有时我得到(非)幸运,它表现出丑陋的头脑,有时候(大部分时间)它完美地运作.
我认为有趣的另一件事是我在Facebook的小部件中看到了同样的问题.由于NDA我失败时无法显示我的应用程序的屏幕,但我可以显示Facebook相同问题的屏幕:

当Facebook的小部件看起来像这样时,它与我的问题完全相同.没有加载数据,所有按钮都没有响应.
对于Facebook和我的小部件,后续更新间隔通常会使问题消失.
尽管我很欣赏我并不是唯一遇到这种情况的人,但我仍然不想发布,直到我解决这个问题.有没有人遇到这个,更好的是找到了解决方案,甚至是问题的原因?谢谢你的帮助.
编辑:有趣的东西.我进行了一项实验,我将更新间隔设置为一整天而不是每30分钟.我的假设是,可能更新方法不是原因,而是导致小部件变得空白且无响应的其他因素.
果然,大约2个小时后,我检查了我的手机并且小部件已经死了,尽管没有调用更新方法.这会让我相信其他东西导致了这个问题,widgetManager.updateAppWidget(widgetCompName, widget);不像我之前想的那样.
我知道配置更改可能导致重建窗口小部件,因此可能会失败.但是,我已经使用Service类的onConfigurationChanged方法在必要时重新加载小部件.是否有另一种情况,如配置更改,可以导致小部件销毁并重新创建自己?
经过大量的血,汗和泪,我找到了解决方案.我将在几天内推迟确认这个答案,以确保错误不会重新出现,但经过大量观察后我认为已经解决了.
所以我在原始问题中的编辑评论中是正确的.这并不是说导致问题的AppWidgetManager的更新方法,而是一些其他Android的过程,导致应用程序插件重新本身.不幸的是我无法隔离那个触发器,但我确实找到了解决方案.
在我的RemoteViewsFactory类(基本上,其用于加载数据集中的包装器),我有看起来像这样的代码块:
RemoteViews views = new RemoteViews(mContext.getPackageName(), R.layout.widget_layout);
if(mItems.size() == 0)
views.setViewVisibility(R.id.widget_empty, View.VISIBLE);
else
views.setViewVisibility(R.id.widget_empty, View.GONE);
AppWidgetManager manager = AppWidgetManager.getInstance(mContext);
ComponentName widgetCompName = new ComponentName(mContext, WidgetReceiver.class);
manager.updateAppWidget(widgetCompName, views);
Run Code Online (Sandbox Code Playgroud)
基本上,如果列表为空,我会显示一条Loading信息,该信息占据了listview所在的整个区域.如果列表不为空,我只是隐藏该消息.
所以这就是发生的事情:当工厂被销毁时(大概是为了记忆目的),小部件本身不是.因此,所有设置数据和内容意图的代码都没有运行.但是,重新创建了工厂,该工厂运行了代码块,该代码块使用新的远程视图对象更新了应用程序窗口小部件.这个远程视图对象没有执行我在我最初发布的onUpdate()方法中看到的任何方法,因此它的所有功能都不起作用.
故事的道德:不要updateAppWidget在你的RemoteViewsFactory类中使用!现在它可能会运行所有必要的行,但我无法确认.
| 归档时间: |
|
| 查看次数: |
4529 次 |
| 最近记录: |