Android Launcher开发(一)LiveFolder(实时文件夹) 完全解析

news/2024/7/7 20:35:39

实时文件夹概述:

      实时文件夹是在SDK1.5中引入的,支持开发人员在设备的默认打开屏幕(我们将其称为设备的主页)上公开 ContentProvider,如联系人信息、笔记和媒体。将ContentProvider(比如Android的 contactsContentProvider)在主页上公开为活动文件夹之后,在联系人数据库中添加、删除或修改联系人时,此实时文件夹能够刷新自身所包含的内容。


       Android中的实时文件夹对ContentProvider的作用就相当于RSS阅读器对发布网站的作用。ContentProvider也是类似于根据URI提供信息的网站。随着网站的迅速增加,每个网站都会以独特的方式发布自己的信息,这就需要集中多个网站的信息,以便用户可以通过单一阅读器了解最新发展动态。为此,RSS应运而生。RSS强制在不同的信息集之间提供一种通用的使用模式。有了通用模式,你只需设计一次阅读器,就可以使用它阅读任何内容,只要该内容具有统一的结构即可。

    实时文件夹在概念上也没有什么不同。就像 RSS阅读器为所发布的网站内容提桶通用的接口一样,实时文件夹也为Android中的 ContentProvider定义一种通用接口。只要 ContentProvider遵守此协议,Android就能够在设备的主页上创建活动文件夹图标来表示该 ContentProvider。当用户单击此活动文件夹图标时,系统将联系 ContentProvider。ContentProvider 应该会返回一个游标。根据活动文件夹契约,此游标必须具有一组预定义的列。此游标通过  ListView 或 GridView直观地显示出来。

   android实时文件夹   android LiveFolder, 为什么说它是实时的,因为它可以根据我们后台数据库的变化更新自身 更新UI 这样无论什么时候显示的内容都是最新的。 比如 我们删除了一条联系人信息,我们的 Live Foler马上也会 更新。是马上 而且你也不用做任何操作 它自己会更新


用户如何使用活动文件夹:

(1) 打开android模拟器 来到主页 (默认屏幕)

(2) 转到主页的上下文菜单。通过在主页的空白处进行长单击(按住不撒手 大约2秒钟),就可以看到上下文菜单了。

(3) 找到一个名为 Folders(中文名就叫文件夹) 的上下文菜单选项,单击可以查看可能可用的活动文件夹。

(4) 从列表中选择并单击希望在主页上公开的活动文件夹名称。这会在主页上创建一个图标来表示所选的活动文件夹。

(5) 单击在第4步中设置的活动文件夹图标,调出 ListView或GridView中的信息(该活动文件夹表示的数据)行。

(6) 单击一行以调用知道如何显示该行数据的应用程序。

(7) 使用该应用程序显示的更多菜单选项查看或操作目标选项。也可以使用应用程序的菜单选项创建它支持的任何新项。

(8) 请注意,活动文件夹显示区域会自动反应对一个或多个项所做的更改。


Eg:



通过代码构建实时文件夹(LiveFolder):


要构建活动文件夹,需要两样东西:一个活动和一个专门的ContentProvider。Android使用此活动的 “ 标签” 来填充可用活动文件夹列表。Android还调用此活动来获得一个URI,这个URI将被调用来显示一组行。

  活动提供的URI 应该指向负责返回行的专门的ContentProvider。该ContentProvider通过一个定义良好的游标返回这些行。我们要求游标 “定义良好”, 因为游标应该具有一组已知的预定义列名称。


Eg:

1. AndroidManifest.xml

