免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2211 | 回复: 0
打印 上一主题 下一主题

實際演練Android模擬器之操作 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-03-25 22:56 |只看该作者 |倒序浏览
1.  何謂Android的嫡系組件

    Android有4項一等公民(或稱為嫡系親屬),包括:Activity、ContentProvider、IntentReceiver與Service。它們都必須宣告於AndroidManifest.xml檔案裡,如下:

                       
                          

1.  何謂Android的嫡系組件

    Android有4項一等公民(或稱為嫡系親屬),包括:Activity、ContentProvider、IntentReceiver與Service。它們都必須宣告於AndroidManifest.xml檔案裡,如下:

    package="com.misoo.SQ03">
      
         android:name="android.permission.INTERNET">
   
   
        provider android:name="DataProvider"
            android:authorities="com.misoo.provider.SQ03">
        provider>
        activity android:name=".ac01" android:label="@string/app_name">
            
               
               
            
        activity>
        activity android:name=".DispActivity" android:label="DispActivity">
        activity>
   

    這讓Android知道我們城市裡定義了多少個嫡系組件類別;Android可以在啟動時就將它們執行起來,成為共享的(Shared)服務組件。這些嫡系服務組件間的溝通,通常是透過「意圖」(Intent)物件來請Android轉達給對方,Android則會依據意圖而找出最佳的配對。配對成功,就展開相互的溝通與服務了。
   


2.   [color="#0000ff"]什麼是ContentProvider嫡系組件
[color="#0000ff"]---- 以SQLite為例

    在Android裡,SQLite資料庫是最典型的ContentProvider,負責儲存各式各樣的內容。除了資料庫之外,還有許多其他種類的ContentProvider。在這裡並不是要介紹這些ContentProvider,而是要透過SQLite認識ContentProvider介面,然後將舶來Linter組件,配上這種ContentProvider介面,讓它搖身一變成為Android的嫡系組件。


2.1  一般(即非嫡系)SQLite的範例

      沒有透過ContentProvider介面來使用SQLite,就是對SQLite的「非嫡系」用法。此時,應用程式透過JDBC介面和SQL語句來與SQLite溝通,以存取資料庫裡的內容。先認識這種傳統用法。此範例將從SQLite讀取資料。首先建立一個程式專案,其含有兩個Java程式檔:ac01.java和DataProvider.java。其中,ac01.java 是典型的Activity類別,負責UI畫面的顯示工作,而DataProvider則負責與SQLite溝通。其詳細程式碼為:

/* ----- ac01.java 程式碼 ------*/
package com.misoo.pklx;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import android.app.ListActivity;
import android.database.Cursor;
import android.os.Bundle;
import android.view.View;
import android.widget.ListView;
import android.widget.SimpleAdapter;

public class ac01 extends ListActivity {
    private static final String[] PROJECTION = new String[] { "stud_no", "stud_name" };

    @Override protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
        DataProvider dp = new DataProvider(this);
        Cursor cur = dp.query(PROJECTION, null, null, null);
        ArrayList> coll
                = new ArrayList>();
        Map item;
        cur.moveToFirst();
        while(!cur.isAfterLast()) {
          item = new HashMap();
          item.put("c1", cur.getString(0) + ",  " + cur.getString(1));
          coll.add(item);
          cur.moveToNext();
        }
        dp.close();
        this.setListAdapter(new SimpleAdapter(this, coll,
              android.R.layout.simple_list_item_1, new String[] { "c1" },
              new int[] {android.R.id.text1}));
    }
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
               finish();
}}

    指令:
           DataProvider dp = new DataProvider(this);

     這和一般類別之用法是一樣的。ac01物件指名要誕生一個DataProvider的物件。然後呼叫它,如下指令:
          Cursor cur = dp.query(PROJECTION, null, null, null);

這要求SQLite從資料庫查詢出某些資料。詳細的DataProvider.java程式碼如下:

/* ----- DataProvider.java 程式碼 ------*/
package com.misoo.pklx;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

