从事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就会显示的通知一个内容观察者,不指定观察者,就会发消息给一个路径

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容