[java]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="xiaohang.zhimeng" android:versionCode="1" android:versionName="1.0">  
  4.     <uses-sdk android:minSdkVersion="10" />  
  5.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
  6.         <activity android:name=".SimpleActivity" android:label="@string/app_name">  
  7.             <intent-filter>  
  8.                 <action android:name="android.intent.action.MAIN" />  
  9.                 <category android:name="android.intent.category.LAUNCHER" />  
  10.             </intent-filter>  
  11.         </activity>  
  12.         <!-- LIVE FOLDERS -->  
  13.         <activity android:name=".AllContactsLiveFolderCreatorActivity"  
  14.             android:label="My live folder" android:icon="@drawable/contacts">  
  15.             <intent-filter>  
  16.                 <span style="color:#FF0000;"><action android:name="android.intent.action.CREATE_LIVE_FOLDER" /></span>  
  17.                 <category android:name="android.intent.category.DEFAULT" />  
  18.             </intent-filter>  
  19.         </activity>  
  20.         <provider android:authorities="com.ai.livefolders.contacts"  
  21.             android:multiprocess="true" android:name=".MyContactsProvider" />  
  22.     </application>  
  23.     <span style="color:#FF0000;"><uses-permission android:name="android.permission.READ_CONTACTS" /></span>  
  24. </manifest>  

2. 根据活动文件夹协议,CREATE_LIVE_FOLDER Intent 允许主页的上下文菜单将
AllContactsLiveFolderCreatorActivity 显示为一个标题为 “My live foler” 的选项。单击此菜单选项将在主页上创建一个图标。AllContactsLiveFolderCreatorActivity 负责定义此图标,其中将包含一个图像和一个标签。在本例子中,AllContactsLiveFolderCreatorActivity 中的代码将此标签指定为 Contacts LF。下面让我们看看创建活动文件夹的类AllContactsLiveFolderCreatorActivity:


[java]  view plain copy
  1. package xiaohang.zhimeng;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.Intent;  
  5. import android.net.Uri;  
  6. import android.os.Bundle;  
  7. import android.provider.LiveFolders;  
  8.   
  9. public class AllContactsLiveFolderCreatorActivity extends Activity {  
  10.   
  11.     @Override  
  12.     protected void onCreate(Bundle savedInstanceState) {  
  13.         super.onCreate(savedInstanceState);  
  14.   
  15.         final Intent intent = getIntent();  
  16.         final String action = intent.getAction();  
  17.         System.out.println("action is " + action);  
  18.         if (LiveFolders.ACTION_CREATE_LIVE_FOLDER.equals(action)) {  
  19.             // 设置本Activity返回的结果  
  20.             setResult(  
  21.                     RESULT_OK,  
  22.                     createLiveFolder(MyContactsProvider.CONTACTS_URI,  
  23.                             "Contacts LF", R.drawable.contacts));  
  24.         } else {  
  25.             setResult(RESULT_CANCELED);  
  26.         }  
  27.         finish();  
  28.     }  
  29.   
  30.     private Intent createLiveFolder(Uri uri, String name, int icon) {  
  31.         final Intent intent = new Intent();  
  32.         intent.setData(uri);  
  33.         // 设置LiveFolder 的Name(这个名字是显示在手机的主页上的)  
  34.         intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME, name);  
  35.         // 设置LiveFolder 的图标  
  36.         intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_ICON,  
  37.                 Intent.ShortcutIconResource.fromContext(this, icon));  
  38.         // 指定LiveFolder 显示的模式 这里用List以列表的形式显示  
  39.         intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_DISPLAY_MODE,  
  40.                 LiveFolders.DISPLAY_MODE_LIST);  
  41.         return intent;  
  42.     }  
  43. }  


AllContactsLiveFolderCreatorActivity 类只有一个功能:担当活动文件夹的生成程序或创建程序。可以将它视为活动文件夹的模板。每次单击此活动(通过主页上下文菜单的Folers选项)时,它都会在主页上生成一个活动文件夹。此活动告诉调用方(在这个例子中为主页或LiveFolder框架) 活动文件夹名称、为活动文件夹图标使用的图像、提供可用数据的 URI,以及显示模式 (列表或网格)。然后,活动文件夹框架负责在主页上创建活动文件夹的图标。


