Adding callback and fix to RemoteViewsFactory on notifyDataSetChanged.

Also removing extra parameter in AppWidgetManager.notifyDataSetChanged.

Change-Id: Ic771fe045ae793a6dacf09f1230e7c1c4b59a13e
This commit is contained in:
Winson Chung
2010-08-16 10:14:56 -07:00
parent 385df2c7a5
commit 6394c0e52c
10 changed files with 96 additions and 25 deletions

View File

@@ -36145,8 +36145,6 @@
>
<parameter name="appWidgetIds" type="int[]">
</parameter>
<parameter name="views" type="android.widget.RemoteViews">
</parameter>
<parameter name="viewId" type="int">
</parameter>
</method>
@@ -36162,8 +36160,6 @@
>
<parameter name="appWidgetId" type="int">
</parameter>
<parameter name="views" type="android.widget.RemoteViews">
</parameter>
<parameter name="viewId" type="int">
</parameter>
</method>
@@ -228464,6 +228460,17 @@
visibility="public"
>
</method>
<method name="onDataSetChanged"
return="void"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="onDestroy"
return="void"
abstract="true"

View File

@@ -62,11 +62,10 @@ public class AppWidgetHost {
msg.sendToTarget();
}
public void viewDataChanged(int appWidgetId, RemoteViews views, int viewId) {
public void viewDataChanged(int appWidgetId, int viewId) {
Message msg = mHandler.obtainMessage(HANDLE_VIEW_DATA_CHANGED);
msg.arg1 = appWidgetId;
msg.arg2 = viewId;
msg.obj = views;
msg.sendToTarget();
}
}
@@ -87,7 +86,7 @@ public class AppWidgetHost {
break;
}
case HANDLE_VIEW_DATA_CHANGED: {
viewDataChanged(msg.arg1, (RemoteViews) msg.obj, msg.arg2);
viewDataChanged(msg.arg1, msg.arg2);
break;
}
}
@@ -264,13 +263,13 @@ public class AppWidgetHost {
}
}
void viewDataChanged(int appWidgetId, RemoteViews views, int viewId) {
void viewDataChanged(int appWidgetId, int viewId) {
AppWidgetHostView v;
synchronized (mViews) {
v = mViews.get(appWidgetId);
}
if (v != null) {
v.viewDataChanged(views, viewId);
v.viewDataChanged(viewId);
}
}
}

View File

@@ -264,7 +264,7 @@ public class AppWidgetHostView extends FrameLayout {
* Process data-changed notifications for the specified view in the specified
* set of {@link RemoteViews} views.
*/
void viewDataChanged(RemoteViews remoteViews, int viewId) {
void viewDataChanged(int viewId) {
View v = findViewById(viewId);
if ((v != null) && (v instanceof AdapterView<?>)) {
AdapterView<?> adapterView = (AdapterView<?>) v;

View File

@@ -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);
}
/**

View File

@@ -202,6 +202,7 @@ public class RemoteViewsAdapter extends BaseAdapter {
int count;
int viewTypeCount;
boolean hasStableIds;
boolean isDataDirty;
Map<Integer, Integer> 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<Integer, Integer>();
}
}
@@ -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();
}

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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<AppWidgetProviderInfo> getInstalledProviders();
AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId);
void bindAppWidgetId(int appWidgetId, in ComponentName provider);

View File

@@ -20,6 +20,7 @@ import android.widget.RemoteViews;
/** {@hide} */
interface IRemoteViewsFactory {
void onDataSetChanged();
int getCount();
RemoteViews getViewAt(int position);
RemoteViews getLoadingView();

View File

@@ -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<N; i++) {
AppWidgetId id = lookupAppWidgetIdLocked(appWidgetIds[i]);
notifyAppWidgetViewDataChangedInstanceLocked(id, views, viewId);
notifyAppWidgetViewDataChangedInstanceLocked(id, viewId);
}
}
}
@@ -502,18 +502,16 @@ class AppWidgetService extends IAppWidgetService.Stub
}
}
void notifyAppWidgetViewDataChangedInstanceLocked(AppWidgetId id, RemoteViews views, int viewId) {
void notifyAppWidgetViewDataChangedInstanceLocked(AppWidgetId id, int viewId) {
// allow for stale appWidgetIds and other badness
// lookup also checks that the calling process can access the appWidgetId
// drop unbound appWidgetIds (shouldn't be possible under normal circumstances)
if (id != null && id.provider != null && !id.provider.zombie && !id.host.zombie) {
id.views = views;
// is anyone listening?
if (id.host.callbacks != null) {
try {
// the lock is held, but this is a oneway call
id.host.callbacks.viewDataChanged(id.appWidgetId, views, viewId);
id.host.callbacks.viewDataChanged(id.appWidgetId, viewId);
} catch (RemoteException e) {
// It failed; remove the callback. No need to prune because
// we know that this host is still referenced by this instance.