zoukankan      html  css  js  c++  java
  • android 中 AppWidget 的 ListView 的实现

    3.0 以后系统直接支持了ListView. 关于ListView 的国内资料匮乏,大多数例子都是转来转去。由于初学android, 鄙人在搜索资料的时候遇到了不少麻烦~很是郁闷和苦恼~深感国内学习氛围确实怪异,学习方式需要改变。应该多去查看官方文档。。。。

    话不多说,现在开始listView 实现:

    这是文档列出的支持的布局和widget控件:

    A RemoteViews object (and, consequently, an App Widget) can support the following layout classes:

    And the following widget classes:

    Descendants of these classes are not supported

    其中有ListView和 GridView 等控件。

    android 中实现 appWidget 有自己的一套机制:

    1.  widget 的支持,AppWidgetProvider 类的实现。

    覆盖在 AppWidgetProvider 的 OnReceive() 函数,从android的源码中可以知道,AppWidgetProvider 的 OnUpdate() , OnEnable(), OnDelete() 等方法都是从 OnReceive() 方法中分配进去的。即所有的广播先通过OnReceive()函数,再分配到OnUpdate()等函数去。

    public void onReceive(Context context, Intent intent) {
        // Protect against rogue update broadcasts (not really a security issue,
        // just filter bad broacasts out so subclasses are less likely to crash).
        String action = intent.getAction();
        if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
            Bundle extras = intent.getExtras();
            if (extras != null) {
                int[] appWidgetIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
                if (appWidgetIds != null && appWidgetIds.length > 0) {
                    this.onUpdate(context, AppWidgetManager.getInstance(context), appWidgetIds);
                }
            }
        }
        else if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) {
            Bundle extras = intent.getExtras();
            if (extras != null && extras.containsKey(AppWidgetManager.EXTRA_APPWIDGET_ID)) {
                final int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
                this.onDeleted(context, new int[] { appWidgetId });
            }
        }
        else if (AppWidgetManager.ACTION_APPWIDGET_ENABLED.equals(action)) {
            this.onEnabled(context);
        }
        else if (AppWidgetManager.ACTION_APPWIDGET_DISABLED.equals(action)) {
            this.onDisabled(context);
        }
    }
    // END_INCLUDE(onReceive)

     

    注意到:

    String action = intent.getAction();

    这里 intent 先获取 action, 通过action 来获取到广播并区分类型,所以自己定义 action 通过 PendingIntent 来实现各种跳转~

    到这里先摆下基础的文件吧:

    这里需要注意到的是:android中的xml 文件不能有大写字母。区分单词用最好用  _  符号。否则找不到文件名。

    provider_info 文件,提供 appWidget 的一些基本控制信息。

    <?xml version="1.0" encoding="utf-8"?>
    <appwidget-provider
      android:minWidth = "294dp"
      android:minHeight = "367dp"
      android:updatePeriodMillis = "1000"
      android:initialLayout = "@layout/listview"
      android:background="#0000ff"
      >
       
    </appwidget-provider>

    listview 文件: ListView 控件就在内部:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
      android:layout_width="294dp"
      android:layout_height="400dp">
      <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="360dp"
        android:minHeight="100dp"
        android:id="@+id/listviewWrapper"
        >
          <ListView
            android:layout_height = "360dp"
            android:layout_width = "294dp"
            android:background="#000000"
            android:id = "@+id/myListView"
          />
      </LinearLayout>
      <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/listviewWrapper"
         
        android:layout_alignParentLeft="true"
        android:id="@+id/refresh"
        android:text="refresh"
        >
      </Button>
    </RelativeLayout>

    下面是list_item 文件:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent">
      <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:textColor="#ff0000"
        android:layout_marginTop="5px"
        android:layout_marginBottom="5px"
        android:paddingBottom="25px"
        android:paddingTop="5px"
        android:textSize="60px"
        android:id="@+id/item"
      />
      <ImageView
        android:id="@+id/imageItem"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignRight="@id/item"
        />
    </RelativeLayout>

     list 的 item 中也可以添加 ImageView 等appWidget 支持的控件。

    这是manifest 问件:

    <?xml version="1.0" encoding="utf-8"?>
        package="com.zgc.AppWidget6"
        android:versionCode="1"
        android:versionName="1.0" >
     
        <uses-sdk android:minSdkVersion="15" />
     
        <application
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name" >
            <receiver android:name=".MyWidgetProvider">
                <meta-data android:name="android.appwidget.provider"
                    android:resource="@xml/provider_info" >
                </meta-data>
                <intent-filter >
                    <action android:name="android.appwidget.action.APPWIDGET_UPDATE"></action>   
                </intent-filter>
            </receiver>
             
            <service android:name=".MyWidgetService"
                android:permission="android.permission.BIND_REMOTEVIEWS"
                android:exported="false" ></service>
             
         </application>
          
        <uses-permission android:name="android.permission.INTERNET"></uses-permission>
    </manifest>

    其中 service 提供 name 是 MyWidgetService ,他是继承RemoteViewsService 类。是我们需要为 远程 ListView 提供 数据源的服务。

    RemoteViewsService的是个服务。其中:

    public RemoteViewsFactory onGetViewFactory(Intent intent) {
          return new ListRemoteViewsFactory(this.getApplicationContext(), intent);
      }
    ListRemoteViewsFactory 这里就充当 ListView 的数据源。

    就好比在activity 中使用ListView 一样。也需要通过AdapterView 来为ListView 提供数据源。不过AdatperView中提供了每一Item的方法。

    具体逻辑如图:

        

    下面是 service 的源代码:

    public class MyWidgetService  extends RemoteViewsService {
        @Override
        public RemoteViewsFactory onGetViewFactory(Intent intent) {
            return new ListRemoteViewsFactory(this.getApplicationContext(), intent);
        }
     
        @Override
        public void onCreate() {
            // TODO Auto-generated method stub
            System.out.println("service in onCreate");
            super.onCreate();
        }
         
        @Override
        public void onDestroy() {
            // TODO Auto-generated method stub
            System.out.println("service in onDestory");
            super.onDestroy();
        }
     
        @Override
        public boolean onUnbind(Intent intent) {
            // TODO Auto-generated method stub
            System.out.println("service in onUnbind");
            return super.onUnbind(intent);
        }
     
        @Override
        public void onRebind(Intent intent) {
            // TODO Auto-generated method stub
            System.out.println("service in onRebind");
            super.onRebind(intent);
        }
     
        @Override
        public void onStart(Intent intent, int startId) {
            // TODO Auto-generated method stub
            System.out.println("service in onStart");
            super.onStart(intent, startId);
        }
     
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            // TODO Auto-generated method stub
            return super.onStartCommand(intent, flags, startId);
        }
    }<br><br>
    class ListRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
         
        private static int mCount = 0;
        private List<WidgetItem> mWidgetItems = new ArrayList<WidgetItem>();
        private List<String> mWidgetItemsAttr= new ArrayList<String>();
        private Context mContext;
        private int mAppWidgetId;
        private String url = "http://10.40.73.77/php/getData.php";
         
        public static int whichPage = 0;
        public static int mainPageId = -1;
        public static int secPageId = -1;
        public static final int mainPage = 0;
        public static final int secPage = 1;
        public static List<Integer> checkPos = new ArrayList<Integer>();
        //public static int[] checkPosArr = new int[100];
         
         
        public ListRemoteViewsFactory(Context context, Intent intent){
            mContext = context;
            mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                    AppWidgetManager.INVALID_APPWIDGET_ID);
        }
         
        @Override
        public void onCreate() {
            System.out.println("onCreate in factory");
            // TODO Auto-generated method stub
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
     
        @Override
        public int getCount() {
            // TODO Auto-generated method stub
            if(whichPage == mainPage){
                mCount = mWidgetItems.size();
            }
            else if(whichPage == secPage){
                mCount = mWidgetItemsAttr.size();
            }
             
            return mCount;
        }
     
        @Override
        public long getItemId(int position) {
            // TODO Auto-generated method stub
            return position;
        }
     
        @Override
        public RemoteViews getLoadingView() {
            // TODO Auto-generated method stub
            System.out.println("getLoadingView");
            return null;
        }
     
        @Override
        public RemoteViews getViewAt(int position) {
            System.out.println("getViewAt");
            // TODO Auto-generated method stub
            RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.list_item);
            switch(whichPage){
            case mainPage :
                if(-1 == mainPageId){ //refresh main page
                    System.out.println("getViewAt mainPage refresh");
                     
                    rv.setTextViewText(R.id.item, mWidgetItems.get(position).text);
                    Bundle extras = new Bundle();
                    extras.putInt("page", 0);
                    extras.putInt(MyWidgetProvider.EXTRA_ITEM, position);
                    extras.putString("name", mWidgetItems.get(position).text);
                    Intent fillInIntent = new Intent();
                fillInIntent.putExtras(extras);
                rv.setOnClickFillInIntent(R.id.item, fillInIntent);
                }
                else{ //refresh to secPage list content
                    System.out.println("getViewAt mainPage item click");
                     
                    mainPageId = -1;
                }
                break;
                 
            case secPage:
                if(-1 == secPageId){ //refresh when click back button, but I only have one home button
                    //refresh second list page
                    System.out.println("getViewAt secPage refresh");
                     
                    rv.setTextViewText(R.id.item, mWidgetItemsAttr.get(position));
                    rv.setImageViewResource(R.id.imageItem, R.drawable.checkbox);
                     
                    Bundle extras = new Bundle();
                    extras.putInt("page", 1);
                    extras.putInt(MyWidgetProvider.EXTRA_ITEM, position);
                    Intent fillInIntent = new Intent();
                    fillInIntent.putExtras(extras);
                    rv.setOnClickFillInIntent(R.id.item, fillInIntent);
                    rv.setOnClickFillInIntent(R.id.imageItem, fillInIntent);
                }
                else{ //change positon
                    rv.setTextViewText(R.id.item, mWidgetItemsAttr.get(position));
                     
                    if(-1 != checkPos.indexOf(position)){
                        //change list item picture to be checked
                        rv.setImageViewResource(R.id.imageItem, R.drawable.checkedbox);
                    }
                    else{
                        rv.setImageViewResource(R.id.imageItem, R.drawable.checkbox);
                    }
                     
                    //每一个 item 都需要从新赋值。否则会出错!!具体原因没有查明
                    Bundle extras = new Bundle();
                    extras.putInt("page", 1);
                    extras.putInt(MyWidgetProvider.EXTRA_ITEM, position);
                    Intent fillInIntent = new Intent();
                    fillInIntent.putExtras(extras);
                    rv.setOnClickFillInIntent(R.id.item, fillInIntent);
                    rv.setOnClickFillInIntent(R.id.imageItem, fillInIntent);
                }
                break;
                default: ;
            }
             
            return rv;
        }
     
        @Override
        public int getViewTypeCount() {
            // TODO Auto-generated method stub
            return 1;
        }
     
        @Override
        public boolean hasStableIds() {
            // TODO Auto-generated method stub
            return true;
        }
     
     
        @Override
        public void onDataSetChanged() {
            // TODO Auto-generated method stub
            System.out.println("onDataSetChanged");
     
                //this func is get data
            mWidgetItems.clear();
             
             
            switch(whichPage){
            case mainPage :
                System.out.println("onDataSetChanged_mainPage");
                if(-1 == mainPageId){ //refresh main page
                     
                    try{
                        URL reqURL = new URL(url);
                        BufferedReader br = new BufferedReader(new InputStreamReader(reqURL.openStream(), "gbk"));
                        StringBuffer sb = new StringBuffer();
                        String line;
                        while(null != (line = br.readLine())){
                            sb.append(line);
                        }  
                        br.close();
                 
                        ArrayList <Map<String, Object>> mList= new ArrayList<Map<String, Object>>();
                            
                        JSONArray arr_json = new JSONArray(sb.toString());
                        for(int i = 0, len = arr_json.length(); i < len; i++){
                               String strName = arr_json.getJSONObject(i).getString("name");
                               String strUrl = arr_json.getJSONObject(i).getString("url");
                               int id = arr_json.getJSONObject(i).getInt("id");
                                
                               Map<String, Object> map = new HashMap<String, Object>();
                                
                               mWidgetItems.add(new WidgetItem(strName, id));
                                
                               map.put("name", strName);
                               map.put("url", strUrl);
                               mList.add(map);            
                        }
                             
                                mCount = mWidgetItems.size();
                        }catch(Exception e){
                            Toast.makeText(mContext, "can't connect server", Toast.LENGTH_LONG).show();
                        }
                }
                else{ //
                    System.out.println("onDataSetChanged_mainPage else");
                     
                    WidgetItem item = mWidgetItems.get(mainPageId);
                     
                }
                 
                System.out.println("onDataSetChanged_-1");
                break;
                 
            case secPage: //here can get more info from server, but no need to get more infomation, 
                if(-1 == secPageId){
                    mWidgetItemsAttr.clear();
                     
                    System.out.println("onDataSetChanged_secPage -1");
                    mWidgetItemsAttr.add("zhang");
                    mWidgetItemsAttr.add("gui");
                    mWidgetItemsAttr.add("chuang");
                    mWidgetItemsAttr.add("hui");
                    mWidgetItemsAttr.add("cong");
                    mWidgetItemsAttr.add("gui");
                    mWidgetItemsAttr.add("chuang");
                    mWidgetItemsAttr.add("hui");
                    mWidgetItemsAttr.add("cong");
                    mWidgetItemsAttr.add("gui");
                    mWidgetItemsAttr.add("chuang");
                    mWidgetItemsAttr.add("hui");
                    mWidgetItemsAttr.add("cong");
                    mWidgetItemsAttr.add("cong");
                }
                else{
                    System.out.println("onDataSetChanged_secPage else");
                }
                break;
                 
                default: return ;
            }
             
     
             
        }
     
        @Override
        public void onDestroy() {
            System.out.println("onDestory in factory");
            // TODO Auto-generated method stub
            mWidgetItems.clear();  
        }
     
    }

      

    <br>
    <br>注意到几个方法:<br>public void onDataSetChanged(){.....}<br>public RemoteViews getViewAt(int position) {....}<br>public int getCount() {....}<br><br>onDateSetChanged(){...} 方法在你使用的 MyWidgetProvider 的 onReceive() 和 onUpdate() 方法中调用
    AppWidgetManager 的实例的方法: mgr.notifyAppWidgetViewDataChanged(appIds, R.id.myListView); 来更新要求更新数据源:<br>首先就会调用 :
    onDataSetChanged(){.....}
    然后在调用 getViewAt(int position){....}<br>其中getViewAt 的参数 position 就是你的ListView中每一项 item 的位置。从 0 计数。<br>其中你必须 override 的 getCount()方法是返回你的ListView item 的总数。这个自己必须返回自己的数据才能让getViewAt的postion能够计数。<br><br>你获取数据的方式比如http从服务器获取数据的话,就需要放在onDateSetChagged()方法里。<br>当然 public RemoteViews getLoadingView(){...} 也可以。不过要注意放回的是RemoteViews 就说明这是要更新界面的,这个函数的作用就是在你更新界面的时候如果耗时就会显示 正在加载... 的默认字样,但是你可以更改这个界面。需要返回一个 RemoteViews 类型。其中你可以使用RemoteViews 去切换自己定义的 Layout 。<br><br>关于 remoteViews 的实例的方法:
    rv.setOnClickFillInIntent(R.id.item, fillInIntent);
    在下面会解释。<br><br><br>下面是provider:
    public class MyWidgetProvider extends AppWidgetProvider{
        public static final String TOAST_ACTION = "com.zgc.listwidget.TOAST_ACTION";
        public static final String EXTRA_ITEM = "com.zgc.listwidget.EXTRA_ITEM";
        public static final String TO_SITE = "com.zgc.listwidget.TO_SITE";
        public static final String SITE = "com.zgc.listwidget.SITE";
        public static final String BACK_HOME = "com.zgc.listwidget.BACK_HOME";
        public static String PicName = "";
        public static final String REFRESH = "com.zgc.listwidget.REFRESH";
         
        public static final String ITEM = "com.zgc.AppWidget6.ITEM";
         
         
     
        @Override
        public IBinder peekService(Context myContext, Intent service) {
            // TODO Auto-generated method stub
            System.out.println("peekService in provider");
            return super.peekService(myContext, service);
        }
     
        @Override
        public void onDeleted(Context context, int[] appWidgetIds) {
            // TODO Auto-generated method stub
            System.out.println("onDeleted in Provider");
            super.onDeleted(context, appWidgetIds);
        }
     
        @Override
        public void onDisabled(Context context) {
            // TODO Auto-generated method stub
            System.out.println("onDisabled in Provider");
            super.onDisabled(context);
        }
     
        @Override
        public void onEnabled(Context context) {
            // TODO Auto-generated method stub
            System.out.println("onEnabled in Provider");
            super.onEnabled(context);
        }
     
        @Override
        public void onReceive(Context context, Intent intent) {
            // TODO Auto-generated method stub
            AppWidgetManager mgr = AppWidgetManager.getInstance(context);
            ComponentName cmpName = new ComponentName(context, MyWidgetProvider.class);
             
            if (intent.getAction().equals(ITEM)) {
                System.out.println("item action");
                int pageNum = intent.getIntExtra("page", 1);
                int itemPos = intent.getIntExtra(EXTRA_ITEM, 0);
                if(0 == pageNum){
                    System.out.println("item action 0 page");
                    ListRemoteViewsFactory.secPageId = -1;
                    ListRemoteViewsFactory.whichPage = ListRemoteViewsFactory.secPage;
                     
                    int[] appIds = mgr.getAppWidgetIds(cmpName);
                    mgr.notifyAppWidgetViewDataChanged(appIds, R.id.myListView);
                     
                    //change refresh to commit button ,here no need to reload listview
                    RemoteViews rv2 = new RemoteViews(context.getPackageName(), R.layout.listview);
                    rv2.setTextViewText(R.id.refresh, "commit");
                    Intent commitIntent = new Intent(context, MyWidgetProvider.class);
                    commitIntent.setData(Uri.parse(commitIntent.toUri(Intent.URI_INTENT_SCHEME)));
                    commitIntent.setAction(SITE);
                    PendingIntent commitPendingIntent = PendingIntent.getBroadcast(context, 0,
                            commitIntent, PendingIntent.FLAG_UPDATE_CURRENT);
                    rv2.setOnClickPendingIntent(R.id.refresh, commitPendingIntent);
                     
                    mgr.updateAppWidget(appIds, rv2);
                     
                }
                else if(1 == pageNum){
                    System.out.println("item action 1 page");
                    ListRemoteViewsFactory.secPageId = itemPos;
                     
                    if(-1 == ListRemoteViewsFactory.checkPos.indexOf(itemPos)){
                        ListRemoteViewsFactory.checkPos.add(itemPos);
                    }
                    else{
                        ListRemoteViewsFactory.checkPos.remove(ListRemoteViewsFactory.checkPos.indexOf(itemPos));
                    }
     
                    int[] appIds = mgr.getAppWidgetIds(cmpName);
                    mgr.notifyAppWidgetViewDataChanged(appIds, R.id.myListView);
                }
     
            }
            else if(intent.getAction().equals(SITE)){
                System.out.println("in receive commit SITE action");
                RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.img);
                int id = R.drawable.uliuli;
                if(PicName.equals("google")){
                    id = R.drawable.uliuli;
                }
                else if(PicName.equals("douban")){
                    id = R.drawable.uliuli;
                }
                rv.setImageViewResource(R.id.displayImage, id);
                 
                Intent homeIntent = new Intent(context, MyWidgetProvider.class);
                homeIntent.setAction(BACK_HOME);
                //homeIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
                homeIntent.setData(Uri.parse(homeIntent.toUri(Intent.URI_INTENT_SCHEME)));
                PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, homeIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT);
                rv.setOnClickPendingIntent(R.id.backHome, pendingIntent);
                 
                mgr.updateAppWidget(cmpName, rv);
                //Toast.makeText(context, "Touched view zhang", Toast.LENGTH_SHORT).show();
            }
            else if(intent.getAction().equals(BACK_HOME)){
                System.out.println("back_home ");
            
                int[] appWidgetIds = mgr.getAppWidgetIds(cmpName);
                 
                //mgr.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.myListView);
                     
                Intent serviceIntent = new Intent(context, MyWidgetService.class);  //
                //intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
                serviceIntent.setData(Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME)));
                RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.listview);
                rv.setRemoteAdapter(R.id.myListView, serviceIntent);
                     
                Intent toastIntent = new Intent(context, MyWidgetProvider.class);
                toastIntent.setAction(MyWidgetProvider.ITEM);
     
                intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
                PendingIntent toastPendingIntent = PendingIntent.getBroadcast(context, 0, toastIntent,
                PendingIntent.FLAG_UPDATE_CURRENT);
                rv.setPendingIntentTemplate(R.id.myListView, toastPendingIntent);
                     
                mgr.updateAppWidget(appWidgetIds, rv);
                 
                Intent refreshIntent = new Intent(context, MyWidgetProvider.class);
                refreshIntent.setAction(REFRESH);
                PendingIntent refreshPendingIntent = PendingIntent.getBroadcast(context, 0,
                        refreshIntent, 0);
                rv.setOnClickPendingIntent(R.id.refresh, refreshPendingIntent);
                 
                ListRemoteViewsFactory.whichPage = ListRemoteViewsFactory.mainPage;
                ListRemoteViewsFactory.mainPageId = -1;
                mgr.updateAppWidget(cmpName, rv);
                mgr.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.myListView);
                System.out.println("zhanggui");
                //Toast.makeText(context, "Touched view back home", Toast.LENGTH_SHORT).show();
            }
            else if(intent.getAction().equals(REFRESH)){
                System.out.println("refresh button begin");
                int[] appWidgetIds = mgr.getAppWidgetIds(cmpName);
                mgr.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.myListView);
                System.out.println("refresh button end");
            }
            super.onReceive(context, intent);
        }
     
        @Override
        public void onUpdate(Context context, AppWidgetManager appWidgetManager,
                int[] appWidgetIds) {
            System.out.println("onUpdate");
            // TODO Auto-generated method stub
             
            for(int i = 0; i < appWidgetIds.length; i++){
                Intent intent = new Intent(context, MyWidgetService.class);
                intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
                // When intents are compared, the extras are ignored, so we need to embed the extras
                // into the data so that the extras will not be ignored.
                intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
                RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.listview);
                rv.setRemoteAdapter(R.id.myListView, intent);
                //rv.setEmptyView(R.id.myListView, R.id.empty);
                 
                Intent refreshIntent = new Intent(context, MyWidgetProvider.class);
                refreshIntent.setAction(REFRESH);
                PendingIntent refreshPendingIntent = PendingIntent.getBroadcast(context, 0,
                        refreshIntent, 0);
                rv.setOnClickPendingIntent(R.id.refresh, refreshPendingIntent);
     
                Intent toastIntent = new Intent(context, MyWidgetProvider.class);
                toastIntent.setAction(MyWidgetProvider.ITEM);
                //toastIntent.putExtra("page", 0); // main page
                intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
                PendingIntent toastPendingIntent = PendingIntent.getBroadcast(context, 0, toastIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT);
                rv.setPendingIntentTemplate(R.id.myListView, toastPendingIntent);
     
                appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
            }
            super.onUpdate(context, appWidgetManager, appWidgetIds);
        }
     
     
    }

    首先看onUpdate() 函数,默认是从这里先进去的:

    申明intent 后使用:

    intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));

    用:这是为了让 intent 能够带上 extras 数据一起传递,否则在intent的比较的过程中会被忽略掉。这里的比较应该是在同一个代码块中有多个intent的时候会发生比较吧(猜测:因为当一条逻辑执行路径上代码块中只有一个Intent发送的时候能够带数据(不适用intent.setData函数),但是有多个Intent的话不行)

    PendingIntent 的使用不再解释。不过这里的 remoteView 实例使用:

    rv.setPendingIntentTemplate(R.id.myListView, toastPendingIntent);

    listView 使用 setPendingIntentTemplate 方法,当你点击 ListView 中的任何一个item 时都会发送 toastPendingIntent ,在我们的 service 中的getViewAt() 方法中,为每一个item 都设置了一个 intent :

    rv.setOnClickFillInIntent(R.id.item, fillInIntent);

    其中 remoteViews 的setOnClickFillInIntent() 是将 fillIntent 合并到 toastPendingIntent 中去。就是两个 intent 合并了。

    具体的合并方法是Intent中的fillIn(..) 方法:

    Intent A : {data="foo", categories="bar"}

    Intent B : {action="gotit", data-type="some/thing", categories="one","two"}.

    调用 fillIn(): A.fillIn(B, Intent.FILL_IN_DATA)

    结果:  A : {action="gotit", data-type="some/thing", categories="bar"}.

     

    注意到 action 还是你在 onUpdate()中设置的 action,当然你也可以在 item 中的 fillInIntent 设置action.但是不好。

    这里可以在每个 item 的 fillInIntent 中 使用 putExtras() 方法让Intent 带每个item 的 位置号码 来区分每个 item.

    机制基本上已经说完,还有一点就是:

    RemoteViewsService 中每次获取数据都会重新创建 service 和 销毁 service ,但是 RemoteViewsService.RemoteViewsFactory

    的销毁则是在 机器上把 appWidget 删除后发生。就好像 RemoteViewsService.RemoteViewsFactory 是个数据库。你每次去访问这个数据源都会创建 一个 RemoteViewsService 然后销毁。这个源于我android学习1月,也不清楚内部机制。没仔细研究。等研究了再发文表上。

    还有 AppWidgetProvider 类的实例是每发送一次 intent (即每一次 boardcast) 就新建一次,所以如果需要做 flag 来表示按钮是否check的话,最好就先声明为 static 类型或者放到其他类中。

    其余的就是自己逻辑的实现:

    我这里实现了 两个 ListView 的数据加载(通过http从服务器获取数据)和点入每条item进入另外的页面(这里也是在listView上从新加载数据,但是可以区分每个Item。也可以自己加载其他的layout)。还可以实现回到第一个加载的页面。其实可以做到回到上一个页面。

    原文:http://www.cnblogs.com/debugman/archive/2012/06/18/android.html

  • 相关阅读:
    WPF之窗体说明
    WPF之基本概念
    WPF学习之button
    写一本”错误百出”的C语言学习教程(一)
    JSP的工作原理-还是没理解--多看点再写。
    Java将中文转换成unicode字符。
    postgres 导出数据到csv 文件
    python小试身手-文件重命名,文件复制和压缩(.gz)
    python 环境安装 mark下。
    JRE,JVM,JDK的区别---粘自百度知道、
  • 原文地址:https://www.cnblogs.com/veins/p/3840365.html
Copyright © 2011-2022 走看看