createLiveFoler() 方法主要设置调用它的Intent的值。当此 Intent返回到调用方时,调用方将知道以下信息。

  活动文件夹的名称
   活动文件夹所使用的图标
   显示模式:列表或网格
   数据或为数据调用的内容URI

3.MyContactsProvider: 当用户单击活动文件夹的图标时,系统将调用 URI 来检索数据。此 URI 所标识的 ContentProvider提供了标准化的游标:

[java]  view plain copy
  1. package xiaohang.zhimeng;  
  2.   
  3. import android.content.ContentProvider;  
  4. import android.content.ContentValues;  
  5. import android.content.UriMatcher;  
  6. import android.database.Cursor;  
  7. import android.database.MatrixCursor;  
  8. import android.net.Uri;  
  9. import android.provider.BaseColumns;  
  10. import android.provider.ContactsContract;  
  11. import android.provider.LiveFolders;  
  12. import android.util.Log;  
  13.   
  14. public class MyContactsProvider extends ContentProvider {  
  15.   
  16.     public static final String AUTHORITY = "com.ai.livefolders.contacts";  
  17.   
  18.     // Uri that goes as input to the live-folder creation  
  19.     public static final Uri CONTACTS_URI = Uri.parse("content://" + AUTHORITY  
  20.             + "/contacts");  
  21.   
  22.     // To distinguish this URI  
  23.     private static final int TYPE_MY_URI = 0;  
  24.     private static final UriMatcher URI_MATCHER;  
  25.     static {  
  26.         URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);  
  27.         URI_MATCHER.addURI(AUTHORITY, "contacts", TYPE_MY_URI);  
  28.     }  
  29.   
  30.     @Override  
  31.     public boolean onCreate() {  
  32.         return true;  
  33.     }  
  34.   
  35.     @Override  
  36.     public int bulkInsert(Uri uri, ContentValues[] values) {  
  37.         return 0;  
  38.     }  
  39.   
  40.     // Set of columns needed by a live folder  
  41.     // This is the live-folder contract  
  42.     private static final String[] CURSOR_COLUMNS = new String[] {  
  43.             BaseColumns._ID, LiveFolders.NAME, LiveFolders.DESCRIPTION,  
  44.             LiveFolders.INTENT, LiveFolders.ICON_PACKAGE,  
  45.             LiveFolders.ICON_RESOURCE };  
  46.   
  47.     // In case there are no rows  
  48.     // use this stand-in as an error message  
  49.     // Notice it has the same set of columns of a live folder  
  50.     private static final String[] CURSOR_ERROR_COLUMNS = new String[] {  
  51.             BaseColumns._ID, LiveFolders.NAME, LiveFolders.DESCRIPTION };  
  52.   
  53.     // The error message row  
  54.     private static final Object[] ERROR_MESSAGE_ROW = new Object[] { -1// id  
  55.             "No contacts found"// name  
  56.             "Check your contacts database" // description  
  57.     };  
  58.   
  59.     // The error cursor to use  
  60.     private static MatrixCursor sErrorCursor = new MatrixCursor(  
  61.             CURSOR_ERROR_COLUMNS);  
  62.     static {  
  63.         // 为 CURSOR_ERROR_COLUMNS 添加给定的列值  
  64.         sErrorCursor.addRow(ERROR_MESSAGE_ROW);  
  65.     }  
  66.   
  67.     // Columns to be retrieved from the contacts database  
  68.     private static final String[] CONTACTS_COLUMN_NAMES = new String[] {  
  69.             ContactsContract.PhoneLookup._ID,  
  70.             ContactsContract.PhoneLookup.DISPLAY_NAME,  
  71.             ContactsContract.PhoneLookup.TIMES_CONTACTED,  
  72.             ContactsContract.PhoneLookup.STARRED,  
  73.             ContactsContract.PhoneLookup.PHOTO_ID };  
  74.   
  75.     @Override  
  76.     public Cursor query(Uri uri, String[] projection, String selection,  
  77.             String[] selectionArgs, String sortOrder) {  
  78.         // Figure out the uri and return error if not matching  
  79.         int type = URI_MATCHER.match(uri);  
  80.         if (type == UriMatcher.NO_MATCH) {  
  81.             // 如果URI 匹配出错则返回错误信息  
  82.             return sErrorCursor;  
  83.         }  
  84.   
  85.         Log.i("ss""query called");  
  86.   
  87.         try {  
  88.             // 调用 loadNewData方法进行查询 返回 匹配好的MatrixCursor对象  
  89.             MatrixCursor mc = loadNewData(this);  
  90.             // setNotificationUri方法用来指定一个Uri以观察它的变化  
  91.             // 参数一:需要一个ContentResolver对象,从上下文对象获得  
  92.             // 参数二:要监视的URI  
  93.             mc.setNotificationUri(getContext().getContentResolver(),  
  94.                     Uri.parse("content://com.android.contacts/contacts/"));  
  95.             MyCursor wmc = new MyCursor(mc, this);  
  96.             return wmc;  
  97.         } catch (Exception e) {  
  98.             System.out.println("Print yi chang ");  
  99.             // 返回我们的错误对象  
  100.             return sErrorCursor;  
  101.         }  
  102.   
  103.     }  
  104.   
  105.     public static MatrixCursor loadNewData(ContentProvider cp) {  
  106.         //  
  107.         MatrixCursor mc = new MatrixCursor(CURSOR_COLUMNS);  
  108.         Cursor allContacts = null;  
  109.         try {  
  110.             // 说一下query方法的参数  
  111.             /* 
  112.              * 参数一:要查询的URI 我们查询的完整URI 为"content://com.android.contacts/contacts" 
  113.              * 也就是所有的联系人参数二:都要查询那些列 上边我们已经定义好参数三:本质上就是一个WHERE子句,它以SQL 
  114.              * WHERE子句(不包含WHERE本身) 的格式声明要返回的行 传递null将返回给定URI 的所有行 
  115.              * 参数四:用来替换where子句中的?号参数五:指定排序的方式 
  116.              */  
  117.             allContacts = cp  
  118.                     .getContext()  
  119.                     .getContentResolver()  
  120.                     .query(ContactsContract.Contacts.CONTENT_URI,  
  121.                             CONTACTS_COLUMN_NAMES, nullnull,  
  122.                             ContactsContract.PhoneLookup.DISPLAY_NAME);  
  123.             while (allContacts.moveToNext()) {  
  124.                 // 返回第二列的值 也就是 ContactsContract.PhoneLookup.TIMES_CONTACTED的值  
  125.                 // the zero-based index  
  126.                 String timesContacted = "Times contacted: "  
  127.                         + allContacts.getInt(2);  
  128.   
  129.                 Object[] rowObject = new Object[] {  
  130.                         allContacts.getLong(0), // id  
  131.                         allContacts.getString(1), // name  
  132.                         timesContacted, // description  
  133.                         Uri.parse("content://com.android.contacts/contacts/"  
  134.                                 + allContacts.getLong(0)), // intent uri  
  135.                         cp.getContext().getPackageName(), // package 返回应用程序的包名称  
  136.                         R.drawable.contacts // 返回我们LiveFolder的图标  
  137.                 };  
  138.                 // 给我们的 MatrixCursor 对象mc 添加给定的列值  
  139.                 mc.addRow(rowObject);  
  140.             }  
  141.             // 返回MatrixCursor对象  
  142.             return mc;  
  143.         } finally {  
  144.             // 关闭Cursor对象, 并释放所有资源并使其无效  
  145.             allContacts.close();  
  146.         }  
  147.     }  
  148.   
  149.     // 如果有自定义类型,必须实现此方法 这里我们 用的是 系统定义好的类型  
  150.     @Override  
  151.     public String getType(Uri uri) {  
  152.         // indicates the MIME type for a given URI  
  153.         // targeted for this wrapper provier  
  154.         // This usually looks like  
  155.         // "vnd.android.cursor.dir/vnd.google.note"  
  156.         return ContactsContract.Contacts.CONTENT_TYPE;  
  157.   
  158.     }  
  159.   
  160.     @Override  
  161.     public Uri insert(Uri uri, ContentValues values) {  
  162.         throw new UnsupportedOperationException(  
  163.                 "no insert as this is just a wrapper");  
  164.     }  
  165.   
  166.     @Override  
  167.     public int delete(Uri uri, String selection, String[] selectionArgs) {  
  168.         throw new UnsupportedOperationException(  
  169.                 "no delete as this is just a wrapper");  
  170.     }  
  171.   
  172.     @Override  
  173.     public int update(Uri uri, ContentValues values, String selection,  
  174.             String[] selectionArgs) {  
  175.         throw new UnsupportedOperationException(  
  176.                 "no update as this is just a wrapper");  
  177.     }  
  178.   
  179. }  

