我正在开发一个小部件的问题。它是由内容提供商支持的简单列表视图。问题是方法0的方法getViewAt()
被调用了两次。这是代码和日志。
Widget Xml提供程序:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="120dp"
android:minHeight="160dp"
android:updatePeriodMillis="86400000"
android:initialLayout="@layout/calendar_appwidget"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen|keyguard">
小工具服务
...
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return new CalendarRemoteViewsFactory(this.getApplicationContext(),intent);
}
...
厂
@Override
public void onCreate() {
readDateFormat(mContext);
simpleDateFormat = new SimpleDateFormat(datePattern, Locale.US);
mCal = Calendar.getInstance();
}
@Override
public RemoteViews getViewAt(int i) {
RemoteViews rv = new RemoteViews(mContext.getPackageName(),R.layout.calendar_widget_item);
Log.d("Widgets","Get view at "+i);
UpcomingShow show = (UpcomingShow)items.get(i);
mCal.setTime(getShowDay(show.getAirs_at()));
int dayOfMonth = mCal.get(Calendar.DAY_OF_MONTH);
if (mLastDay != dayOfMonth){
mLastDay = dayOfMonth;
rv.setTextViewText(R.id.day,String.valueOf(dayOfMonth));
rv.setViewVisibility(R.id.day, View.VISIBLE);
}else
rv.setViewVisibility(R.id.day, View.INVISIBLE);
rv.setTextViewText(R.id.title, show.getShow().getTitle());
try {
Date showDate = loadDate(show.getAirs_at(), datePattern);
simpleDateFormat.applyPattern(timeFormat == Utils.TimeFormat.CLOCK_24H ? "k:mm" : "h:mm a");
simpleDateFormat.setTimeZone(mTimeZone);
rv.setTextViewText(R.id.date,simpleDateFormat.format(showDate) + " on " + show.getShow().getNetwork());
} catch (Exception e) {
e.printStackTrace();
}
//Episode
String episodeStr = show.getEpisode().getSeason() + "x" + show.getEpisode().getNumber() + " " + show.getEpisode().getTitle();
rv.setTextViewText(R.id.episode,Utils.getTextInBold(episodeStr, 0, episodeStr.indexOf(" "), Spanned.SPAN_INCLUSIVE_EXCLUSIVE));
return rv;
}
@Override
public int getCount() {
return items != null ? items.size() : 0;
}
@Override
public RemoteViews getLoadingView() {
return null;
}
@Override
public int getViewTypeCount() {
return 1;
}
@Override
public long getItemId(int i) {
return 0;
}
@Override
public void onDataSetChanged() {
final long identityToken = Binder.clearCallingIdentity();
pos = 0;
Log.d("Widgets","OnDataSetChanged");
String selection = DataProviderContract.Upcoming.COLUMN_AIRS_AT + " >= " + mCal.getTimeInMillis();
try {
mCursor = mContext.getContentResolver().query(
DataProviderContract.Upcoming.CONTENT_URI,
null,
selection,
null,
DataProviderContract.Upcoming.COLUMN_AIRS_AT + " ASC "
);
if (items!=null && items.size()>0)
items.clear();
items = getShowsFromCursor(mCursor);
if (mCursor!=null && !mCursor.isClosed())
mCursor.close();
} catch (Exception e) {
e.printStackTrace();
}finally {
Binder.restoreCallingIdentity(identityToken);
}
}
窗口小部件提供程序
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
// Perform this loop procedure for each App Widget that belongs to this provider
for (int i=0; i<N; i++) {
// Set up the intent that starts the StackViewService, which will
// provide the views for this collection.
Intent intent = new Intent(context, CalendarWidgetService.class);
// Add the app widget ID to the intent extras.
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
// Instantiate the RemoteViews object for the app widget layout.
RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.calendar_appwidget);
// Set up the RemoteViews object to use a RemoteViews adapter.
// This adapter connects
// to a RemoteViewsService through the specified intent.
// This is how you populate the data.
rv.setRemoteAdapter(appWidgetIds[i], R.id.list, intent);
//Calls update
appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
logcat的
03-26 10:02:54.011 1781-1792/com.D/Widget﹕ Acaba o parse com: 5
03-26 10:02:54.019 1781-1791/com.D/Widgets﹕ Get view at 0
03-26 10:02:54.027 1781-1792/com.D/Widgets﹕ Get view at 0
03-26 10:02:54.031 1781-1792/com.D/Widgets﹕ Get view at 1
03-26 10:02:54.031 1781-1792/com.D/Widgets﹕ Get view at 2
03-26 10:02:54.035 1781-1792/com.D/Widgets﹕ Get view at 3
03-26 10:02:54.039 1781-1792/com.D/Widgets﹕ Get view at 4
PS: 小部件布局
<?xml version="1.0" encoding="utf-8"?>
<ListView
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@color/background"
android:dividerHeight="0dp"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/list"/>
正如你所看到的那样,方法被调用了两次pos 0并且有时跳转位置,比如getViewAt(1) - &gt; getViewAt(3) - &gt; getViewAt(2)。我不知道为什么会这样。我做错了什么。
Teste with 5.0.2,4.4.4,4.1.1
由于
答案 0 :(得分:1)
为了提高效率,ListView没有特定的顺序来调用位置,并且可以调用相同的位置两次或更多。这是预期的行为。
答案 1 :(得分:0)
好吧,也许你应该让你的getItemId()
至少返回位置而不是全部0.但这可能不是你问题的原因。
事实上,我相信Android并不保证调用getViewAt()
的顺序或时间。这不是你的错。更糟糕的是,在我的制作应用程序中,有时我遇到的情况是我的位置与我的尺寸相同,所以我崩溃了。
所以我的建议是,您可以安全地忽略调用的顺序或次数,并且应该防止错误的位置:检查对getViewAt()
和getItemId()
的调用,并使其返回null或-1。