一、 Android四大组件之一:Activity
Activty的生命周期的也就是它所在进程的生命周期。如图所示: 一个Activity的启动顺序:
onCreate()——>onStart()——>onResume() 当另一个Activity启动时: 第一个Activity onPause()—>第二个Activity onCreate()—>onStart()—>onResume() ——>第一个Activity onStop() //当第二个activity完全挡住第一个的时候才会执行 当返回到第一个Activity时: 第二个Activity onPause() ——> 第一个Activity onRestart()——>onStart()——>onResume() ——>第二个Activity onStop()——>onDestroy() 一个Activity的销毁顺序: (情况一)onPause()——> (情况二)onPause()——>onStop()——> (情况三)onPause()——>onStop()——>onDestroy() 每一个活动(
但是当一个活动的状态发生改变的时候,开发者可以通过调用 在实现 override )这些方法即可在你需要处理的时候来调用。 各个状态描述:
一、 onCreate :当活动第一次启动的时候,触发该方法,可以在此时完成活动的初始化工作。
onCreate 方法有一个参数,可以为空(null),也可以是之前调用onSaveInstanceState()方法保存的状态信息。 二、 onStart :该方法的触发表示所属活动将被展现给用户。
三、 onResume :当一个活动和用户发生交互的时候,触发该方法。
四、 onPause :当一个正在前台运行的活动因为其他的活动需要前台运行而转入后台运行的时候,触发该方法。这时候需要将活动的状态持久化,比如正在编辑的数据库记录等。
五、 onStop :当一个活动不再需要展示给用户的时候,触发该方法。如果内存紧张,系统会直接结束这个活动,而不会触发 onStop 方法。 所以保存状态信息是应该在onPause时做,而不是onStop时做。活动如果没有在前台运行,都将被停止或者Linux管理进程为了给新的活动预留足够的存储空间而随时结束这些活动。因此对于开发者来说,在设计应用程序的时候,必须时刻牢记这一原则。在一些情况下,onPause方法或许是活动触发的最后的方法,因此开发者需要在这个时候保存需要保存的信息。
六、onRestart :当处于停止状态的活动需要再次展现给用户的时候,触发该方法。
七、 onDestroy :当活动销毁的时候,触发该方法。和 onStop 方法一样,如果内存紧张,系统会直接结束这个活动而不会触发该方法。
八、onWindowFocusChanged方法:在Activity窗口获得或失去焦点时被调用,有如下几种情况:
1) 创建时首次呈现在用户面前;
2) 当前Activity被其他Activity覆盖;
3) 当前Activity转到其他Activity或按Home键回到主屏,自身退居后台;
4) 用户退出当前Activity。
注:并且当Activity被创建时是在onResume之后被调用,当Activity被覆盖或者退居后台或者当前Activity退出时,它是在onPause之后被调用,如图所示:
这个方法在某种场合下还是很有用的,例如程序启动时想要获取视特定视图组件的尺寸大小,在onCreate中可能无法取到,因为窗口Window对象还没创建完成,这个时候我们就需要在onWindowFocusChanged里获取;如果大家已经看过我写的Android动画之Frame Animation这篇文章就会知道,当时试图在onCreate里加载frame动画失败的原因就是因为窗口Window对象没有初始化完成,所以最后我将加载动画的代码放到了onWindowFocusChanged中,问题迎刃而解。
九、onSaveInstanceState方法:有如下几种情况会被调用:
1) 在Activity被覆盖或退居后台之后,系统资源不足将其杀死;
2) 在用户改变屏幕方向时;
3) 在当前Activity跳转到其他Activity或者按Home键回到主屏,自身退居后台时。
第一种情况我们无法保证什么时候发生,系统根据资源紧张程度去调度;
第二种是屏幕翻转方向时,系统先销毁当前的Activity,然后再重建一个新的,调用此方法时,我们可以保存一些临时数据;比如说在一串字符串中的光标所处的位置等。
第三种情况系统调用此方法是为了保存当前窗口各个View组件的状态。
通常情况下,开发者不需要重写覆盖该方法,在默认的实现中,已经提供了自动保存活动所涉及到的用户界面组件的所有状态信息。
注:onSaveInstanceState的调用顺序是在onPause之前。
十、onRestoreInstanceState方法:有如下几种情况会被调用:
1) 在Activity被覆盖或退居后台之后,系统资源不足将其杀死,然后用户又回到了此Activity;
2) 在用户改变屏幕方向时,重建的过程中,我们可以重写此方法,以便可以恢复一些临时数据。
注:onRestoreInstanceState的调用顺序是在onStart之后。
为了避免这样销毁重建的过程,我们需要在AndroidMainfest.xml中对OrientationActivity对应的配置android:configChanges="orientation"
注:如果配置了android:screenOrientation属性,则会使android:configChanges="orientation"失效。
1) 在android里,有4种activity的启动模式,分别为:
standard: 标准模式,是默认的启动模式,不用为配置android:launchMode属性即可,当然也可以指定值为standard。一调用startActivity()方法就会产生一个新的实例。 2) singleTop: 如果已经有一个实例位于Activity栈的顶部时,就不产生新的实例,而只是调用Activity中的newInstance()方法。如果不位于栈顶,会产生一个新的实例
3) singleTask:如果发现有对应的Activity实例,则使此Activity实例之上的其他Activity实例统统出栈,使此Activity实例成为栈顶对象,显示到幕前。
4) singleInstance: 这种启动模式比较特殊,因为它会启用一个新的栈结构,将Acitvity放置于这个新的栈结构中,并保证不再有其他Activity实例进入。这个跟singleTask基本上是一样,只有一个区别:在这个模式下的Activity实例所处的task中,只能有这个activity实例,不能有其他的实例。
在AndroidManifest.xml配置的android:launchMode属性为以上四种之一即可。
转自:
Activity的Flag和Activity的元素的特性值交互控制。Task把不同的应用程序组织在一起
所属task的区别 一般情况下,“standard”和”singleTop”的activity的目标task,和收到的Intent的发送者在同一个task内,就相当于谁调用它,它就跟谁在同一个Task中。 除非Intent包括参数FLAG_ACTIVITY_NEW_TASK。如果提供了FLAG_ACTIVITY_NEW_TASK参数,会启动到别的task里。 “singleTask”和”singleInstance” 总是把要启动的activity作为一个task的根元素,他们不会被启动到一个其他task里。 是否允许多个实例 “standard”和”singleTop”可以被实例化多次,并且是可以存在于不同的task中;这种实例化时一个task可以包括一个activity的多个实例; “singleTask”和”singleInstance”则限制只生成一个实例,并且是task的根元素。 singleTop 要求如果创建intent的时候栈顶已经有要创建的Activity的实例,则将intent发送给该实例,而不创建新的实例。 是否允许其它activity存在于本task内 “singleInstance”独占一个task,其它activity不能存在那个task里; 如果它启动了一个新的activity,不管新的activity的launch mode 如何,新的activity都将会到别的task里运行(如同加了FLAG_ACTIVITY_NEW_TASK参数)。 而另外三种模式,则可以和其它activity共存。 是否每次都生成新实例 “standard”对于每一个启动Intent都会生成一个activity的新实例; “singleTop”的activity如果在task的栈顶的话,则不生成新的该activity的实例,直接使用栈顶的实例,否则,生成该activity的实例。 比如: 现在task栈元素为A-B-C-D(D在栈顶),这时候给D发一个启动intent,如果D是 “standard”的,则生成D的一个新实例,栈变为A-B-C-D-D。 如果D是singleTop的话,则不会生产D的新实例,栈状态仍为A-B-C-D 如果这时候给B发Intent的话,不管B的launchmode是”standard” 还是 “singleTop” ,都会生成B的新实例,栈状态变为A-B-C-D-B。 “singleInstance”是其所在栈的唯一activity,它会每次都被重用。 “singleTask” 如果在栈顶,则接受intent,否则,该intent会被丢弃,但是该task仍会回到前台。 当已经存在的activity实例处理新的intent时候,会调用onNewIntent()方法,如果收到intent生成一个activity实例,那么用户可以通过back键回到上一个状态;如果是已经存在的一个activity来处理这个intent的话,用户不能通过按back键返回到这之前的状态。 (一)、Service的概念
Service是Android程序中四大基础组件之一,它和Activity一样都是Context的子类,只不过它没有UI界面,是在后台执行长时间操作的组件。
注:任何一个service不管它是怎么启动的,都会默许客户端绑定到它,因此可以在任何service上调用onBound()和onUnBound()
(二)、Service的生命周期
Service对象不能自己启动,需要通过某个Activity、Service或者其他Context对象来启动。启动的方法有两种:Context.startService和Context.bindService()。
这两种模式有以下几点不同之处:
startService模式下调用者与服务无必然联系,即使调用者结束了自己的生命周期,只要没有使用stopService方法停止这个服务,服务仍会运行;
bindService模式下服务是与调用者生死与共的,在绑定结束之后,一旦调用者被销毁,服务也就立即终止。
如果我们先以startService方式启动服务,然后再用bindService绑定到这个服务,之后使用unbindService解除绑定,此时服务并不会因此而终止,而是继续运行,直到我们使用stopService来停止这个服务。
即:由startService启动的Service必须要有stopService来结束,不调用stopService则会造成Activity结束了而Service还运行着。而且不能返回执行结果,不能和启动service的组件进行交互!
由bindService启动的Service可以由unbindService来结束,也可以在Activity结束之后(onDestroy)自动结束。组件和service建立一个长连接,可以和service交互!被绑定的service通常不能再用startservice方式启动,可以获得启动的service的实例
具体如下所示。
1、 Context.startService方式的生命周期:
<IGNORE_JS_OP style="WORD-WRAP: break-word"> 启动时,startService–> onCreate() –> onStartCommand () ->Service running
停止时,stopService–> onDestroy()->Service stop 注:如果Service还没有运行,则android先调用onCreate()然后调用onStartCommand();如果Service已经运行,则只调用onStartCommand(),所以一个Service的onStartCommand()方法可能会重复调用多次.
stopService的时候直接onDestroy,如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行.该Service的调用者再启动起来后可以通过stopService关闭Service. 所以调用startService的生命周期为:onCreate --> onStartCommand(可多次调用) --> onDestroy 2、Context.bindService方式的生命周期:
绑定时,bindService -> onCreate() –> onBind() ->Servicerunning
解绑定时,unbindService–>onUnbind() –> onDestory()->Service stop 注:onBind将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service运行的状态或其他操作.这个时候把调用者(Context,例如Activity)会和Service绑定在一起,Context退出了,Srevice就会调用onUnbind->onDestroy相应退出. 所以调用bindService的生命周期为:onCreate --> onBind(只一次,不可多次绑定) --> onUnbind -->onDestory. 在Service每一次的开启关闭过程中,只有onStartCommand可被多次调用(通过多次startService调用),其他onCreate,onBind,onUnbind,onDestory在一个生命周期中只能被调用一次. 使用方法:Service跟Activity一样也由Intent调用。在工程里想要添加一个Service,先新建继承Service的类,然后到 AndroidManifest.xml -> Application->Application Nodes中的Service标签中添加。Intent负责传递参数。
1、在activity中利用意图调用startService(intent)方法,启动一个service服务。如下:
Intent intent = new Intent();
intent.setClass(MainActivity.this, SecondActivity.class);
startService(intent);
2、在继承了service的类中创建一个线程(一般在onStartCommand()中写):
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
//在这里写线程要操作的方法
for (int i = 0; i < 30; i++){
Log.i("Thread",i + "");
try {
Thread.sleep(1000);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
stopSelf();//在操作完自关闭线程
}
});
thread.start();//启动线程
注意:要特别注意onStartCommand()方法中的返回值(return),值不同效果不同!
当该进程被杀了之后,系统会重新启动!
如果service里就做一件事情,则用IntentService,不需要创建线程了!
public classSecondActivity extends IntentService {
public SecondActivity() {
super("");
//这个构造器有改动,请注意!
}
@Override
protected void onHandleIntent(Intentintent) {
// TODO Auto-generated method stub
for (int i = 0; i < 30; i++){
Log.i("Thread",i + "");
try {
Thread.sleep(1000);
}catch(InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
三、Android四大组件之三:
(一)、BroadcastReceiver简介
Broadcast(广播)是一种广泛运用在应用程序之间传输信息的机制。
broadcastReceiver是对发送出来的broadcast进行过滤接受并响应的一类组件。
1、无序广播(也叫普通广播(Normalbroadcasts))
(1)是完全异步执行的广播
(2)没有指定广播接收器的运行顺序(即可以在同一时刻(逻辑上)被所有接收者接收到)
(3)优点:效率最高
(4)接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播。 2、有序广播(Ordered broadcasts)
(1)有序广播是按照接收者声明的优先级别,被接收者依次接收广播。如: A的级别高于B,B的级别高于C,那么,广播先传给A,再传给B,最后传给C 。优先级别声明在 intent-filter 元素的 android:priority 属性中,数越大优先级别越高,取值范围:-1000到1000,优先级别也可以调用IntentFilter对象的setPriority()进行设置 。
(2)同一时间只有一个广播接收器在处理广播,按照指定的顺序交给下一个广播接收器
(3) 可以传递运行的结果
(4) 可以终止广播Intent的传播。广播Intent的传播一旦终止,后面的接收者就无法接收到广播。
注: Context.sendBroadcast()
发送的是普通广播,所有订阅者都有机会获得并进行处理。 Context.sendOrderedBroadcast() 发送的是有序广播,系统会根据接收者声明的优先级别按顺序逐个执行接收者, (1)静态注册:
在AndroidManifest.xml中用标签声明注册,并在标签内用标签设置过滤器。如:
(2)动态注册: 一般在Activity.onResume()方法中使用Context.registerReceiver()方法来注册一个广播接收器,在Activity.onPause()中使用unregisterReceiver(r)方法注销一个广播接收器,
一般在onStart中注册,onStop中取消unregisterReceiver
在代码中先定义并设置好一个 IntentFilter对象,然后在需要注册的地方调 Context.registerReceiver()方法,如果取消时就调用Context.unregisterReceiver()方法。如果用动态方式注册的BroadcastReceiver的Context对象被销毁时,BroadcastReceiver也就自动取消注册了。 如:
IntentFilter intentFilter = newIntentFilter();
intentFilter.addAction(String); //String为action,用于接收同action的广播
registerReceiver(BroadcastReceiver,intentFilter);
注意:
1、若在使用sendBroadcast()的方法是指定了接收权限,则只有在AndroidManifest.xml中用标签声明了拥有此权限的BroascastReceiver才会有可能接收到发送来的Broadcast。
2、BroadcastReceiver使用步骤:
2、若在注册BroadcastReceiver时指定了可接收的Broadcast的权限,则只有在包内的AndroidManifest.xml中 用标签声明了,拥有此权限的Context对象所发送的Broadcast才能被这个 BroadcastReceiver所接收。 1、//构建一个类继承自BroadcastReceiver
public class SystemEventReceiver extendsBroadcastReceiver {};
2、重写public voidonReceive(Context context, Intent intent)方法
3、 在要发送广播的地方,把要发送的信息和用于过滤的信息(Action、Category)装入Intent对象,通过调用sendOrderBroadcast()和sendStickyBroadcast()方法,把Intent发送出去。
如:
static final String INTENAL_ACTION_1="com.cuc.miti.BroastcastReceiver.Internal_1";
Intent intent=new Intent(INTENAL_ACTION_1); //action
sendBroadcast(intent); //发送广播事件
4、BroadcastReceiver注册,检查IntentFilter是否与发送的Intent相匹配,若匹配,则调用BroadcastReceiver的onReceiver()方法, 将含消息的intent对象传回。
5、Intent是一个对动作和行为的抽象描述,负责组件之间程序之间进行消息传递。那么BroadcastReceiver组件就提供了一种把Intent作为一个消息广播出去,由所有对其感兴趣的程序对其作出反应的机制。
二、BroadcastReceiver接收系统自带的广播
注:需要在AndroidManifest.xml中注册此Receiver
android系统中定义的Broadcast Action来响应系统的广播件:
ACTION_BOOT_COMPLETED (系统启动完成后触发) ACTION_TIME_CHANGED 时间改变时触发
ACITON_DATE_CHANGED 日期改变时触发
ACTION_TIMEZONE_CHANGED 时区改变时触发
ACTION_BATTERY_LOW 电量低时触发
ACTION_BATTERY_CHANGED (电量低时触发)
ACTION_MEDIA_EJECT 插入或拔出外部媒体
ACTION_MEDIA_BUTTON 按下媒体按钮时触发
ACTION_PACKAGE_ADDED 添加包时触发
ACTION_PACKAGE_REMOVED 删除包时触发
AlarmManager中常用的属性和方法
ELAPSED_REALTIME设置闹钟时间,从系统启动开始
ELAPSED_REALTIME_WAKEUP设置闹钟时间,从系统启动开始,如火设备休眠则唤醒
INTERVAL_DAY设置闹钟时间,间隔一天
INTERVAL_FIFTEEN_MINUTES间隔15分钟
INTERVAL_HALF_DAY间隔半天
INTERVAL_HALF_HOUR间隔半小时
INTERVAL_HOUR间隔1小时
RTC设置闹钟时间,从系统当前时间开始(System.currentTimeMillis())
RTC_WAKEUP设置闹钟时间,从系统当前时间开始,设备休眠则唤醒
set(int type,long tiggerAtTime,PendingIntent operation)设置在某个时间执行闹钟
setRepeating(int type,long triggerAtTiem,long interval,PendingIntentoperation)
设置在某个时间重复执行闹钟
setInexactRepeating(int type,long triggerAtTiem,longinterval,PendingIntent operation)
是指在某个时间重复执行闹钟,但不是间隔固定时间
四、Android四大组件之四:1、基本概念
1) contentprovider为存储和获取数据提供了统一的接口
2) 使用contentprovider可以在不同的应用程序之间共享数据
3) android为常见的一些数据提供了contentprovider(包括音频、视频、图片、通讯录等等)
contentprovider使用表的形式来组织数据
Content Provider 定义一个URI访问指定的数据,进行数据的增、删、改、查。
2、contentprovider都存放在3、4、实现contentprovider的过程
1) 定义一个content_URI常量
2) 定义一个类,继承contentprovider
3) 实现查询等方法
4) 在androidManifest.xml当中进行声明
(二)、使用现成的Content Provider,如:通讯录
(三)、定义自己的Content Provider
|