先说一下 timesContacted,它是用来记录 我们的联系人呼叫我我们几次 比如你电话存着 女朋友的电话 timesContacted就记录着你女朋友给你打了几个电话,或者说呼叫了你几次,还有就连这个也可以时时更新,所以说还是比较强大的。

     INTENT 字段实际上是一个字符串,指向 ContentProvider 中该项的URL。在用户单击该项时,Android将使用此URL 来调用VIEW操作。此字符串字段称为 INTENT 字段是因为,在内部,Android会从字符串 URI 派生 INTENT。



   方法 loadNewData() 从联系人提供程序获取一组联系人并创建 MatrixCursor,MatrixCursor对象包含我们需要的列。这段代码然后告诉 MatrixCursor 向 ContentResolver 注册自身,以便在URI (content://com.android.contacts/contacts/) 所指向的数据以任何形式发生变化时,ContentResolver能够提醒游标也就是我们的Cursor对象


MyCursor对象是我们自己定义的一个Cursor对象,这里要理解为什么需要包装游标,需要了解视图如何更新更改的内容。ContentProvider(比如Contacts)通常通过将一个URI 注册为 query方法实现的一部分,告诉游标它需要监视更改。这是通过 cursor.setNotificationUri完成的。游标然后将向 ContentProvider 注册此URI 及它的所有子URI。然后,当在 ContentProvider 上发生插入或删除操作时,插入或删除操作的代码需要发出一个事件,表示特定URI 所标识的行中的数据发生了更改。

    这将出发游标通过 requery进行更新,视图也将相应更新。遗憾的是, MatrixCursor不适用此 requery。SQLiteCursor适用于它,但我们无法在这里使用 SQLiteCursor,因为我们已将这些列映射到了一组新列。

    为了解决这一限制,我们将MatrixCursor包装到一个游标包装器中,并重写 requery 方法以丢弃内部的 MatrixCursor,并使用更新的数据创建一个新游标。更明确的讲,每次数据更改时,我们都希望获得新的 MatrixCursor。但我们仅向 Android活动文件夹框架返回所包装的外部游标。这将告诉活动文件夹框架只有一个游标,但在后台,当数据更改时我们会创建新游标,我们下面来说说这两个类。


4. MyCursor.java


MyCursor最开始使用一个 MatrixCursor进行初始化。在requery上, MyCursor 将回调提供程序来返回一个 MatrixCursor。然后,新 MatrixCursor 将使用 set 方法替代旧 MatrixCursor。

说明:可以通过重写 MatrixCursor的requery来完成此任务,但该类无法清除数据并重新启动。所以这是一种合理的解决办法。


[java]  view plain copy
  1. package xiaohang.zhimeng;  
  2.   
  3. import android.content.ContentProvider;  
  4. import android.database.MatrixCursor;  
  5.   
  6. public class MyCursor extends BetterCursorWrapper {  
  7.   
  8.     private ContentProvider mcp = null;  
  9.   
  10.     public MyCursor(MatrixCursor mc, ContentProvider inCp) {  
  11.         super(mc);  
  12.         mcp = inCp;  
  13.     }  
  14.   
  15.     @Override  
  16.     public boolean requery() {  
  17.         MatrixCursor mc = MyContactsProvider.loadNewData(mcp);  
  18.         this.setInternalCursor(mc);  
  19.         return super.requery();  
  20.     }  
  21.   
  22. }  

5.    BetterCursorWrapper.java

BetterCursorWrapper类 非常类似于 Android数据库框架中的 CursorWrapper类。但我们还需要 CursorWrapper 所缺少的另外两项功能。首先,它没有提供 set方法来替换 requery 方法中的内部游标。其次, CursorWrapper 不是CrossProcessCursor。活动文件夹需要 CrossProcessCursor,而不是普通游标,因为活动文件夹会跨进程边界进行工作。
BetterCursorWrapper源代码:

[java]  view plain copy
  1. package xiaohang.zhimeng;  
  2.   
  3. import android.content.ContentResolver;  
  4. import android.database.CharArrayBuffer;  
  5. import android.database.ContentObserver;  
  6. import android.database.CrossProcessCursor;  
  7. import android.database.CursorWindow;  
  8. import android.database.DataSetObserver;  
  9. import android.net.Uri;  
  10. import android.os.Bundle;  
  11.   
  12. public class BetterCursorWrapper implements CrossProcessCursor {  
  13.   
  14.     // Holds the internal cursor to delegate methods to  
  15.     protected CrossProcessCursor internalCursor;  
  16.   
  17.     public CursorWindow getWindow() {  
  18.         return internalCursor.getWindow();  
  19.     }  
  20.   
  21.     public boolean onMove(int oldPosition, int newPosition) {  
  22.         return internalCursor.onMove(oldPosition, newPosition);  
  23.     }  
  24.   
  25.     public int getCount() {  
  26.         return internalCursor.getCount();  
  27.     }  
  28.   
  29.     public int getPosition() {  
  30.         return internalCursor.getPosition();  
  31.     }  
  32.   
  33.     public boolean move(int offset) {  
  34.         return internalCursor.move(offset);  
  35.     }  
  36.   
  37.     public boolean moveToPosition(int position) {  
  38.         return internalCursor.moveToPosition(position);  
  39.     }  
  40.   
  41.     public boolean moveToFirst() {  
  42.         return internalCursor.moveToFirst();  
  43.     }  
  44.   
  45.     public boolean moveToLast() {  
  46.         return internalCursor.moveToLast();  
  47.     }  
  48.   
  49.     public boolean moveToNext() {  
  50.         return internalCursor.moveToNext();  
  51.     }  
  52.   
  53.     public boolean moveToPrevious() {  
  54.         return internalCursor.moveToPrevious();  
  55.     }  
  56.   
  57.     public boolean isFirst() {  
  58.         return internalCursor.isFirst();  
  59.     }  
  60.   
  61.     public boolean isLast() {  
  62.         return internalCursor.isLast();  
  63.     }  
  64.   
  65.     public boolean isBeforeFirst() {  
  66.         return internalCursor.isBeforeFirst();  
  67.     }  
  68.   
  69.     public boolean isAfterLast() {  
  70.         return internalCursor.isAfterLast();  
  71.     }  
  72.   
  73.     public int getColumnIndex(String columnName) {  
  74.         return internalCursor.getColumnIndex(columnName);  
  75.     }  
  76.   
  77.     public int getColumnIndexOrThrow(String columnName)  
  78.             throws IllegalArgumentException {  
  79.         return internalCursor.getColumnIndexOrThrow(columnName);  
  80.     }  
  81.   
  82.     public String getColumnName(int columnIndex) {  
  83.         return internalCursor.getColumnName(columnIndex);  
  84.     }  
  85.   
  86.     public String[] getColumnNames() {  
  87.         return internalCursor.getColumnNames();  
  88.     }  
  89.   
  90.     public int getColumnCount() {  
  91.         return internalCursor.getColumnCount();  
  92.     }  
  93.   
  94.     public byte[] getBlob(int columnIndex) {  
  95.         return internalCursor.getBlob(columnIndex);  
  96.     }  
  97.   
  98.     public String getString(int columnIndex) {  
  99.         return internalCursor.getString(columnIndex);  
  100.     }  
  101.   
  102.     public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) {  
  103.         internalCursor.copyStringToBuffer(columnIndex, buffer);  
  104.     }  
  105.   
  106.     public short getShort(int columnIndex) {  
  107.         return internalCursor.getShort(columnIndex);  
  108.     }  
  109.   
  110.     public int getInt(int columnIndex) {  
  111.         return internalCursor.getInt(columnIndex);  
  112.     }  
  113.   
  114.     public long getLong(int columnIndex) {  
  115.         return internalCursor.getLong(columnIndex);  
  116.     }  
  117.   
  118.     public float getFloat(int columnIndex) {  
  119.         return internalCursor.getFloat(columnIndex);  
  120.     }  
  121.   
  122.     public double getDouble(int columnIndex) {  
  123.         return internalCursor.getDouble(columnIndex);  
  124.     }  
  125.   
  126.     public boolean isNull(int columnIndex) {  
  127.         return internalCursor.isNull(columnIndex);  
  128.     }  
  129.   
  130.     public void deactivate() {  
  131.         internalCursor.deactivate();  
  132.     }  
  133.   
  134.     public boolean requery() {  
  135.         return internalCursor.requery();  
  136.     }  
  137.   
  138.     public void close() {  
  139.         internalCursor.close();  
  140.     }  
  141.   
  142.     public boolean isClosed() {  
  143.         return internalCursor.isClosed();  
  144.     }  
  145.   
  146.     public void registerContentObserver(ContentObserver observer) {  
  147.         internalCursor.registerContentObserver(observer);  
  148.     }  
  149.   
  150.     public void unregisterContentObserver(ContentObserver observer) {  
  151.         internalCursor.unregisterContentObserver(observer);  
  152.     }  
  153.   
  154.     public void registerDataSetObserver(DataSetObserver observer) {  
  155.         internalCursor.registerDataSetObserver(observer);  
  156.     }  
  157.   
  158.     public void unregisterDataSetObserver(DataSetObserver observer) {  
  159.         internalCursor.unregisterDataSetObserver(observer);  
  160.     }  
  161.   
  162.     public void setNotificationUri(ContentResolver cr, Uri uri) {  
  163.         internalCursor.setNotificationUri(cr, uri);  
  164.     }  
  165.   
  166.     public boolean getWantsAllOnMoveCalls() {  
  167.         return internalCursor.getWantsAllOnMoveCalls();  
  168.     }  
  169.   
  170.     public Bundle getExtras() {  
  171.         return internalCursor.getExtras();  
  172.     }  
  173.   
  174.     public Bundle respond(Bundle extras) {  
  175.         return internalCursor.respond(extras);  
  176.     }  
  177.   
  178.     // Constructor takes a crossprocesscursor as an input  
  179.     public BetterCursorWrapper(CrossProcessCursor inCursor) {  
  180.         this.setInternalCursor(inCursor);  
  181.     }  
  182.   
  183.     // You can reset in one of the derived class's method  
  184.     public void setInternalCursor(CrossProcessCursor inCursor) {  
  185.         internalCursor = inCursor;  
  186.     }  
  187.   
  188.     @Override  
  189.     public void fillWindow(int pos, CursorWindow winow) {  
  190.         internalCursor.fillWindow(pos, winow);  
  191.     }  
  192.   
  193. }  

