我正在使用ListView在Android窗口小部件中显示信息。
信息需要从Internet上加载,而Internet在调用RemoveViewsFactory onDataSetChanged
时使用异步任务加载。异步任务完成后,将再次调用onDataSetChanged
方法,并显示刚接收到的信息。
虽然最初一切正常,但是在Android初始化的更新(“ updatePeriodMillis”)上,小部件内的ListView变空了。即,不再显示条目,也不显示不存在条目时显示的“不存在条目”占位符。 窗口小部件的默认更新时间设置为一小时。
当我(通过小部件上的按钮)强制进行手动更新时,条目会再次显示。
根据我的调试日志消息,在条目消失之前调用onDataSetChanged
方法,从而强制更新信息。
awm.notifyAppWidgetViewDataChanged
(awm
是AppWidgetManager
)被调用,但最终不会触发public RemoteViews getViewAt(int position)
(或此方法返回null
?),并且{ {1}}没有被调用。
[编辑]
似乎在后台轮询完成之前,调用public int getCount()
方法并返回0。但是,在从回调中调用getCount()
方法之后(即,在存在新数据之后),{{ 1}}不再被调用。我实际上可以在不进行后台加载的情况下强制执行一次其他强制更新,但这比实际的正确方法更具hacky解决方法。
[/编辑]
由于这是一个相当罕见的事件(最少更新时间为30分钟...),所以我很难调试它,并希望遇到类似问题的人也可以。
完整的项目可在此处找到:Github
以下是代码摘录:
initData
还有getCount()
:
public class VplanWidgetDataProvider implements RemoteViewsService.RemoteViewsFactory {
// ...
@Override
public void onDataSetChanged() {
plan = new Vplan(mContext, day);
plan.loadFromCache();
initData();
}
// ...
private void initData() {
Log.d("WIDGET", "INIT DATA: " + plan.getDay());
nightmode = VplanWidget.useNightmode(mContext, widgetId);
mCollection.clear();
if (plan.isLoaded() && plan.upToDate()) {
mCollection.clear();
Log.d("WIDGET", "Data present");
for (VplanEntry entry : plan.getEntries()) {
mCollection.add(entry);
}
Log.d("WIDGET", "Entries: " + mCollection.size());
Log.d("WIDGET", "Day: " + plan.getDayString());
Log.d("WIDGET", "Date: " + plan.formatDate());
Log.d("WIDGET", "NOTIFY");
AppWidgetManager awm = AppWidgetManager.getInstance(mContext);
awm.notifyAppWidgetViewDataChanged(awm.getAppWidgetIds(new ComponentName(mContext, VplanWidgetServiceToday.class)), R.id.widget_list_view);
awm.notifyAppWidgetViewDataChanged(awm.getAppWidgetIds(new ComponentName(mContext, VplanWidgetServiceTomorrow.class)), R.id.widget_list_view);
} else {
Log.d("WIDGET", "Loading started");
plan.load(new SuccessCallback() {
@Override
public void callback(boolean success) {
Log.d("WIDGET", "Loading finished: " + success);
if (success) {
onDataSetChanged();
}
}
});
}
@Override
public RemoteViews getViewAt(int position) {
if (mCollection.size() <= position) {
return null;
}
VplanEntry entry = mCollection.get(position);
nightmode = VplanWidget.useNightmode(mContext, widgetId);
int layout = nightmode ? R.layout.vplan_widget_entry_dark : R.layout.vplan_widget_entry;
RemoteViews view = new RemoteViews(mContext.getPackageName(), layout);
view.setTextViewText(R.id.widget_plan_plan, entry.getPlan());
view.setTextViewText(R.id.widget_plan_comment, entry.getComment());
view.setTextViewText(R.id.widget_plan_substitution, entry.getSubstitution());
view.setTextViewText(R.id.widget_plan_lesson, entry.getLesson());
view.setTextViewText(R.id.widget_plan_cls, entry.getCls());
if (entry.getComment().isEmpty()) {
view.setViewVisibility(R.id.widget_plan_comment, View.GONE);
} else {
view.setViewVisibility(R.id.widget_plan_comment, View.VISIBLE);
}
if (entry.getSubstitution().isEmpty()) {
view.setViewVisibility(R.id.widget_plan_substitution, View.GONE);
} else {
view.setViewVisibility(R.id.widget_plan_substitution, View.VISIBLE);
}
if (entry.getSubstitution().isEmpty() && entry.getComment().isEmpty()) {
view.setViewVisibility(R.id.widget_arrow, View.GONE);
} else {
view.setViewVisibility(R.id.widget_arrow, View.VISIBLE);
}
return view;
}
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public boolean hasStableIds() {
return false;
}
}