android有四大组件:分别为活动activity,服务,广播接收器Broadcast,内容提供器ContentResolver。
1.Activity
其中activity有一个生命周期,包含7个方法:
oncreate,onstart,onresume,onpause,onstop,ondestroy,onrestart。
首先我们引入一个栈的概念,后进先出的数据结构。活动就是这样放进这个栈的。
onstart:活动由不可见到开始可见。
onresume:此时活动一定可见,且处于栈顶位置
onpause:不在栈顶,但可见。
onstop:活动页面完全不可见。要经历onpause阶段。
ondestroy:销毁活动
![](https://img.haomeiwen.com/i7730759/9e974b0521d133a6.png)
此方法应用在比如听音乐和看电影时突然有电话打进来(有另一活动页面进来),就要暂停音乐和电影。还有类似短信和简书的保存信息。
有些时候由于内存的不够,系统会回收一些活动。怎样在系统回收前保存数据呢?系统回收前会调用onsaveinstancestate(Bundle a)的方法,这时只要往a里存数据就可以了,通过a.putString(健值,内容)的方式存取。然后在onceeate(Bundle a)中取出存的内容。a.getString(健值)。
![](https://img.haomeiwen.com/i7730759/9f58010524d1bf22.png)
Activity的启动模式(standard,singletop,singletask,singleinstance)
第一种是默认模式
用法:android:launchMode=“standard”
standard:只要是活动的都收,不管跟栈顶的活动一不一样。
singleTop:跟栈顶元素活动一样的不收。
singleTask:只要栈有的就不收。
singleInstance:其实是用两个栈来存储活动。
当调用栈中的activty重新运行,会调用onNewIntent()方法。
有时你看别人的代码的时候,想修改其中的一个页面,而又不知道这个页面的名字,就可以使用一个类来查看当前页面的名字,如图
其缺点是要把所有的活动的父继承改为BaseActivity而不是AppCompatActivity
![](https://img.haomeiwen.com/i7730759/f77d0e4fea467e77.png)
其中有关于final和static的区别这篇文章有讲:https://www.jianshu.com/p/9d4a41df164f
2.service
启动有两种启动方法:
服务的方法
1.自定义一个类继承Service,重写onBind,onStartCommand()方法。或继承IntentService
2.在Manifest.xml注册Service
3.在activity中启动Service
第一种使活动与服务关联的服务
![](https://img.haomeiwen.com/i7730759/207f4cadc610f526.png)
![](https://img.haomeiwen.com/i7730759/c6373676739ec31e.png)
![](https://img.haomeiwen.com/i7730759/26f206c3cc43b3ac.png)
第二种:活动控制不了的服务
![](https://img.haomeiwen.com/i7730759/f2c18036d44e0474.png)
![](https://img.haomeiwen.com/i7730759/71c1893897b7637a.png)
![](https://img.haomeiwen.com/i7730759/36ac875c8b07d140.png)
无论多少个活动启动同一个服务,服务的实例只有一个,如果同时启动与绑定服务,只有停止和解绑服务都操作时,才能去除服务。
最后,配置服务
![](https://img.haomeiwen.com/i7730759/6787dfd59fa80315.png)
在这里,因为服务的执行操作一般都比较复杂,需要子线程,而且不调用stopSelf(),服务还不会停止,所以封装了一个IntentService的类接口,让服务在子线程中完成并自动停止服务.
![](https://img.haomeiwen.com/i7730759/83944d07e4f198e1.png)
![](https://img.haomeiwen.com/i7730759/d1e5e5887004ee0f.png)
![](https://img.haomeiwen.com/i7730759/07efaa3608ac3a9f.png)
![](https://img.haomeiwen.com/i7730759/997767c46b839d11.png)
3.Broadcast
发送广播:sendBroadcast(intent) 普通广播:一发送全都能接收
sendOrderBroadcast(intent)有序广播:根据优先级一个一个接收
其中动态广播接收器大于静态广播接收器
广播接收器:1.自定义一个类继承BroadcastReceiver
2.重写onRecive()方法
3.在Manifest.xml中注册
在广播接收器中注册广播有两种:在代码中注册称为动态注册,在AndroidManifest.xml中注册为静态注册。
代码动态注册:
创建一个广播接收器类,继承BroadcastReceiver,在重写onReceiver()方法。
注册服务 :registerReceiver(广播接收器类,IntentFilter对象) 在oncreat()中调用
取消注册:unregisterReceiver(广播接收器) 在onDestroy()中调用
利用IntentFilter.addAction(类型):注册要接收什么广播 :例如:android.net.conn.CONNECTIBITY_CHANGE检测网络变化。
动态注册的缺点是在oncreate()中注册,只有在活动开启时才能启动广播。要想在未启动活动启动服务只能使用静态注册。
![](https://img.haomeiwen.com/i7730759/4a37dd18abc83278.png)
静态注册:
活动不运行时,也能接收。
在AS中创建一个广播接收器类new-other-Broadcast Receiver,只需在onReceive()写自己的代码,和在xml中写入要的权限。
![](https://img.haomeiwen.com/i7730759/34e02ab74077462d.png)
在接到有序广播后,想把这个广播屏蔽掉,在继承roadcastReceiver类中在onReceive()中,调用abortBroadcast();
只给自己的程序广播和只接收自己程序的本地广播:只能动态注册
LocalBroadcastManager.registerReceiver(广播接收器,广播);
LocalBroadcastManager.sendBroadcast(intent)
LocalBroadcastManager.unregiterReceiver(广播接收器)
怎样获得LocalBroadcastManager的实例:LocalBroadcastManager.getInstance(this)
![](https://img.haomeiwen.com/i7730759/fb5cfc5d55c8f25e.png)
4.ContentResolver
内容提供器简单来说就是访问别人的表的数据和提供给别人表的数据,如手机的联系人,短信,媒体库等。它主要的作用就是将程序的内部的数据和外部进行共享
1.获取ContentResolver实例
2.确定Uri的内容,并解析为具体的Uri实例
3.通过ContentResolver实例来调用相应的方法,传递相应的参数,但是第一个参数总是Uri,它制定了我们要操作的数据的具体地址
1.读取别人的内容提供器的内容
获得一个ContentResolver的对象,Context的getContentResolver()就可以获得ContentResolver的对象.
此对象跟SQLite的增删改查(query,insert,updata,delete)操作几乎一样。把表名改为Uri。其中内容Uri的格式为:
content://com.example.app.provider/table1表示访问table1表。content://com.example.app.provider/table1/1 表示访问table1表中id=1的数据。
ContentValues,使用的是put存储数据.put(列,值)
1.例如查询其他共享表信息:getContentResolver.query(Uri,列,where,where?,order),返回一个Cursor的对象。然后利用moveToNext()遍历cursor对象,调用其cursor.getString(cursor.getImColumnIndex(“”)):得到相应的属性值
2.向其他表添加数据:getContentResolver.insert(Uri,ContentValues)
3.跟新其他表的数据:getContentResolver.updata(Uri,ContentValues,where,where?)
4.删除其他表的数据:getContentResolver.delete(Uri,where,where?)
2.创建自己的内容提供器
1.新建一个类继承ContentProvider,并重写6个抽象方法 (new-other-ContentProvider),oncreat()ture表示内容提供器初始化成功,query(),insert().updata()返回更新的行数.delete()返回被删除的行数,getType()。
*:表示任意字符 #:表示任意数字
那么内容提供器是怎样识别出传进来的Uri要哪什么内容?
首先,调用UriMatcher这个类的对象,new UriMatcher(UriMatcher.NO_MATCH)
然后调用此对象的addURI(路径名,表名,自定义参数)的方法,传入三个参数
然后将传进来的UriMatcher用此对象的match(uri)来得到自定义参数。
![](https://img.haomeiwen.com/i7730759/c1aae20a506fdf4c.png)
创建内容提供器案例
![](https://img.haomeiwen.com/i7730759/9bd0c3766af0e60c.png)
![](https://img.haomeiwen.com/i7730759/babdba3c3ade43c3.png)
![](https://img.haomeiwen.com/i7730759/19110c37e2087ebf.png)
![](https://img.haomeiwen.com/i7730759/11a9ca29a113fbef.png)
![](https://img.haomeiwen.com/i7730759/c214a6fa3c152e96.png)
![](https://img.haomeiwen.com/i7730759/8d767455391eb1c5.png)
![](https://img.haomeiwen.com/i7730759/6d424b04464c71d4.png)
其中查看联系人的权限是READ_CONTACTS
联系人的Uri是:ContectsContract.CommonDataKinds.Phone.CONTENT_URI
联系人手机号码的列名:ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
联系人的姓名的列名:ContactsContract.CommonDataKinds.Phone.NUMBER
网友评论