大家看前几个方法就行了,后边方法都没有用到 实现CrossProcessCursor这个接口就会实现这些方法。大家也可以用 Eclipse 自动生成一下,将光标放在 internalCursor上。用鼠标右键单击并选择 Source---》GenerateDelegate Methods。Eclipse随后将填充该类剩余部分。现在看一下完成此示例需要的一个简单activity.



6 .SimpleActivity.java:

SimpleActivity.java 不是活动文件夹必须的类,但在项目中包含它可以为所有项目提供一种通用模式。此外,它支持在通过 Eclipse调试时,部署应用程序并在屏幕上查看它。


[java]  view plain copy
  1. package xiaohang.zhimeng;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5.   
  6. public class SimpleActivity extends Activity {  
  7.     /** Called when the activity is first created. */  
  8.     @Override  
  9.     public void onCreate(Bundle savedInstanceState) {  
  10.         super.onCreate(savedInstanceState);  
  11.         setContentView(R.layout.main);  
  12.     }  
  13. }  

XML 布局文件:

[java]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical" android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent">  
  5.     <TextView android:layout_width="fill_parent"  
  6.         android:layout_height="wrap_content" android:text="Live Folder Example" />  
  7. </LinearLayout>  

完成这些就可以进行部署条数了.刚打开会打开一个Activity 就是我们上边的那个SimpleActivity 然后我们切换到主页 按照我们 最开始 介绍的步骤就可以建立 活动文件夹了






