From 6394c0e52cf641d93f678fd052499aa952e3595d Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Mon, 16 Aug 2010 10:14:56 -0700 Subject: [PATCH] Adding callback and fix to RemoteViewsFactory on notifyDataSetChanged. Also removing extra parameter in AppWidgetManager.notifyDataSetChanged. Change-Id: Ic771fe045ae793a6dacf09f1230e7c1c4b59a13e --- api/current.xml | 15 ++++-- .../java/android/appwidget/AppWidgetHost.java | 9 ++-- .../android/appwidget/AppWidgetHostView.java | 2 +- .../android/appwidget/AppWidgetManager.java | 10 ++-- .../android/widget/RemoteViewsAdapter.java | 51 +++++++++++++++++++ .../android/widget/RemoteViewsService.java | 19 ++++++- .../internal/appwidget/IAppWidgetHost.aidl | 2 +- .../internal/appwidget/IAppWidgetService.aidl | 2 +- .../internal/widget/IRemoteViewsFactory.aidl | 1 + .../com/android/server/AppWidgetService.java | 10 ++-- 10 files changed, 96 insertions(+), 25 deletions(-) diff --git a/api/current.xml b/api/current.xml index 3b262e9c6d2cc..28a531249bcc3 100644 --- a/api/current.xml +++ b/api/current.xml @@ -36145,8 +36145,6 @@ > - - @@ -36162,8 +36160,6 @@ > - - @@ -228464,6 +228460,17 @@ visibility="public" > + + )) { AdapterView adapterView = (AdapterView) v; diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java index b83642bb54c01..2a583c14f438b 100644 --- a/core/java/android/appwidget/AppWidgetManager.java +++ b/core/java/android/appwidget/AppWidgetManager.java @@ -353,12 +353,11 @@ public class AppWidgetManager { * to invalidate their currently data. * * @param appWidgetIds The AppWidget instances for which to notify of view data changes. - * @param views The RemoteViews which contains the view referenced at viewId. * @param viewId The collection view id. */ - public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, RemoteViews views, int viewId) { + public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId) { try { - sService.notifyAppWidgetViewDataChanged(appWidgetIds, views, viewId); + sService.notifyAppWidgetViewDataChanged(appWidgetIds, viewId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -370,11 +369,10 @@ public class AppWidgetManager { * to invalidate it's currently data. * * @param appWidgetId The AppWidget instance for which to notify of view data changes. - * @param views The RemoteViews which contains the view referenced at viewId. * @param viewId The collection view id. */ - public void notifyAppWidgetViewDataChanged(int appWidgetId, RemoteViews views, int viewId) { - notifyAppWidgetViewDataChanged(new int[] { appWidgetId }, views, viewId); + public void notifyAppWidgetViewDataChanged(int appWidgetId, int viewId) { + notifyAppWidgetViewDataChanged(new int[] { appWidgetId }, viewId); } /** diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java index ebf5d6ee9977d..cd1e4220260bb 100644 --- a/core/java/android/widget/RemoteViewsAdapter.java +++ b/core/java/android/widget/RemoteViewsAdapter.java @@ -202,6 +202,7 @@ public class RemoteViewsAdapter extends BaseAdapter { int count; int viewTypeCount; boolean hasStableIds; + boolean isDataDirty; Map mTypeIdIndexMap; RemoteViewsInfo() { @@ -209,6 +210,7 @@ public class RemoteViewsAdapter extends BaseAdapter { // by default there is at least one dummy view type viewTypeCount = 1; hasStableIds = true; + isDataDirty = false; mTypeIdIndexMap = new HashMap(); } } @@ -282,6 +284,39 @@ public class RemoteViewsAdapter extends BaseAdapter { } } + protected void onNotifyDataSetChanged() { + // we mark the data as dirty so that the next call to fetch views will result in + // an onDataSetDirty() call from the adapter + synchronized (mViewCacheInfo) { + mViewCacheInfo.isDataDirty = true; + } + } + + private void updateNotifyDataSetChanged() { + // actually calls through to the factory to notify it to update + if (mServiceConnection.isConnected()) { + IRemoteViewsFactory factory = mServiceConnection.getRemoteViewsFactory(); + try { + factory.onDataSetChanged(); + } catch (RemoteException e) { + e.printStackTrace(); + } + + } + + // re-request the new metadata (only after the notification to the factory) + requestMetaData(); + + // post a new runnable on the main thread to propagate the notification back + // to the base adapter + mMainQueue.post(new Runnable() { + @Override + public void run() { + completeNotifyDataSetChanged(); + } + }); + } + protected void updateRemoteViewsInfo(int position) { if (mServiceConnection.isConnected()) { IRemoteViewsFactory factory = mServiceConnection.getRemoteViewsFactory(); @@ -499,6 +534,16 @@ public class RemoteViewsAdapter extends BaseAdapter { @Override public void run() { while (mBackgroundLoaderEnabled) { + // notify the RemoteViews factory if necessary + boolean isDataDirty = false; + synchronized (mViewCacheInfo) { + isDataDirty = mViewCacheInfo.isDataDirty; + mViewCacheInfo.isDataDirty = false; + } + if (isDataDirty) { + updateNotifyDataSetChanged(); + } + int index = -1; synchronized (mViewCacheLoadIndices) { if (!mViewCacheLoadIndices.isEmpty()) { @@ -668,6 +713,12 @@ public class RemoteViewsAdapter extends BaseAdapter { public void notifyDataSetChanged() { // flush the cache so that we can reload new items from the service mViewCache.flushCache(); + + // notify the factory that it's data may no longer be valid + mViewCache.onNotifyDataSetChanged(); + } + + public void completeNotifyDataSetChanged() { super.notifyDataSetChanged(); } diff --git a/core/java/android/widget/RemoteViewsService.java b/core/java/android/widget/RemoteViewsService.java index 7c9d7ff77f1ac..61d628c664269 100644 --- a/core/java/android/widget/RemoteViewsService.java +++ b/core/java/android/widget/RemoteViewsService.java @@ -43,9 +43,24 @@ public abstract class RemoteViewsService extends Service { * An interface for an adapter between a remote collection view (ListView, GridView, etc) and * the underlying data for that view. The implementor is responsible for making a RemoteView * for each item in the data set. + * + * @see android.widget.Adapter */ public interface RemoteViewsFactory { + /** + * Called when your factory is first constructed. The same factory may be shared across + * multiple RemoteViewAdapters depending on the intent passed. + */ public void onCreate(); + /** + * Called upon {@link AppWidgetManager#notifyAppWidgetViewDataChanged} to allow a factory + * implementation to respond to data changes by updating any internal references. + */ + public void onDataSetChanged(); + /** + * Called when the last RemoteViewsAdapter that is associated with this factory is + * unbound. + */ public void onDestroy(); public int getCount(); @@ -64,7 +79,9 @@ public abstract class RemoteViewsService extends Service { public RemoteViewsFactoryAdapter(RemoteViewsFactory factory) { mFactory = factory; } - + public void onDataSetChanged() { + mFactory.onDataSetChanged(); + } public int getCount() { return mFactory.getCount(); } diff --git a/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl b/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl index f0920d14d0cc5..216d985bd55db 100644 --- a/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl +++ b/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl @@ -24,6 +24,6 @@ import android.widget.RemoteViews; oneway interface IAppWidgetHost { void updateAppWidget(int appWidgetId, in RemoteViews views); void providerChanged(int appWidgetId, in AppWidgetProviderInfo info); - void viewDataChanged(int appWidgetId, in RemoteViews views, int viewId); + void viewDataChanged(int appWidgetId, int viewId); } diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl index 8da51b180fa33..4d56745ac0eb8 100644 --- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl +++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl @@ -42,7 +42,7 @@ interface IAppWidgetService { void updateAppWidgetIds(in int[] appWidgetIds, in RemoteViews views); void partiallyUpdateAppWidgetIds(in int[] appWidgetIds, in RemoteViews views); void updateAppWidgetProvider(in ComponentName provider, in RemoteViews views); - void notifyAppWidgetViewDataChanged(in int[] appWidgetIds, in RemoteViews views, int viewId); + void notifyAppWidgetViewDataChanged(in int[] appWidgetIds, int viewId); List getInstalledProviders(); AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId); void bindAppWidgetId(int appWidgetId, in ComponentName provider); diff --git a/core/java/com/android/internal/widget/IRemoteViewsFactory.aidl b/core/java/com/android/internal/widget/IRemoteViewsFactory.aidl index 7851347d5d827..ae9900cc4b7cb 100644 --- a/core/java/com/android/internal/widget/IRemoteViewsFactory.aidl +++ b/core/java/com/android/internal/widget/IRemoteViewsFactory.aidl @@ -20,6 +20,7 @@ import android.widget.RemoteViews; /** {@hide} */ interface IRemoteViewsFactory { + void onDataSetChanged(); int getCount(); RemoteViews getViewAt(int position); RemoteViews getLoadingView(); diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java index b8b8880b9d5c3..f825df9bce72b 100644 --- a/services/java/com/android/server/AppWidgetService.java +++ b/services/java/com/android/server/AppWidgetService.java @@ -442,7 +442,7 @@ class AppWidgetService extends IAppWidgetService.Stub } } - public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, RemoteViews views, int viewId) { + public void notifyAppWidgetViewDataChanged(int[] appWidgetIds, int viewId) { if (appWidgetIds == null) { return; } @@ -454,7 +454,7 @@ class AppWidgetService extends IAppWidgetService.Stub synchronized (mAppWidgetIds) { for (int i=0; i