Android-四大组件2

版权声明:个人见解,希望可以帮助大家,共同进步. https://blog.csdn.net/weixin_40783315/article/details/84997507

                                       四大组件

1、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

2、异常情况下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来保存和恢复数据。

3、什么是Activity任务栈。

- 是什么:

任务栈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就是来负责实现这个功能的,它是从用户角度来理解应用而建立的一个抽象概念。
 

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

1. 启动模式

- standard 标准模式(系统默认模式)

每次启动一个Activity都会重新创建一个新的实例。
当用ApplicationContext去启动standard模式的Activity时,会报如下错误![](https://github.com/chen-eugene/Interview/blob/master/image/1536215413(1).png)                                                                               
这是因为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中可能使用。

2. 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实例并放入栈顶。

5、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方法。

6、Service生命周期,与IntentService的区别。


IntentService是一个基于Service的一个类,用来处理异步的请求。你可以通过startService(Intent)来提交请求,该Service会在需要的时候创建,当完成所有的任务以后自己关闭,且请求是在工作线程处理的。                                                                                                   
IntentService最起码有两个好处,① 不需要自己去new Thread;② 不需要考虑在什么时候关闭该Service。

7、startService和bindService混合使用的场景,这时候Service的生命周期是怎样的。


- 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来销毁它。

8、广播的两种注册方式有什么区别。


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

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

9、怎么增加广播的安全性。


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

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

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

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

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

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

3. 发送广播时,指定特定广播接收器所在的包名,具体是通过intent.setPackage(packageName)指定在,这样此广播将只会发送到此包中的App内与之相匹配的有效广播接收器中。
4. App应用内广播(LocalBroadcast),广播的发送者和接收者都同属于一个App。
相比于全局广播,App应用内广播优势体现在:

   - 安全性更高;
 
   - 更加高效。
 

如果觉得不错就打赏一下吧~

打开支付宝首页搜“     543200904    ”领红包,领到红包的小伙伴赶紧使用哦! 

猜你喜欢

转载自blog.csdn.net/weixin_40783315/article/details/84997507
今日推荐