转载地址:http://blog.csdn.net/t12x3456/article/details/7845040

http://www.niftyadmin.cn/n/3649072.html

相关文章

网页开端第一次培训笔记

HTML HTML基本语法由 标签、整体结构、DOCTYPE组成 HTML的常用标签有 标题和水平线、段落和换行、列表、div和span、格式化标签 图片、超链接标签、表格、表单、字符实体等 HTML的全称为超文本标记语言&#xff0c;是一种标记语言。它包括一系列标签&#xff0e;通过这些标…

eclipse theia_如何在Ubuntu 18.04上设置Eclipse Theia Cloud IDE平台

eclipse theia介绍 (Introduction) With developer tools moving to the cloud, adoption of cloud IDE (Integrated Development Environment) platforms is growing. Cloud IDEs are accessible from every type of modern device through web browsers, and they offer nume…

Activity还是getApplicationContext、Fragment

Activity还是getApplicationContext 显示dialog必须使用Activity 使用adapter中初始化convertView最好使用Activity 显示地图时必须使用ApplicationContext 其他绝大的情况下两者都可以 选择ApplicationContext肯定没有问题 选择Activity可能会导致Activity对象不能被回收&…

网页开端第二次培训笔记

form标签性质及相关属性 input元素相关内容及框内属性、按钮属性 label标签、button按钮、select 常用属性&#xff1a;value设置值&#xff0c;selected 设置选中状态

