從事Android以來的相關總結2-Android技能

Android的進程與線程:

1、進程的生命周期:

1)、進程的創建及回收:

進程是被系統創建的,當內存不足的時候,又會被系統回收

2)、進程的級別:

Foreground Process前臺進程

Visible Process可視進程

Service Process服務進程:可以提高級別的

Background Process后臺進程

Empty Process空進程(無組件啟動,做進程緩存使用,恢復速度快)

Android技能

?熟練掌握Android四大組件,常用的布局文件,自定義控件等

Android中4大組件是:ContentProvider、Activity、BroadcastReceiver和Service

清單文件:

1、所有的應用程序必須要有清單文件

在manifest節點下需要聲明當前應用程序的包名

2、包名:聲明包的名字,必須唯一

如果兩個應用程序的包名和簽名都相同,后安裝的會覆蓋先安裝的

3、聲明的程序的組件(4大組件)

其中比較特殊的是廣播接收者,可以不在清單文件中配置,可以通過代碼進行注冊

4、聲明程序需要的權限:保護用戶的隱私

5、可以控制服務在單獨的進程中的,四大組件都可以配置這個屬性process

在組件節點配置process:

如:android:process="xxx.ooo.xxx"

比如說:處理圖片的時候,會很耗內存,就需要在單獨的新的進程中,可以減少內存溢出的幾率


一、ContentProvider內容提供者

1、特點

①、可以將應用中的數據對外進行共享;

②、數據訪問方式統一,不必針對不同數據類型采取不同的訪問策略;

③、內容提供者將數據封裝,只暴露出我們希望提供給其他程序的數據(這點有點類似Javabeans);

④、內容提供者中數據更改可被監聽;

2、創建內容提供者

?定義類繼承ContentProvider,根據需要重寫其內容方法(6個方法):

lonCreate()創建內容提供者時,會調用這個方法,完成一些初始化操作;

lcrud相應的4個方法用于對外提供CRUD操作;

lgetType()返回當前Url所代表數據的MIME類型:

返回的是單條記錄:以vnd.android.cursor.item/開頭,如:vnd.android.cursor.item/person

返回的是多條記錄:以vnd.android.cursor.dir/開頭,如:vnd.android.cursor.dir/person

?在清單文件的節點下進行配置,標簽中需要指定name、authorities、exported屬性

lname:為全類名;

lauthorities:是訪問Provider時的路徑,要唯一;

lexported:用于指示該服務是否能夠被其他應用程序組件調用或跟它交互

?URI代表要操作的數據,由scheme、authorites、path三部分組成:

lcontent://com.itheima.sqlite.provider/person

lscheme:固定為content,代表訪問內容提供者;

lauthorites:節點中的authorites屬性;

lpath:程序定義的路徑,可根據業務邏輯定義;

?操作URI的UriMather與ContentUris工具類:

當程序調用CRUD方法時會傳入Uri

lUriMatcher:表示URI匹配器,可用于添加Uri匹配模式,與匹配Uri(見下代碼);

lContentUris:用于操作Uri路徑后面的ID部分,2個重要的方法:

1.withAppendedId(uri, id)為路徑加上ID部分;

2.parseId(uri)用于從路徑中獲取ID部分;

示例代碼(內容提供者類):

