Activity及生命周期.docx
《Activity及生命周期.docx》由会员分享,可在线阅读,更多相关《Activity及生命周期.docx(19页珍藏版)》请在冰豆网上搜索。
Activity及生命周期
AndroidActivity生命周期
一般来说Android程序主要由下列4部分组成
·Activity
·BroadcastReceiver
·Service
·ContentProvider
Activity介绍
·一个应用程序是由一个或者多个Activity组成
·一个Activity代表了可以和用户进行交互的可视化界面。
·Activity在Android应用的onCreate中初始化通过布局管理添加各种View组件
·通过setContentView(int)方法可以将视图呈现出来
BroadcastReceiver介绍
·BroadcastReceiver负责对外部事件做出响应
·BroadcastReceiver不生成UI,是不可见的
·BroadcastReceiver需要在程序中进行注册
·应用程序可以通过Context.sendBroadcast()将自己的intent广播出去。
其他程序通过自身的BroadcastReceivers截获后进行时间处理。
Service介绍
·service运行在后台,负责处理一些用户看不到,并且会有持续时间的事情。
比如下载数据,播放音乐等。
·service是跑在程序的主线程中,处理耗时的事件续
·service没有用户界面
·所有用户实现的service必须继承系统的Service类,并且在配置文件中进行注册。
ContentProvider介绍
·数据在Android当中是程序私有的
·ContentProvider提供了多个程序间数据交互的机制。
·ContentProvider暴露出来一些标准的API来对数据进行操作:
1.query(Uri,String[],String,String[],String):
通过关键字查询数据
2.insert(Uri,ContentValues):
将一组数据插入到指定的地方
3.update(Uri,ContentValues,String,String[]):
更新数据
4.delete(Uri,String,String[]):
删除数据
Activity其实是继承了ApplicationContext这个类,我们可以重写以下方法,如下代码:
publicclassActivityextendsApplicationContext{
protectedvoidonCreate(BundlesavedInstanceState);
protectedvoidonStart();
protectedvoidonRestart();
protectedvoidonResume();
protectedvoidonPause();
protectedvoidonStop();
protectedvoidonDestroy();
}
便于理解上图示中的生命周期见HelloAndroidActivity.java.我们运行调试。
通过图示和分析程序得出三种生命周期:
1.整体生命周期:
onCreate()-……..->onDestory();
2.可视生命周期:
onStart-……..->onStop();
3.活动生命周期(或者称为焦点生命周期):
onResume()-……..->onPause();
1、程序启动运行Activity执行顺序:
onCreate()->onStart()->onResume三个方法,见LogCat。
程序启动。
2、BACK键等退出销毁,Activity先后执行:
onPause()->onStop()->onDestory()三个方法,见LogCat。
程序销毁退出。
3、HOME键等运行中被打断时(比如突然打入电话),Activity先后执行:
onPause()->onStop()这两个方法。
此时程序并未退出,只是在保存于后台状态栈中。
4、再次启动应用程序时,则先后分别执行了onRestart()->onStart()->onResume()三个方法,重新调出程序到前台显示。
!
!
!
引出一个问题,当我们按HOME键或程序运行中被打断时,我们应用的状态如何保存(举例)?
(见演示)
几点总结:
onCreate:
在这里创建界面,做一些数据的初始化工作。
onStart:
到这一步变成用户可见不可交互的。
onResume:
变成和用户可交互的,(在activity栈系统通过栈的方式管理这些个Activity的最上面,运行完弹出栈,则回到上一个Activity)
onPause:
到这一步是可见但不可交互的,系统会停止动画等消耗CPU的事情,从上文演示中已经知道,应该在这里保存一些数据,因为这个时候本程序的优先级降低,有可能被系统收回。
在这里保存的数据,应该在onResume里读出来,注意:
这个方法里做的事情时间要短,因为下一个activity不会等到这个方法完成才启动
onstop:
变得不可见,被下一个activity覆盖了
onDestroy:
这是activity被干掉前最后一个被调用方法了,可能是外面类调用finish方法或者是系统为了节省空间将它暂时性的干掉,可以用isFinishing()来判断它,如果你有一个ProgressDialog在线程中转动,请在onDestroy里把他cancel掉,不然等线程结束的时候,调用Dialog的cancel方法会抛异常的。
由上:
由于android系统中,Activit生命周期、内存管理等都是交给系统自动管理的,实际工作中因为生命周期的变化而带来的问题也很多,onPause,onstop,onDestroy三种状态下activity都有可能被系统管理机制给干掉,丢失数据及状态,所以为了保证程序的正确性与合理性,所以特别注意onPause()里数据的处理,比如写上持久层操作的代码,将用户编辑的内容都保存到存储介质上(一般都是数据库,还有xml等)。
当然我们一般是采用Android的消息机制[Handler,Message]来处理多线程和界面交互的问题来避免这些状态丢失问题,后边讲。
注意各个事件的处理,状态的保存;同时以后的开发中注意,当Activity某一个生命周期运行时间过长,占用内存过大时,注意防止被android自动内存管理回收机制给干掉。
1.1强制保持AndroidActivity状态
有的时候我们的Android在应用运行时,可能需要临时退出,比如突然接到来电,但是切换回来界面时,可能Activity又重新从第一个界面开始显示,并不是刚才用户操作的界面,这里可以通过在androidmanifest.xml中在需要保留的activity中添加android:
alwaysRetainTaskStat="true"这句即可,这里要提醒大家的是有时候你的应用可能会产生多个实例,你还可以在主Activity中加入android:
launchMode="singleInstance"来强制让系统仅运行一个实例。
2.Android开机自启动程序
背景知识:
当Android启动时,会发出一个系统广播,内容为ACTION_BOOT_COMPLETED,它的字符串常量表示为android.intent.action.BOOT_COMPLETED。
只要在程序中“捕捉”到这个消息,再启动之即可。
记住,Android框架说:
Don''tcallme,I''llcallyouback。
我们要做的是做好接收这个消息的准备,而实现的手段就是实现一个BroadcastReceiver。
Android应用的工程文件组成
·src源文件(java文件)
·R.java文件
·assets目录
·res目录(资源)
·drawable目录
·layout目录
·values目录
AndroidManifest.xml
·声明应用程序的构成
·程序包的全局变量
·活动(Activities)
·内容管理器(ContentProviders)
·服务(Services)
·广播接收器(BroadcastReceivers)
·请求安全授权(uses-permission)
·声明安全授权(permission)
AndroidManifest.xml文件剖析
对于Android全局配置文件AndroidManifest.xml完整的结构以及每个节点的作用。
在我们日常的开发中都少不了下面的配置,每创建一个Activity、Service都离不开这个全局配置文件,深入的了解可以简化程序代码以及提高程序的维护性。
在最外层包含了包名、软件的版本 android:
versionCode="1"以及 android:
versionName="1.0",里面一层的application分支中将可能包含Android程序的四种对象Activity、Service、ContentProvider以及Receiver。
我们每添加上面四个类型中的任一新对象都需要在androidmanifest.xml文件中添加相应节点。
其中Activity的属性常用的可能为android:
name和android:
label但我们需要了解所有的属性以帮助解决复杂的问题,完整的如下:
android:
allowTaskReparenting=["true"|"false"]
android:
alwaysRetainTaskState=["true"|"false"]
android:
clearTaskOnLaunch=["true""|"false"]
android:
configChanges=[oneormoreof:
"mcc""mnc""locale"
"touchscreen""keyboard""keyboardHidden"
"navigation""orientation""fontScale"]
android:
enabled=["true"|"false"]
android:
excludeFromRecents=["true"|"false"]
android:
exported=["true"|"false"]
android:
finishOnTaskLaunch=["true"|"false"]
android:
icon="drawableresource"
android:
label="stringresource"
android:
launchMode=["multiple"|"singleTop"|
"singleTask"|"singleInstance"]
android:
multiprocess=["true"|"false"]
android:
name="string"
android:
noHistory=["true"|"false"]
android:
permission="string"
android:
process="string"
android:
screenOrientation=["unspecified"|"user"|"behind"|
"landscape"|"portrait"|
"sensor"|"nonsensor"]
android:
stateNotNeeded=["true"|"false"]
android:
taskAffinity="string"
android:
theme="resourceortheme"
android:
windowSoftInputMode=[oneormoreof:
"stateUnspecified"
"stateUnchanged""stateHidden"
"stateAlwaysHidden""stateVisible"
"stateAlwaysVisible""adjustUnspecified"
"adjustResize""adjustPan"]>
有关AndroidManifest.xml文件的application分支我们有必要了解一些常见的属性,这里可以看到一些我们实用的选项,比如允许调试android:
debuggable、任务关系android:
taskAffinity,比如我们常见的方式创建一个新的任务实用标记FLAG_ACTIVITY_NEW_TASK,为程序制定一个主题,可以使用android:
theme指向一个主题文件。
平时我们创建的程序使用一些安全敏感项,会需要请求系统许可权限,这里可以使用android:
permission来制定相关的许可,每个程序的service、activity、contentprovider、receiver都需要在application的节点内实现。
有关完整的属性可以查看:
allowClearUserData=["true"|"false"]
android:
allowTaskReparenting=["true"|"false"]
android:
debuggable=["true"|"false"]
android:
description="stringresource"
android:
enabled=["true"|"false"]
android:
hasCode=["true"|"false"]
android:
icon="drawableresource"
android:
label="stringresource"
android:
manageSpaceActivity="string"
android:
name="string"
android:
permission="string"
android:
persistent=["true"|"false"]
android:
process="string"
android:
taskAffinity="string"
android:
theme="resourceortheme">
...
有关Androidmanifest.xml文件中的数据提供,我们来看下Provider节点中用到的定义,可以看到包含了权限控制、排序方式完整的如下:
authorities="list"
android:
enabled=["true"|"false"]
android:
exported=["true"|"false"]
android:
grantUriPermissions=["true"|"false"]
android:
icon="drawableresource"
android:
initOrder="integer"
android:
label="stringresource"
android:
multiprocess=["true"|"false"]
android:
name="string"
android:
permission="string"
android:
process="string"
android:
readPermission="string"
android:
syncable=["true"|"false"]
android:
writePermission="string">
而对于服务相关定义如下:
enabled=["true"|"false"]
android:
exported[="true"|"false"]
android:
icon="drawableresource"
android:
label="stringresource"
android:
name="string"
android:
permission="string"
android:
process="string">
最后是Broadcast使用的Receiver定义,一般配合和隐式处理。
enabled=["true"|"false"]
android:
exported=["true"|"false"]
android:
icon="drawableresource"
android:
label="stringresource"
android:
name="string"
android:
permission="string"
android:
process="string">
Android蓝牙API之BluetoothAdapter类
(1)
使用BluetoothAdapter类,你能够在Android设备上查找周边的蓝牙设备然后配对(绑定),蓝牙通讯是基于唯一地址MAC来相互传输的,考虑到安全问题Bluetooth通讯时需要先配对。
然后开始相互连接,连接后设备将会共享同一个RFCOMM通道以便相互传输数据,目前这些实现在Android2.0或更高版本SDK上实现。
一、查找发现findding/discoveringdevices
对于Android查找发现蓝牙设备使用BluetoothAdapter类的startDiscovery()方法就可以执行一个异步方式获取周边的蓝牙设备,因为是一个异步的方法所以我们不需要考虑线程被阻塞问题,整个过程大约需要12秒时间,这时我们紧接着注册一个BroadcastReceiver对象来接收查找到的蓝牙设备信息,我们过滤ACTION_FOUND这个Intent动作来获取每个远程设备的详细信息,通过附加参数在Intent字段EXTRA_DEVICE和EXTRA_CLASS,中包含了每个BluetoothDevice对象和对象的该设备类型BluetoothClass,示例代码
privatefinalBroadcastReceivercwjReceiver=newBroadcastReceiver(){
publicvoidonReceive(Contextcontext,Intentintent){
Stringaction=intent.getAction();
if(BluetoothDevice.ACTION_FOUND.equals(action)){
BluetoothDevicedevice=intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
myArrayAdapter.add(device.getName()+"android123"+device.getAddress());//获取设备名称和mac地址
}
}
};
// 注册这个BroadcastReceiver
IntentFilterfilter=newIntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(cwjReceiver,filter);
最后android123提醒大家需要注意的是,记住在Service或Activity中重写onDestory()方法,使用unregisterReceiver方法反注册这个BroadcastReceiver对象保证资源被正确回收。
一些其他的状态变化有ACTION_SCAN_MODE_CHANGED额外参数EXTRA_SCAN_MODE 和EXTRA_PREVIOUS_SCAN_MODE以及SCAN_MODE_CONNECTABLE_DISCOVERABLE、SCAN_MODE_CONNECTABLE和SCAN_MODE_NONE,
二、配对绑定bnded/paireddevice
在Android中配对一个蓝牙设备可以调用BluetoothAdapter类的getBondedDevices()方法可以获取已经配对的设备,该方法将会返回一个BluetoothDevice数组来区分每个已经配对的设备,示例代码如下:
SetpairedDevices=cwjBluetoothAdapter.getBonded