BaseAdapter的封装(ListView)

首先第一步&#xff1a;我们看下我们一般情况下我们的BaseAdapter的使用 public class ProductAdapter extends BaseAdapter {private List<Product> productList;public ProductAdapter(List<Product> productList) {this.productList productList; }Override …

minio.exe怎么安装_如何在Ubuntu 18.04上使用Minio设置对象存储服务器

minio.exe怎么安装The author selected the Open Internet/Free Speech Fund to receive a donation as part of the Write for DOnations program. 作者选择了“ 开放互联网/言论自由基金会”作为“ Write for DOnations”计划的一部分来接受捐赠。 介绍 (Introduction) From…

[收藏]笑傲职场--如何获得影响力、权力和晋升

笑傲职场(如何在工作中获得、扩大影响力、权力和晋升&#xff09;以下是初稿大纲&#xff0c;有时间再细细道来。      序言&#xff1a;不走弯路就是捷径   内容&#xff1a;   一. 定位的原则   1、 你不能永远同时走两条钢丝   2、 永远站在主流之列   3、 一…

android桌面组件开发

Widget是Android1.5版所引进的特性之一.Widget,可让用户在主屏幕界面及时了解程序显示的重要信息.标准的Android系统已包含几个Widget的示例,如模拟时钟,音乐播放器等. 1、AppWidget 框架类 1、AppWidgetProvider &#xff1a;继承自 BroadcastRecevier &#xff0c; 在AppWid…