name="com.example.mobilesafe.WatchDogActivity"
android:
launchMode="singleInstance"/>
1.5Activity启动方法
1)在一个Activity中调用startActivity()方法。
直接启动Activity,不带请求码。
2)在一个Activity中调用startActivityForResult()方法。
带请求码启动Activity。
1.6请求码与响应码
请求码(RequestCode)
在一个业务中可能在两个按钮被单击事件中打开同一个Activity,但我们在onActivityResult事件中如何判断是哪个按钮打开了新的Activity?
请求码就是为解决这个问题的,那么我们打开新的Activity时应该使用startActivityForResult(intent,1);。
其中的第二个参数就是请求码。
结果码(ResultCode)
在一个业务中可能要打开多个不同的Activity,那关闭Activity时在onActivityResult事件中我们如何知道关闭的是哪一个Activity呢?
结果码就是为解决这个问题的,那么我们打开新的Activity时应该使用setResult(2,intent);或在关闭Activity前调用ActivityObj.setResult
(2);。
其中的第一个参数就是结果码。
在onActivityResult事件中,通过判断resultCode更可知道是哪个Activity被关闭了。
2BroadcastReceiver
2.1概念
BroadcastReceiver也就是“广播接收者”的意思,顾名思义,它就是用来接收来自系统和应用中的广播。
2.2应用场景
在Android系统中,广播体现在方方面面:
eg:
1.当开机完成后系统会产生一条广播,接收到这条广播就能实现开机启动服务的功能;
2.当锁屏或者点亮屏幕时就会产生一条广播,接收这条广播就可以实现一些暂停或者开启一些耗电进程的功能。
3.当网络状态改变时系统会产生一条广播,接收到这条广播就能及时地做出提示和保存数据等操作;
4.当电池电量改变时,系统会产生一条广播,接收到这条广播就能在电量低时告知用户及时保存进度;
2.3注册
2.3.1静态注册
2.3.1.1概念
静态注册是在AndroidManifest.xml文件中配置的。
2.3.2动态注册
2.3.2.1概念
动态注册需要在代码中动态的指定广播地址并注册。
2.3.2.2需要注意的事项
RegisterReceiver是android.content.ContextWrapper类中的方法,Activity和Service都继承了ContextWrapper,所以可以直接调用。
在实际应用中,我们在Activity或Service中注册了一个BroadcastReceiver,当这个Activity或Service被销毁时如果没有解除注册,系统会报一个异常,提示我们是否忘记解除注册了。
所以,需要在特定的地方执行解除注册操作:
生命周期的onDestroy()。
有部分广播接受者,涉及到用户的敏感内容,需要在权限文件中声明。
如开机完成的广播,用户电量变化的广播,用户网络状态发生改变的广播
2.3.3生命周期
1.广播接收者的生命周期是非常短暂的,在接收到广播的时候创建,onReceive()方法结束之后销毁
2.广播接收者中不要做一些耗时的工作,否则会弹出ApplicationNoResponse错误对话框
3.最好也不要在广播接收者中创建子线程做耗时的工作,因为广播接收者被销毁后进程就成为了空进程,很容易被系统杀掉
4.耗时的较长的工作最好放在服务中完成
3Service
3.1概念
服务是看不到界面的,,就是一个没有界面的Activity,并且长期在后台运行的一个组件.。
3.2为什么用服务?
进程优先级,回收时是从5~1,从低到高
Foregroundprocess前台进程
Visibleprocess可视进程
Serviceprocess服务进程
Backgroundprocess后台进程
Emptyprocess空进程
回收的优先级:
先回收空进程,一个一个回收的,当内存够用时,不再回收空进程.如果空进程回收完毕后,内存还是不够用时,继续向上一个一个的回收后台进程.依次类推.
当系统内存不够用时,需要回收服务进程时,当系统内存又够用时,会重新启动服务.当用户去手动的把服务关闭时,服务不会再重启了
3.3作用
由于ANR对Activity和BroadcastReceiver响应时间的限制(Activity对事件响应不超过5秒,BroadcastReceiver执行不超过10秒),使得在其中都不适合执行较耗时操作,这样像网络、数据库、复杂计算这类耗时操作的执行就需要一个组件来承担。
Service作为Android四大组件之一,其功能之一就是耗时操作的执行,主要功能如下:
a.执行需要长时间运行的操作,这个操作不与用户进行交互,如网络下载、大文件I/O、复杂计算、监听手机状态。
b.应用内或应用间数据通信,Android每个应用程序都在自己的dalvik虚拟机中运行,一个应用是不允许访问其他应用的内存信息的,为此Android引入了ContentProvider在不同应用间共享数据,BroadcastReceiver广播信息给不同应用程序,但ContentProvider更多用于数据的共享,BroadcastReceiver广播的信息会被所有应用接收较耗费系统资源,对于两个应用间动态的进行交互还需要通过Service来完成。
3.4启动方式
3.4.1直接启动
Activity开启完服务后就不管服务了.Activity和服务没有关系.startService开启的服务, 只有stopService可以关闭
3.4.2绑定启动
绑定服务,生命周期方法会执行:
onUnbind->onDestory服务销毁了.
在activity中调用service中的方法.
步骤:
调用bindService方法绑定服务
1.在Activity中定义一个连接桥的内部类,会在bindService方法传递给service.
2.在service服务中onBind方法中返回一个IBinder接口对象.
3.在service类中定义一个IBinder的内部实现类,在onBind方法返回.
4.当onBinder方法返回完对象后,activity中连接桥里的onServiceConnected会被调用,其中形参IBinderservice就是service类中onBind返回的对象.
5.activity得到了service中的内部类对象,点击按钮是调用内部类中的forwardBuyTicket方法,此方法会转调服务中buyTicket方法.
3.5生命周期
Service的生命周期 (适用于2.1及以上)
1. 被startService的
无论是否有任何活动绑定到该Service,都在后台运行。
onCreate(若需要)->onStart(intid,Bundleargs). 多次startService,则onStart调用多次,但不会创建多个Service实例,只需要一次stop。
该Service一直后台运行,直到stopService或者自己的stopSelf()或者资源不足由平台结束。
2. 被bindService的
调用bindService绑定,连接建立服务一直运行。
未被startService只是BindService,则onCreate()执行,onStart(int,Bund,le)不被调用;这种情况下绑定被解除,平台就可以清除该Service(连接销毁后,会导致解除,解除后就会销毁)。
3. 被启动又被绑定
类似startService的生命周期,onCreateonStart都会调用。
4. 停止服务时
stopService时显式onDestroy()。
或不再有绑定(没有启动时)时隐式调用。
有bind情况下stopService()不起作用。
4ContentProvider
4.1ContentProvider
数据库在Android当中是私有的,当然这些数据包括文件数据和数据库数据以及一些其他类型的数据。
不能将数据库设为WORLD_READABLE,每个数据库都只能创建它的包访问,
这意味着只有由创建数据库的进程可访问它。
如果需要在进程间传递数据,
则可以使用AIDL/Binder或创建一个ContentProvider,但是不能跨越进程/包边界直接来使用数据库。
一个ContentProvider类实现了一组标准的方法接口,从而能够让其他的应用保存或读取此ContentProvider的各种数据类型。
也就是说,一个程序可以通过实现一个ContentProvider的抽象接口将自己的数据暴露出去。
外界根本看不到,也不用看到这个应用暴露的数据在应用当中是如何存储的,或者是用数据库存储还是用文件存储,还是通过网上获得,这些一切都不重要,
重要的是外界可以通过这一套标准及统一的接口和程序里的数据打交道,可以读取程序的数据,也可以删除程序的数据,
当然,中间也会涉及一些权限的问题。
下边列举一些较常见的接口,这些接口如下所示。
·query(Uriuri,String[]projection,Stringselection,String[]selectionArgs,StringsortOrder):
通过Uri进行查询,返回一个Cursor。
·insert(Uriurl,ContentValuesvalues):
将一组数据插入到Uri指定的地方。
·update(Uriuri,ContentValuesvalues,Stringwhere,String[]selectionArgs):
更新Uri指定位置的数据。
·delete(Uriurl,Stringwhere,String[]selectionArgs):
删除指定Uri并且符合一定条件的数据。
4.2ContentResolver
外界的程序通过ContentResolver接口可以访问ContentProvider提供的数据,在Activity当中通过getContentResolver()可以得到当前应用的ContentResolver实例。
ContentResolver提供的接口和ContentProvider中需要实现的接口对应,主要有以下几个。
Øquery(Uriuri,String[]projection,Stringselection,String[]selectionArgs,StringsortOrder):
通过Uri进行查询,返回一个Cursor。
Øinsert(Uriurl,ContentValuesvalues):
将一组数据插入到Uri指定的地方。
Øupdate(Uriuri,ContentValuesvalues,Stringwhere,String[]selectionArgs):
更新Uri指定位置的数据。
Ødelete(Uriurl,Stringwhere,String[]selectionArgs):
删除指定Uri并且符合一定条件的数据。
4.3ContentObserver
在注册,翻译成中文就是内容观察者,目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理。
ContentObserver一般和系统或第三方程序提供的Provider一起使用,这些Provider一般情况下会有一个Uri,然后ContentObserver就去监听这些Uri数据的变化,然后做出相应的处理。
4.4ContentProvider和ContentResolver中用到的Uri
在ContentProvider和ContentResolver当中用到了Uri的形式通常有两种,一种是指定全部数据,另一种是指定某个ID的数据。
我们看下面的例子。
·content:
//contacts/people/这个Uri指定的就是全部的联系人数据。
·content:
//contacts/people/1这个Uri指定的是ID为1的联系人的数据。
在上边两个类中用到的Uri一般由3部分组成。
·第一部分是方案:
"content:
//"这部分永远不变
·第二部分是授权:
"contacts"
·第二部分是路径:
"people/","people/1"(如果没有指定ID,那么表示返回全部)。
由于URI通常比较长,而且有时候容易出错,且难以理解。
所以,在Android当中定义了一些辅助类,并且定义了一些常量来代替这些长字符串的使用,例如下边的代码:
Contacts.People.CONTENT_URI(联系人的URI)。
在我们的实例MyProvider中是如下定义的:
publicstaticfinalStringAUTHORITY="com.teleca.PeopleProvider";
publicstaticfinalStringPATH_SINGLE="people/#";
publicstaticfinalStringPATH_MULTIPLE="people";
publicstaticfinalUricontent_URI=Uri.parse("content:
//"+AUTHORITY+"/"+PATH_MULTIPLE);
5Service如何向Activity传递数据
一个Android程序可以由多个Activity和Servier组成,在这些程序组件之间传递数据的方法有以下几种,每种方法都有其特定的使用途径。
5.1原始数据类型
在Activity/Servier之间传递临时性的原始数据,可以使用Intent的putExtras方法来传递数据。
若传递的数据需要长久保存,则使用SharedPreference类来完成。
5.2传递对象
当在Activity/Servier之间传递不需要长久保存的对象时,可以使用以下几种途径:
(1)通过Application类,每个Android应用程序都有一个Application类。
当你在程序的AndroidManifest.xml中给Application设定一个名字时,你的程序中就必须有一个Application的子类。
这个Application子类会被Android自动实例化,并且是一个全局性的类,它的生命周期和程序的生命周期相同,你可以把一些全局性的对象保存在Application类中。
Application类可以通过getApplication()获得。
(2)通过HashMapofWeakReferences传递对象。
当一个Activity需要向另外一个Activity传递对象时,可以使用一个关键字把对象存在一个HashMap中,并把这个关键字通过Internt的Extras发给目标Activity,目标Activity接到该关键字后使用该关键字把对象从HashMap中取出。
5.3在Activity/Service之间传递需要长久保存的对象时,可以使用以下的方式
1.ApplicationPreferences
2.Files
3.contentProviders
4.SQLiteDB
6AsyncTask
6.1底层处理
底层使用本地线程池机制:
1.核心线程数:
线程池中保存的线程数,包括空闲线程,默认为5个
2.线程池中允许的最大线程数,固定为128个+10个阻塞线程
3.当线程数大于核心线程数时,如果线程池中中线程数大于核心线程数5超过一秒事,终止多余的线程,保留五个核心线程数。
4.执行前用于保持任务的队列,此队列仅保持execute方法提交的Runnable任务,固定容量为10
5.执行程序创建新线程时使用的工厂
6.2AsyncTask介绍
Android的AsyncTask比Handler更轻量级一些(只是代码上轻量一些,而实际上要比handler更耗资源),适用于简单的异步处理。
首先明确Android之所以有Handler和AsyncTask,都是为了不阻塞主线程(UI线程),且UI的更新只能在主线程中完成,因此异步处理是不可避免的。
Android为了降低这个开发难度,提供了AsyncTask。
AsyncTask就是一个封装过的后台任务类,顾名思义就是异步任务。
AsyncTask直接继承于Object类,位置为android.os.AsyncTask。
要使用AsyncTask工作我们要提供三个泛型参数,并重载几个方法(至少重载一个)。
AsyncTask定义了三种泛型类型Params,Progress和Result。
Params启动任务执行的输入参数,比如HTTP请求的URL。
Progress后台任务执行的百分比。
Result后台执行任务最终返回的结果,比如String。
使用过AsyncTask的同学都知道一个异步加载数据最少要重写以下这两个方法:
doInBackground(Params…)后台执行,比较耗时的操作都可以放在这里。
注意这里不能直接操作UI。
此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。
在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。
onPostExecute(Result)相当于Handler处理UI的方式,在这里面可以使用在doInBackground得到的结果处理操作UI。
此方法在主线程执行,任务执行的结果作为此方法的参数返回
有必要的话你还得重写以下这三个方法,但不是必须的:
onProgressUpdate(Progress…)可以使用进度条增加用户体验度。
此方法在主线程执行,用于显示任务执行的进度。
onPreExecu