我有一个包含StackView的AppWidget。与AppWidget一起,我有一个服务,当用户将我的AppWidget添加到他们的主屏幕时每两小时轮询一次新数据时启动该服务。当服务找到新数据时,我需要它提醒我的AppWidget,并将该数据传递给RemoteViewsService(它有我的RemoteViewsFactory),以便它可以为新数据创建必要的视图。
目前,当服务找到新数据时,我向AppWidget广播已发现新数据,将该数据作为意图内的整数数组传递。
我的AppWidgetProvider中的onReceive方法将数据拉出来,然后我完成设置一个新的intent的过程,该新的intent传递给我的RemoteViews for AppWidget。示例代码如下:
public void onReceive( Context context, Intent intent )
{
int[] appWidgetIds = appWidgetManager.getAppWidgetIds( new ComponentName( context, SampleAppWidgetProvider.class ) );
int[] sampleData = intent.getIntArrayExtra( Intent.EXTRA_TITLE );
for ( int i = 0; i < appWidgetIds.length; i++ )
{
// RemoteViewsFactory service intent
Intent remoteViewsFactoryIntent = new Intent( context, SampleAppWidgetService.class );
remoteViewsFactoryIntent.putExtra( AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i] );
remoteViewsFactoryIntent.setData( Uri.parse( remoteViewsFactoryIntent.toUri( Intent.URI_INTENT_SCHEME ) ) );
remoteViewsFactoryIntent.putExtra( Intent.EXTRA_TITLE, sampleData );
RemoteViews rv = new RemoteViews( context.getPackageName(), R.layout.widget_layout );
// Sync up the remoteviews factory
rv.setRemoteAdapter( appWidgetIds[i], R.id.sample_widget, remoteViewsFactoryIntent );
rv.setEmptyView( R.id.sample_widget, R.id.empty_view );
appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
}
super.onUpdate( context, appWidgetManager, appWidgetIds );
}
这是第一次使用。 RemoteViewsService / RemoteViewsFactory显示数据。后续新数据未命中RemoteViewsFactory的构造函数,因为该工厂的服务已在运行。
如何更新数据?我觉得我应该使用onDataSetChanged,但是如何访问我从AppWidget的onReceive传递的意图?
我很欣赏任何关于如何妥善解决这个问题的见解。感谢。
答案 0 :(得分:5)
我使用BroadcastReceiver解决了传递给RemoteViewsFactory的整数数组的解决方案。我扩展了我的RemoteViewsFactory来实现BroadcastReceiver(特别是onReceive),并在工厂的构造函数中将我的应用程序注册到了它(这也意味着我在onDestroy中取消注册它)。有了这个,我能够用我在AppWidgetProvider的onReceive中的整数数组广播intent,并在RemoteViewsFactory中接收它。
确保同时调用AppWidgetManager的notifyAppWidgetViewDataChanged,以便RemoteViewsFactory知道它之前使用的数据已经失效,并且提供了一个新的整数数组来创建新的RemoteViews。
答案 1 :(得分:3)
为了arne.jans和其他人的利益,为了进一步阐述Steve的上述解决方案,我实施了Steven的解决方案:
StackRemoteViewsFactory
提取到自己的BroadcastReceiver
onReceive()
方法以将新数据保存到StackRemoteViewsFactory
类在其getViewAt
需要数据时也可以访问的静态变量Intent
传入所有小部件ID,以便我可以使用notifyAndUpdate
方法调用所有小部件中的onReceive()
。答案 2 :(得分:2)
我没有使用BroadcastReceiver扩展RemoteViewFactory,但在其上实现动态BroadcastReceiver以将字符串从AppWidgetProvider传递到RemoteViewFactory。
像这样:public class MyWidgetProvider extends AppWidgetProvider {
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
String action = intent.getAction();
if (action.equals("android.appwidget.action.APPWIDGET_UPDATE")) {
.....
} else if (action.equals("some.string.you.want.ACTION_TODO")) {
String url = intent.getStringExtra("some.string.you.want.EXTRA_URL");
// Send broadcast intent to pass mUrl variable to the MyContentFactory.
Intent broadcastIntent = new Intent("some.string.you.want.ACTION_UPDATE_URL");
broadcastIntent.putExtra("some.string.you.want.EXTRA_URL", url);
context.sendBroadcast(broadcastIntent);
}
.....
}
}
public class MyContentFactory implements RemoteViewsService.RemoteViewsFactory {
private Context mContext;
private String mUrl; // target to update
private BroadcastReceiver mIntentListener;
public MyContentFactory(Context context, Intent intent) {
mContext = context;
setupIntentListener();
}
@Override
public void onDestroy() {
teardownIntentListener();
}
private void setupIntentListener() {
if (mIntentListener == null) {
mIntentListener = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Update mUrl through BroadCast Intent
mUrl = intent.getStringExtra("some.string.you.want.EXTRA_URL");
}
};
IntentFilter filter = new IntentFilter();
filter.addAction("some.string.you.want.ACTION_UPDATE_URL");
mContext.registerReceiver(mIntentListener, filter);
}
}
private void teardownIntentListener() {
if (mIntentListener != null) {
mContext.unregisterReceiver(mIntentListener);
mIntentListener = null;
}
}
}
答案 3 :(得分:1)
另一种方法是使用文件系统或sqlite数据库,例如
在AppWidgetProvider中:
File file = new File(context.getCacheDir(), "filename that service also knows");
writeFile(file, "my content"); // impl. not shown; uses BufferedWriter.java
在RemoteViewsService中:
File file = new File(context.getCacheDir(), "filename that service also knows");
if (file.exists()) {
// handle params contained within file
file.delete(); // clear for next run
}