public class DataProvider {
    private static final String DATABASE_NAME = "StudDB";
    private static final String TABLE_NAME = "Student";
    private final int DB_MODE = Context.MODE_PRIVATE;
    private SQLiteDatabase db=null;
            
    public DataProvider(Context ctx) {
       try {  db = ctx.openOrCreateDatabase(DATABASE_NAME, DB_MODE, null);   }
catch (Exception e) {  Log.e("ERROR", e.toString());   return;   }

       try { db.execSQL("drop table "+ TABLE_NAME); }
catch (Exception e) {  Log.e("ERROR", e.toString());   }

       db.execSQL("CREATE TABLE " + TABLE_NAME + " ("  + "stud_no" + " TEXT,"
                               + "stud_name" + " TEXT" + ");");
             String sql_1 = "insert into "+ TABLE_NAME +
" (stud_no, stud_name) values('S101', 'Lily');";
String sql_2 = "insert into " + TABLE_NAME +
" (stud_no, stud_name) values('S102', 'Linda');";
             String sql_3 = "insert into " + TABLE_NAME +
" (stud_no, stud_name) values('S103', 'Bruce');";

   try {  db.execSQL(sql_1);   db.execSQL(sql_2);  db.execSQL(sql_3); }
catch (SQLException e) {  Log.e("ERROR", e.toString());  return;  }
   }
    public Cursor query(String[] projection, String selection, String[] selectionArgs,
                               String sortOrder) {
           Cursor cur = db.query(TABLE_NAME, projection, null, null, null, null, null);
          return cur;
    }
    public void close(){   db.close();   }
}

這種用法屬於非嫡系的用法:在ac01.java程式碼裡,其指令:
           DataProvider dp = new DataProvider(this);

明確指定由DataProvider物件來提供服務。反之,嫡系用法則是透過意圖(Intent)來請Android代為配對,進而找出適當的ContentProvider物件來為aco1物件提供服務。


2.2  嫡系SQLite的範例

    剛才的範例裡,我們直接使用DataProvider類別的介面來與SQLite溝通。本節的範例,將替DataProvider配上ContentProvider介面,讓ac01物件能透過ContentProvider新介面來溝通。此範例也是從SQLite資料庫讀取3筆資料;請仔細看看其程式碼的微妙差異:

/* ----- ac01.java 程式碼 ------*/
package com.misoo.pkrr;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import android.app.ListActivity;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.ListView;
import android.widget.SimpleAdapter;

public class ac01 extends ListActivity {
           public static int g_variable;
           public static final String AUTHORITY = "com.misoo.provider.rx09-02";
           public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY
                                + "/Student");
           private static final String[] PROJECTION
              = new String[]{ "stud_no", "stud_name"};
           @Override  protected void onCreate(Bundle savedInstanceState) {
                     super.onCreate(savedInstanceState);
                     Intent intent = getIntent();
                     if (intent.getData() == null)  intent.setData(CONTENT_URI);
                     Cursor cur = getContentResolver().query(getIntent().getData(),
                                           PROJECTION, null, null, null);
                     ArrayList> coll = new ArrayList>();
                     Map item;
                     cur.moveToFirst();
                     while (!cur.isAfterLast()) {
                                item = new HashMap();
                                item.put("c1", cur.getString(0) + ",  " + cur.getString(1));
                                coll.add(item);
                                cur.moveToNext();
                     }
                     this.setListAdapter(new SimpleAdapter(this, coll,
                                           android.R.layout.simple_list_item_1, new String[] { "c1" },
                                           new int[] { android.R.id.text1 }));
           }
           @Override
           protected void onListItemClick(ListView l, View v, int position, long id) { finish();}
}

   指令:
              Cursor cur = getContentResolver().query(getIntent().getData(),
                                           PROJECTION, null, null, null);

