Android四大组件

Activity和Fragment的生命周期

这个是入门的小白都要知道的东西 ,这里就不详细介绍了,以前的文章里有。

 

Activity常见的生命周期(按下home键、锁屏)

Back键:onPause → onSaveInstanceState → onStop → onDestroy

Home键:onPause → onStop / onRestart → onStart → onResume

锁屏: onPause → onSaveInstanceState → onStop / onRestart → onStart → onResume

A启动B:A:onPause → B:onCreate → B:onStart → B:onResume → A:onSaveInstanceState → A:onStop → A:onDestroy(A是否调用finish)

被打断时(如接电话):onPause → onSaveInstanceState → onStop / onRestart → onStart → onResume

 

异常情况下Activity的生命周期(横竖屏切换、系统资源不足)

横竖屏切换 Activity被销毁:onPause → onSaveInstanceState(与onPause没有时序关系,可能在之前,也可能在之后) → onStop → onDestroy

Activity被重新创建:onCreate → onRestoreInstanceState → onStart → onResume
当不想Activity被重新创建,则需要在Manifest中添加configChanges属性,在Activity中复写onConfigurationChanged方法。

资源内存不足导致低优先级Activity被kill :

①前台Activity —— 正在和用户交互的Activity,优先级最高。

②可见但非前台Activity —— 如Activity弹了一个对话框,导致Activity可见但位于后台,无法与用户直接交互。

③后台Activity —— 已经被暂停的Activity,比如执行了onStop,优先级最低。 当系统内存不足时,会按照优先级去杀死Activity,并通过onSaveInstanceState和onRestoreInstanceState来保存和恢复数据。

 

任务栈

 

任务栈是什么?

任务栈(Task):是一种用来放置Activity实例的容器,它是以栈的形式进行存放,当我们启动一个Application的时候,系统会为它默认创建一个对应的Task,用来放置根Activity。默认启动Activity会放在同一个Task中,新启动的Activity会被压入启动它的那个Activity的栈中,并且显示它。当用户按下回退键时,这个Activity就会被弹出栈,按下Home键回到桌面,再启动另一个应用,这时候之前那个Task就被移到后台,成为后台任务栈,而刚启动的那个Task就被调到前台,成为前台任务栈,Android系统显示的就是前台任务栈中的Top实例Activity。

任务栈的作用是什么?

作用: 由于Android强化了组件概念,弱化了Aplication的概念,所以在Android程序开发中,A应用的A组件想要使用拍照或录像的功能就可以不用去针对Camera类进行开发,直接调用系统自带的摄像头应用(称其B应用)中的组件(称其B组件)就可以了,但是这就引发了一个新问题,A组件运行在A应用中,B组件运行在B应用中,自然都不在同一个进程中,那么从B组件中返回的时候,如何实现正确返回到A组件呢?Task就是来负责实现这个功能的,它是从用户角度来理解应用而建立的一个抽象概念。

 

Activity的启动模式以及应用场景,对应的Intent Flag。

 

启动模式及应用场景:

standard(标准模式)       singleTop(栈顶复用)        singleTask(栈内复用)           singleInstance(单实例模式)

 

standard(标准模式):每次启动一个Activity都会重新创建一个新的实例。 当用ApplicationContext去启动standard模式的Activity时,会报如下错误。

这是因为standard模式的Activity默认会进入启动它的Activity所属的任务栈中,但是由于非Activity类型的Context(如ApplicationContext)并没有任务栈。 解决方法就是为Intent添加FLAG_ACTIVITY_NEW_TASK标记,这样启动的时候就会创建一个新的任务栈,相当于singleTask模式。 以standard方式启动的Activity被跨进程调用,在5.0之前新启动的Activity实例会放入发送Intent的Task的栈的顶部,尽管它们属于不同的程序,在5.0之后,上述情景会创建一个新的Task,新启动的Activity就会放入刚创建的Task中。

 singleTop(栈顶复用):如果新Activity已经位于任务栈的栈顶,那么Activity不会被重新创建,同时它的onNewIntent方法会被调用。如果新Activity不在栈顶,那么新Activity仍会被重新创建。 应用场景:在通知栏点击收到的通知,然后需要启动一个Activity,这个Activity就可以用singleTop,否则每次点击都会新建一个Activity。

singleTask(栈内复用):当一个具有singleTask模式的Activity被启动后,比如Activity A,系统首先会寻找是否存在A想要的任务栈,如果不存在,就重新创建一个任务栈,然后创建A的实例并放入到栈中。如果存在A所需的任务栈,并且存在A的实例,那么系统就会回调A的onNewIntent方法。singleTask具有ClearTop效果,会将位于它以上的Activity实例全部清除出栈。 TaskAffinity属性可以为Activity指定一个任务栈,属性值不能和包名相同,否则就相当于没有指定,因为默认情况下,所有的Activity的任务栈为应用的包名。 当TaskAffinity和singleTask配对使用的时候,待启动的Activity会运行在名字和TaskAffinity形同的任务栈中。

singleInstance(单实例模式):整个手机系统只有一个实例存在,不同的应用去打开这个activity 共享公用的同一个activity。他会运行在自己单独,独立的任务栈里面,并且任务栈里面只有他一个实例存在。应用场景:呼叫来电界面。这种模式的使用情况比较罕见,在Launcher中可能使用。

 

Intent Flag:

有两种方式为Activity指定启动模式:

1、通过AndroidMenifest

2、通过Intent设置标识来启动。

第二种的优先级高于第一种,当两种方式同时存在时,以第二种方式为准。

FLAG_ACTIVITY_NEW_TASK:指定singleTask启动模式。
FLAG_ACTIVITY_SINGLE_TOP:指定singleTop启动模式。
FLAG_ACTIVITY_CLEAR_TOP:当Activity启动时,在统一任务栈中所有位于它上面的Activity都要出栈。一般和FLAG_ACTIVITY_NEW_TASK配合使用,在这种情况下,如果被启动的Activity实例已经存在,系统就会回调onNewIntent方法;如果被启动的Activity采用的时standard模式,那么它连同它之上的Activity都要出栈,系统会创建新的Activity实例并放入栈顶。

 

IntentFilter匹配规则:

Activit的启动模式分为显示调用和隐式调用,如果两者同时出现以显示调用为主。

action匹配规则:

Intent中的action必须能够和过滤规则中的action完全匹配(action的字符串值完全一样)。一个过滤规则中可以有多个action,只要Intent中的action存在且必须和过滤规则中的其中一个action相同。

category匹配规则:

Intent中如果携带category,那么所有的category都必须和过滤规则中的其中一个相同。 如果不设置category,那么系统在调用startActivity或者startActivityForResult的时候就会默认为Intent加上"android.intent.category.DEFAULT",为了Activity能够接收隐士调用,就必须在intent-filter中指定"android.intent.category.DEFAULT"。

data匹配规则:

data的匹配规则和action类似,如果过滤规则中定义了data,那么Intent中必须也要定义可匹配的data。

①如果Intent中的mimeType属性为"image/*",这种情况下虽然没有指定URI,但却又默认值,URL的默认值为content和file,也就是说,虽然没有指定URI,但是Intent中的URI部分的schema必须为content或者file才能匹配。

②如果要为Intent指定完整的data,必须要调用setDataAndType方法,不能先调用setData再调用setType,因为这两个方法会彼此清除掉对方的值。

当我们通过隐士方式启动一个Activity的时候,可以通过PackageManager的resolveActivity方法或者Intent的resolveActivity方法来进行判断。PackageManager还提供了queryIntentActivities方法。

 

Service生命周期与Intentservice的区别

IntentService是一个基于Service的一个类,用来处理异步的请求。你可以通过startService(Intent)来提交请求,该Service会在需要的时候创建,当完成所有的任务以后自己关闭,且请求是在工作线程处理的。


IntentService最起码有两个好处:

① 不需要自己去new Thread。

② 不需要考虑在什么时候关闭该Service。

 

startService和bindService混合使用的场景

startService:

调用onCreate()->onStartCommand() bindService:调用onBind() stopService:没有调用onDestory() Service仍然在运行! unbindService:调用onUnbind()->onDestory() 此时Service关闭!

startService:

调用onCreate()->onStartCommand() bindService:调用onBind() unbindService:调用onUnbind() Service仍然在运行! stopService:调用onDestory() 此时Service才关闭!

若被停止的服务依然有ServiceConnection 与其绑定,则服务不能销毁,直至我们把所有ServiceConnection 解绑。

当所有ServiceConnection 解绑后,系统会自动销毁服务。不包括同时用startService()启动的情况。此时,我们不得不再调用一次stopService来销毁它。

 

广播的两种注册方式(有什么区别)

静态注册:

静态注册的广播接收器即使app已经退出,主要有相应的广播发出,依然可以接收到(但此种描述自Android 3.1开始有可能不再成立)。 自Android3.1开始,系统本身则增加了对所有app当前是否处于运行状态的跟踪。在发送广播时,不管是什么广播类型,系统默认直接增加了值为FLAG_EXCLUDE_STOPPED_PACKAGES的flag,导致即使是静态注册的广播接收器,对于其所在进程已经退出的app,同样无法接收到广播。 由此,对于系统广播,由于是系统内部直接发出,无法更改此intent flag值,因此,3.1开始对于静态注册的接收系统广播的BroadcastReceiver,如果App进程已经退出,将不能接收到广播。

动态注册:

当此Activity销毁时,动态注册的广播接收器将不再接收到相应的广播。

 

怎么增加广播的安全性?

Android中的广播可以跨进程甚至跨App直接通信,且注册是exported对于有intent-filter的情况下默认值是true,由此将可能出现安全隐患如下:

  1. 其他App可能会针对性的发出与当前App intent-filter相匹配的广播,由此导致当前App不断接收到广播并处理;

  2. 其他App可以注册与当前App一致的intent-filter用于接收广播,获取广播具体信息。

无论哪种情形,这些安全隐患都确实是存在的。由此,最常见的增加安全性的方案是:

对于同一App内部发送和接收广播,将exported属性人为设置成false,使得非本App内部发出的此广播不被接收;

在广播发送和接收时,都增加上相应的permission,用于权限验证;

发送广播时,指定特定广播接收器所在的包名,具体是通过intent.setPackage(packageName)指定在,这样此广播将只会发送到此包中的App内与之相匹配的有效广播接收器中。

App应用内广播(LocalBroadcast),广播的发送者和接收者都同属于一个App。 相比于全局广播,App应用内广播优势体现在:

①安全性更高。

②更加高效。

 

                                                                                                                                                       

 

 

 

 

 

 

 

 

你可能感兴趣的:(Android四大组件)