本文翻译整理自:
http://developer.android.com/guide/topics/appwidgets/index.html#implementing_collections
3.3、AppWidgetProvider class for app widgets with collections
app widgets with collections像一般的app widget一样,你主要代码应该在AppWidgetProvider的onUpdate()方法中。
主要区别在于,在 app widgets with collections中,你必须对RemoteViews调用setRemoteAdapter方法。这个函数能告诉collection view能在哪里取得它的数据.。RemoteViewsService必须能返回一个RemoteViewsFactory对象。
当你调用setRemoteAdapter()方法的时候, 你必须传递一个用于启动你的RemoteViewsService的intent和一个App Widget ID用于说明对哪个app widget进行更新.
For example, here's how the StackView Widget sample implements the onUpdate() callback method to set the RemoteViewsService as the remote adapter for the app widget collection:
示例4
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // update each of the app widgets with the remote adapter for (int i = 0; i < appWidgetIds.length; ++i) { // Set up the intent that starts the StackViewService, which will // provide the views for this collection. Intent intent = new Intent(context, StackWidgetService.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.widget_layout); // 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.stack_view, intent); // The empty view is displayed when the collection has no items. // It should be in the same layout used to instantiate the RemoteViews // object above. rv.setEmptyView(R.id.stack_view, R.id.empty_view); // // Do additional processing specific to this app widget... // appWidgetManager.updateAppWidget(appWidgetIds[i], rv); } super.onUpdate(context, appWidgetManager, appWidgetIds); }
3.4、RemoteViewsService class
如上面描述那样, 你的RemoteViewsService应该编写一个RemoteViewsFactory,以提供数据项的remote collection view.
具体来说,您需要执行这些步骤:
第一、新建一个RemoteViewsService的子类. RemoteViewsService是个service,通过它remote adapter可以请求并获得RemoteViews.
第二,在你RemoteViewsService的子类中, 添加一个实现了RemoteViewsFactory接口的方法.
RemoteViewsFactory
为collection view (such as ListView, GridView, and so on)和collection view的数据提供了适配接口。
在RemoteViewsFactory中,你要负责为数据集的每个数据项提供一个RemoteViews对象. RemoteViewsFactory相等于Adapter的一个精简版本。
编写RemoteViewsService的主要工作集中在RemoteViewsFactory,关于次将在下文进行介绍
3.5、RemoteViewsFactory interface
你的RemoteViewsFactory需要为app widget提供数据集的每个数据项其对应的RemoteViews对象
为此, 你需要用app widget数据项的View布局文件和数据集的数据项来合成RemoteViews对象。数据源可以为任何形式,可以是一个简单的数组,也来自于数据库。在StackView Widget示例程序中, 数据源是个WidgetItems数组. RemoteViewsFactory的主要功能就是把数据变成 RemoteViews.
在RemoteViewsFactory中,你主要需要实现
onCreate()
和getViewAt()
这两个方法 。
当RemoteViewsFactory首次被创建时,onCreate()方法将被调用.
在该函数中,你应该做些初始工作,比如建立针对你的数据源的连接或光标。比如, 在StackView Widget示例程序中的onCreate()方法中,
就初始了一个WidgetItem对象数组. 当你app widget活动的时候, 系统可以通过数组索引号来访问这些WidgetItem对象。
这些WidgetItem对象中所包含的文本内容也就将被显示。
以下是StackView Widget示例程序的RemoteViewsFactory中关于onCreate()方法的部分代码:
示例5
class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory { private static final int mCount = 10; private List<WidgetItem> mWidgetItems = new ArrayList<WidgetItem>(); private Context mContext; private int mAppWidgetId; public StackRemoteViewsFactory(Context context, Intent intent) { mContext = context; mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); } public void onCreate() { // In onCreate() you setup any connections / cursors to your data source. Heavy lifting, // for example downloading or creating content etc, should be deferred to onDataSetChanged() // or getViewAt(). Taking more than 20 seconds in this call will result in an ANR. for (int i = 0; i < mCount; i++) { mWidgetItems.add(new WidgetItem(i + "!")); } ... } ...
RemoteViewsFactory的getViewAt()方法将返回与数据集的指定位置的数据项相对应的RemoteViews对象.下面是
StackView Widget示例程序中,
关于
RemoteViewsFactory
的部分代码。
示例6
public RemoteViews getViewAt(int position) { // Construct a remote views item based on the app widget item XML file, // and set the text based on the position. RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item); rv.setTextViewText(R.id.widget_item, mWidgetItems.get(position).text); ... // Return the remote views object. return rv; }