public classHeimaProvider extends ContentProvider {

private static final int PERSON = 1;//匹配碼

private static final int STUDENT = 2;//匹配碼

private static final int PERSON_ID = 3;//匹配碼

private MyHelper helper;

/** Uri匹配器*/

private UriMatcher uriMatcher = newUriMatcher(UriMatcher.NO_MATCH);

@Override

public boolean onCreate() {

System.out.println("onCreate...");

helper = newMyHelper(getContext());

// ==添加uri匹配模式,設置匹配碼(參數3)Uri如果匹配就會返回相應的匹配碼==

uriMatcher.addURI("com.itheima.sqlite.provider","person", PERSON);

uriMatcher.addURI("com.itheima.sqlite.provider","#", PERSON_ID);// #表示匹配數字,*表示匹配文本

uriMatcher.addURI("com.itheima.sqlite.provider","student", STUDENT);

return true;

}

@Override

public Uri insert(Uri uri, ContentValuesvalues) {

SQLiteDatabase db =helper.getWritableDatabase();

switch (uriMatcher.match(uri)) {//匹配uri

case PERSON:

long id =db.insert("person", "id", values);

db.close();

returnContentUris.withAppendedId(uri, id);//在原uri上拼上id,生成新的uri并返回;

case STUDENT:

long insert =db.insert("student", "id", values);

System.out.println("數據文件中,沒有student表,也不會報錯");

db.close();

returnContentUris.withAppendedId(uri, insert);//為路徑上,加上ID

default:

throw newIllegalArgumentException(String.format("Uri:%s不是合法的uri地址", uri));

}

}

@Override

public int delete(Uri uri, Stringselection, String[] selectionArgs) {

SQLiteDatabase db =helper.getWritableDatabase();

switch (uriMatcher.match(uri)) {//匹配uri

case PERSON_ID:

long parseId =ContentUris.parseId(uri);//獲取傳過來的ID值

selection = "id=?";//設置查詢條件

selectionArgs = newString[] { parseId + "" };//查詢條件值

case PERSON:

int delete =db.delete("person", selection, selectionArgs);

db.close();

return delete;

default:

throw newIllegalArgumentException(String.format("Uri:%s不是合法的uri地址", uri));

}

}

@Override

public int update(Uri uri, ContentValuesvalues, String selection, String[] selectionArgs) {

SQLiteDatabase db =helper.getWritableDatabase();

switch (uriMatcher.match(uri)) {

case PERSON_ID:

long parseId =ContentUris.parseId(uri);//獲取傳過來的ID值

selection ="id=?";//設置查詢條件

selectionArgs = newString[] { parseId + "" };//查詢條件值

case PERSON:

int update =db.update("person", values, selection, selectionArgs);

db.close();

return update;

default:

throw newIllegalArgumentException(String.format("Uri:%s不是合法的uri地址", uri));

}

}

@Override

public Cursor query(Uri uri, String[]projection, String selection, String[] selectionArgs, String sortOrder) {

SQLiteDatabase db =helper.getWritableDatabase();

switch (uriMatcher.match(uri)) {

case PERSON_ID:

// ==根據ID查詢==

long parseId =ContentUris.parseId(uri);//獲取傳過來的ID值

selection ="id=?";//設置查詢條件

selectionArgs = newString[] { parseId + "" };//查詢條件值

case PERSON:

Cursor cursor =db.query("person", projection, selection, selectionArgs, null, null,sortOrder);

// ==注意:此處的db與cursor不能關閉==

return cursor;

default:

throw newIllegalArgumentException(String.format("Uri:%s不是合法的uri地址", uri));

}

}

//返回傳入URI的類型,可用于測試URI是否正確

@Override

public String getType(Uri uri) {

switch (uriMatcher.match(uri)) {

case PERSON_ID:

return"vnd.android.cursor.item/person";//表示單條person記錄

case PERSON:

return"vnd.android.cursor.dir/person";//表單多個person記錄

default:

return null;

}

}

}

清單中的配置:

android:exported="true"

android:name="com.itheima.sqlite.provider.HeimaProvider"

android:authorities="com.itheima.sqlite.provider" />

authorities可以配置成如下形式(系統聯系人的):

android:authorities="contacts;com.android.contacts"

“;”表示的是可使用contacts,與com.android.contacts

3、內容解析者ContentResolver

?通過Context獲得ContentResolver內容訪問者對象(內容提供者的解析器對象);

?調用ContentResolver對象的方法即可訪問內容提供者

測試類代碼:

public class HeimaProviderTest extends AndroidTestCase {

/**測試添加數據*/

public void testInsert() {

ContentResolver resolver =this.getContext().getContentResolver();

Uri uri =Uri.parse("content://com.itheima.sqlite.provider/person");

ContentValues values = newContentValues();

values.put("name","小翼");

values.put("balance",13000);

Uri insert = resolver.insert(uri,values);//獲取返回的uri,如:content://com.itheima.sqlite.provider/7

System.out.println(insert);

}

/**測試刪除*/

public void testRemove() {

ContentResolver resolver = this.getContext().getContentResolver();

Uri uri =Uri.parse("content://com.itheima.sqlite.provider/person");

int count = resolver.delete(uri,"id=?", new String[] { 3 + "" });

System.out.println("刪除了" + count + "行");

}

/**測試更新*/

public void testUpdate() {

ContentResolver resolver =this.getContext().getContentResolver();

Uri uri =Uri.parse("content://com.itheima.sqlite.provider/person");

ContentValues values = newContentValues();

values.put("name","小趙update");

values.put("balance",56789);

int update = resolver.update(uri,values, "id=?", new String[] { 6 + "" });

System.out.println("更新了" + update + "行");

}

/**測試查詢*/

public void testQueryOne() {

ContentResolver resolver =this.getContext().getContentResolver();

Uri uri = Uri.parse("content://com.itheima.sqlite.provider/person");

Cursor c = resolver.query(uri, newString[] { "name", "balance" }, "id=?", newString[] { 101 + "" }, null);

if (c.moveToNext()) {

System.out.print(c.getString(0));

System.out.println("" + c.getInt(1));

}

c.close();

}

/**測試查詢全部*/

public void testQueryAll() {

ContentResolver resolver =this.getContext().getContentResolver();

Uri uri =Uri.parse("content://com.itheima.sqlite.provider/person");

Cursor c = resolver.query(uri, newString[] { "id", "name", "balance" }, null, null,"name desc");

while (c.moveToNext()) {

System.out.println(c.getInt(0)+ ", " + c.getString(1) + ", " + c.getInt(2));

}

c.close();

}

/**測試查詢一條*/

public void testQueryOneWithUriId() {

ContentResolver resolver =this.getContext().getContentResolver();

Uri uri =Uri.parse("content://com.itheima.sqlite.provider/3");//查詢ID為3的記錄

Cursor c = resolver.query(uri, newString[] { "id", "name", "balance" }, null, null,null);

if (c.moveToNext()) {

System.out.println(c.getInt(0)+ ", " + c.getString(1) + ", " + c.getInt(2));

}

c.close();

}

/**測試獲取內容提供者的返回類型*/

public void testGetType() {

ContentResolver resolver =this.getContext().getContentResolver();

System.out.println(resolver.getType(Uri.parse("content://com.itheima.sqlite.provider/2")));

System.out.println(resolver.getType(Uri.parse("content://com.itheima.sqlite.provider/person")));

}

}

4、監聽內容提供者的數據變化

?在內容提供者中可以通知其他程序數據發生變化

通過Context的getContentResolver()方法獲取ContentResolver

調用其notifyChange()方法發送數據修改通知,發送到系統的公共內存(消息信箱中)

?在其他程序中可以通過ContentObserver監聽數據變化

通過Context的getContentResolver()方法獲取ContentResolver

調用其registerContentObserver()方法指定對某個Uri注冊ContentObserver

自定義ContentObserver,重寫onChange()方法獲取數據

示例代碼(發通知部分):

public int delete(Uri uri, Stringselection, String[] selectionArgs) {

SQLiteDatabase db =helper.getWritableDatabase();

int delete =db.delete("person", selection, selectionArgs);

// ==通過內容訪問者對象ContentResolve發通知給所有的Observer ==

getContext().getContentResolver().notifyChange(uri,null);

db.close();

returndelete;

}

}

監聽部分:

//注冊內容觀察者事件

private voidinitRegisterContentObserver() {

Uri uri =Uri.parse("content://com.itheima.sqlite.provider");//監聽的URI

// ==第2個參數:true表示監聽的uri的后代都可以監聽到==

getContentResolver().registerContentObserver(uri,true, new ContentObserver(new Handler()) {

public voidonChange(boolean selfChange) {//接到通知就執行

personList =personDao.queryAll();

((BaseAdapter)personListView.getAdapter()).notifyDataSetChanged();

}

});

}

5、區別Provider/Resolver/Observer

1)ContentProvider:內容提供者

把一個應用程序的私有數據(如數據庫)信息暴露給別的應用程序,讓別的應用程序可以訪問;

在數據庫中有對應的增刪改查的方法,如果要讓別的應用程序訪問,需要有一個路徑uri:

通過content://路徑對外暴露,uri寫法:content://主機名/表名

2)ContentResolver:內容解析者

根據內容提供者的路徑,對數據進行操作(crud);

3)ContentObserver:內容觀察者

可以理解成android系統包裝好的回調,數據發送變化時,會執行回調中的方法;

ContentResolver發送通知,ContentObserver監聽通知;

當A的數據發生變化的時候,A就會顯示的通知一個內容觀察者,不指定觀察者,就會發消息給一個路徑

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容