Activity作为四大组件中使用最频繁的组件,我们在使用的过程中应该要知道它的生命周期和启动模式。
Activity生命周期如下图所示(图片摘自《Android开发艺术探索》):
为了防止重建Activity,可以给Activity指定configChanges属性,例如不想让Activity在屏幕旋转时重建就可以给configChanges添加orientation属性,不想让Activity在分屏后恢复全屏时重建,可以给configChanges添加screenLayout属性,如果想指定多个值,可以用“|”连接起来,如下所示:
android:configChanges="screenLayout|orientation"
Activity目前有四种启动模式:standard、singleTop、singleTask和singleInstance:
BroadcastReciever的生命周期很短,当onRecieve()方法执行完毕之后即会被finish,因此不推荐在onRecieve方法中执行耗时操作。不应该在onRecieve方法中开启线程处理耗时操作,因为当onRecieve方法执行完毕后BroadcastReciever就会退出,而线程还在,此时该线程会被标记为空线程,在系统内存紧张的时候会被回收而导致线程无法保证被执行完毕,因此建议启动一个service,由service去执行耗时操作。另外,如果onRecieve方法超过10秒未执行完毕,会导致系统抛出ANR。
广播的注册分为静态注册与动态注册两种。静态注册在清单文件中进行注册,而动态注册则在代码中通过Context.registerReciever()进行注册。
Service有两种启动方式
2018-12-06 16:43:59.324 23816-23816/com.anyidc.service_study E/tag: --------Service-------->>onCreate
2018-12-06 16:43:59.325 23816-23816/com.anyidc.service_study E/tag: --------Service-------->>onStartCommand
2018-12-06 16:44:02.992 23816-23816/com.anyidc.service_study E/tag: --------Service-------->>onBind
2018-12-06 16:44:04.278 23816-23816/com.anyidc.service_study E/tag: --------Service-------->>onUnbind
2018-12-06 16:44:06.090 23816-23816/com.anyidc.service_study E/tag: --------Service-------->>onDestroy
2018-12-06 17:02:40.037 27910-27910/com.anyidc.service_study E/tag: --------Service-------->>onCreate
2018-12-06 17:02:40.038 27910-27910/com.anyidc.service_study E/tag: --------Service-------->>onBind
2018-12-06 17:02:44.181 27910-27910/com.anyidc.service_study E/tag: --------Service-------->>onStartCommand
在这一步如果先stopService(),Service的onDestroy方法不执行,再进行解绑操作,则执行以下两个方法。
若先执行unBindService(),则Service方法的onUnbind方法执行,onDestroy方法不会执行,此时要通过stopService方法退出Service,onDestroy才会被执行。
2018-12-06 17:02:47.599 27910-27910/com.anyidc.service_study E/tag: --------Service-------->>onUnbind
2018-12-06 17:02:47.600 27910-27910/com.anyidc.service_study E/tag: --------Service-------->>onDestroy
IntentService是Service的子类,可以使用它来做一些下载文件等耗时操作,其特征为:
ContentProvider主要用于在不同的应用之间实现数据共享的功能。ContentProvider的用法一般有两种,一种是使用现有的内容提供者来读取和操作相应程序的数据,另一种是创建自己的内容提供者给我们的数据提供外部访问接口。
对于每一个应用程序,如果想要访问内容提供者中的共享数据,就一定要借助ContentResolver类,可以通过Context.getContentResolver()方法获取到该类的实例。ContentResolver类提供了一系列方法对数据进行CRUD操作,ContentProvider通过Uri作为数据的唯一标识符,它主要由两部分组成:authority和path。authority一般采用程序的包名+provider进行命名,path则是用于区分同一程序中不同的表,通常跟在authority的后面。标准的Uri内容如下:
content://com.example.app.provider/table1
获取到内容的Uri后即可通过ContentResolver去获取和操作相应程序表中的数据了,以下为ContentResolver操作数据的相关方法:
通过ContentResolver的query方法获取到游标对象,随后遍历游标的所有行即可获取数据
Cursor cursor=getContentResolver().query(uri,projection,selection,selectionArgs,sortOrder);
通过ContentValues对象和ContentResolver的insert方法往表中插入数据
ContentValues values=new ContentValues();
values.put("列名",value);
getContentResolver().insert(uri,values);
通过ContentValues对象和ContentResolver的update方法修改表中数据
ContentValues values=new ContentValues();
values.put("列名",value);
getContentResolver().update(uri,values,"列名=?and列名2=?",new String[]{"text","1"});
通过ContentResolver的delete放放删除表中数据
getContentResolver().delete(uri,"列名=?",new String[]{"text"});
创建自己的内容提供者需要创建一个类去继承ContentProvider并且实现其6个抽象方法。
public class ThisContentProvider extends ContentProvider {
@Override
public boolean onCreate() {
//初始化内容提供者的时候调用。通常在这里完成对数据库的创建和升级。
return false;
}
@Override
public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {
//从内容提供者中查询数据。
return null;
}
@Override
public String getType(Uri uri) {
//根据传入的uri返回相应的MIME类型
return null;
}
@Override
public Uri insert(Uri uri, ContentValues contentValues) {
//向内容提供者中插入数据
return null;
}
@Override
public int delete(Uri uri, String s, String[] strings) {
//删除内容提供者中的数据
return 0;
}
@Override
public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
//更新内容提供者中已有的数据。
return 0;
}
}
在自己的内容提供者类中,应该先获取本程序中的SQLiteDatabase对象,再通过此对象对uri中的相应表格进行CRUD操作,具体的逻辑应该根据项目的业务逻辑分别在六个方法中进行完善,特别需要注意的是,自定义的内容提供者编写完成后应该在清单文件中进行注册,并且需要指定authority属性,并将enabled和exported属性设置为true,表示允许此内容提供者被其他程序访问。
参考资料: