Widgets高级篇(二)

来源:互联网 发布:技校软件开发 编辑:程序博客网 时间:2024/04/29 17:14
本文翻译整理自: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;
}