要求Android代為尋找適合的ContentProvider來提供服務,並不刻意指定由DataProvider物件來擔任。只要合乎ConentProvider介面,且符合意圖條件的物件皆可以來為ac01物件提供服務。於是,ac01程式碼就不再直接呼叫DataProvider類別的函數了,而是呼叫ContentProvider介面所提供的函數。再來仔細看看DataProvider類別與ContentProvider介面的搭配情形:

/* ----- DataProvider.java 程式碼 ------*/
package com.misoo.pkrr;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.util.Log;

public class DataProvider extends ContentProvider {
           private static final String DATABASE_NAME = "StudNewDB";
           private static final int DATABASE_VERSION = 2;
           private static final String TABLE_NAME = "StudTable";
           private static class DatabaseHelper extends SQLiteOpenHelper {
                     DatabaseHelper(Context context) {
                                super(context, DATABASE_NAME, null, DATABASE_VERSION);  }
                     @Override  public void onCreate(SQLiteDatabase db) {
                                db.execSQL("CREATE TABLE " + TABLE_NAME + " (" + "stud_no"
                                                     + " TEXT," + "stud_name" + " TEXT" + ");");
                                String sql_1 = "insert into " + TABLE_NAME
                                                     + " (stud_no, stud_name) values('S1001', 'Pam');";
                                String sql_2 = "insert into " + TABLE_NAME
                                                     + " (stud_no, stud_name) values('S1002', 'Steve');";
                                String sql_3 = "insert into " + TABLE_NAME
                                                     + " (stud_no, stud_name) values('S1003', 'John');";
                                try { db.execSQL(sql_1);  db.execSQL(sql_2);  db.execSQL(sql_3);       }
catch (SQLException e) { Log.e("ERROR", e.toString());         }
                     }
                     @Override
                     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
           }
           // ---------------------------------------------------------------------------------
           private DatabaseHelper mOpenHelper;
           @Override  public boolean onCreate() {
                     mOpenHelper = new DatabaseHelper(getContext());  return true;  }
           @Override  public Cursor query(Uri uri, String[] projection, String selection,
                                String[] selectionArgs, String sortOrder) {
                     SQLiteDatabase db = mOpenHelper.getReadableDatabase();
                     Cursor c = db.query(TABLE_NAME, projection, null, null, null, null,      null);
                     return c;
           }
           @Override  public String getType(Uri uri) {         return null;  }
           @Override  public Uri insert(Uri uri, ContentValues initialValues) { return uri; }
           @Override  public int delete(Uri uri, String where, String[] whereArgs) { return 0; }
           @Override  public int update(Uri uri, ContentValues values, String where,
                            String[] whereArgs)
{  return 0;  }
}

     類別定義:
           public class DataProvider extends ContentProvider {
// …..…..
}

DataProvider類別繼承ContentProvider父類別,也繼承了它的介面定義。ContentProvider介面定義了多個函數,主要包括:
l           query()函數---- 它查詢出合乎某條件的資料。
l           insert()函數---- 它將存入一筆新資料。
l           delete()函數---- 它刪除合乎某條件的資料。
l           update()函數---- 更新某些筆資料的內容。

     在這個DataProvider類別裡,撰寫了query()函數內的指令,來實現query()介面,這個query()函數實際呼叫SQLite資料庫的功能。也就是說,ac01等應用程式透過ContentProvider介面間接呼叫到DataProvider的query()函數,然後此query()函數才使用SQLite的服務。
     由於此範例的DataProvider已經是ContentProvider嫡系身份了,必須由Android來啟動它,而不是有ac01等應用程式來直接啟動它,所以必須在AndroidManifest.xml文檔裡給Android一些指示,如下:

/* ----- AndroidManifest.xml 文檔 ------*/
      package="com.misoo.pkrr"
      android:versionCode="1"
      android:versionName="1.0.0">
   
        
                  android:label="@string/app_name">
            
               
               
            
        
        
            android:authorities="com.misoo.provider.rx09-02">
        
   

這特別說明DataProvider是一個ContentProvider,於是Android就會來啟動它。
  (by Misoo團隊)
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/49742/showart_1879764.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP