Android基础相关面试题
一、Activity
①定义:Activity是安卓与用户交互时提供的一个界面,用户可以通过它来实现点击、滑动操作。
②Activity四种状态:
Running (活动状态。屏幕根据用户操作做出反应。处于栈顶);
paused (失去焦点、非全屏界面占据、失去和用户交互能力);
stopped (被另一个Activity完全覆盖、不可见);
killed (被系统回收,保存信息成员变量不存在)。
③生命周期:
Ⅰ Activity启动:onCreate()(被创建时回调、处理一些预加载)->onStart()(表明Activity正在启动,处于可见状态,但不能与用户交互)->onResume()(表明已经在前台,可以交互)
Ⅱ 点击Home键回到主界面或被覆盖(Activity不可见):onPause()->onStopped()(表明已被停止或覆盖,内存紧张时可能被回收)
Ⅲ 再次回到原Activity时:onRestart()->onStart()->onResume()(可以交互了)
Ⅳ 退出当前Activity时:onPause()->onStop()->onDestroy()(表明当前Activity正在被销毁,回收工作,资源释放)
①onCreate :Activity第一次被实例化的时候系统会调用,整个生命周期只调用1次该方法。
通常用于初始化设置: 1、为Activity设置所要使用的布局文件。2、为安卓控件绑定监听器等静态的设置操作。
②onStart(可见不可交互):当Activity可见未获得用户焦点不能交互时系统会调用。
③onResume(可见可交互) :当Activity和用户发生交互的时候,触发该方法。
④onPause (有一点可见不能交互):当一个正在前台运行的Activity因为其他的Activity需要前台运行而转入后台运行的时候,触发该方法。
⑤onStop(不可见不能交互):当Activity被其他的Activity完全覆盖不可见时,触发该方法,如果内存紧张,系统会直接结束这个Activity,而不会触发 onStop 方法。
⑥onRestart (由不可见到可见):当处于停止状态的Activity需要再次展现给用户的时候,触发该方法。
⑦onDestroy :当Activity(用户调用finish()或系统由于内存不足)被系统销毁时调用,(整个生命周期只调用1次)用来释放onCreate ()方法中创建的资源,如结束线程,清空数据,注销广播等。和 onStop 方法一样,如果内存紧张,系统会直接结束这个Activity而不会触发该方法。
具体区别:https://blog.csdn.net/superjunjin/article/details/44674917
④启动模式:
1. standard
2. singletop(栈顶复用模式)
3. singletask
4. singleinstance
scheme跳转协议(一种页面内跳转协议,方便跳转app各个页面,可以通过通知栏消息定制化跳转页面,可以通过H5页面跳转页面)
二、Fragment(第五大组件)
不属于其他四大组件,有自己的生命周期,可以灵活加载到Activity上,并不完全独立,必须依附Activity并加载到Activity上。
1、加载到Activity两种方式:
① 静态加载:把Fragment作为XML标签加载到Activity中;
② 动态加载:通过FragmentManager来管理所有要启动的Fragment。
Step1:创建FragmentManager对象,通过FragmentManager创建FragmentTransaction;实体transaction
Step2:调用transaction里的add(R.id.)方法;
Step3:调用transaction.commit()
2、Fragment生命周期:
OnAttach(Fragment与Activity关联后回调)
onCreate(创建Fragment)
onCreateView(系统在Fragment首次绘制用户界面时调用,返回的View必须是Fragment的根视图)
onViewCreated(表明UI界面绘制好,初始化Fragment内控件资源)
Activity-onCreate(初始化Activity布局及数据)
Activity-onCreated(渲染绘制成功以后调用)
Activity-onStart(表示Activity可见了)
onStart(表明Fragment也可见了)
Activity-onResume(Activity和用户可交互了)
onResume(Fragment与用户也可交互了,用户可进行滑动、点击等操作)
onPause(Fragment失去用户交互)
Activity-onPause(Activity也不可交互)
onStop
Activity-onStop
onDestroyView(对应创建时的onCreateView方法,表明Fragment即将结束)
onDestroy
onDetach
Activity-onDestroy(整个Activity被回收)
3、Fragment通信:
① 在Fragment中调用Activity中的方法getActivity
② 在Activity中调用Fragment中的方法,接口回调
③ 在Fragment中调用Activity中getActivity获取到Activity方法,通过Fragment中的方法findFragmentById获取到另一个
4、Fragment的方法
Fragment的replace、add、remove方法:
add:将Fragment实例添加到最上层
remove:将Fragment实例从Fragment队列中删除
replace(FragmentManager的方法):将Fragment目标实例替换到最上层的实例
三、Service(一个可以在后台执行长时间运行操作而没有用户界面的应用组件、运行在主线程,不能做耗时操作)
1、Service和Thread的区别:
A.定义
Thread:是程序执行的最小单元,是分配CPU的基本单位,可执行耗时的操作。
Service:一种轻量级的IPC通信,一个可以在后台执行长时间运行操作而没有用户界面的应用组件、运行在主线程,不能做耗时操作。
B.实际开发
Thread一般指工作线程,即后台线程,做耗时操作,而主线程负责处理UI线程的绘制;
Service运行在主线程中,如果要执行耗时操作一定要开启单独线程。
C.应用场景
当需要执行网络请求、文件数据查询以及其他阻塞UI线程的操作时,都需要开启工作线程,
而Service应用于需要长时间在后台运行且不需要交互的情况下,如播放音乐,天气预报统计及数据统计等。
2、开启Service的两种启动方法
①stratservice:
启动的服务:主要用于启动一个服务执行后台任务,不进行通信。停止服务使用stopService;
step2:在Mainfest.Xml文件中配置该Service
step3:使用Context的startService(Intent)方法启动该Service
step4:不再使用时,调用stopService(Intent)方法停止该服务
②bindService:
启动的服务:该方法启动的服务可以进行通信。停止服务使用unbindService;
step1:创建bindService服务端,继承自Service并在类中,创建一个实现IBinder接口的实例对象并提供公共方法给客户端调用
step2:从onBind()回调方法返回此Binder实例
step3:在客户端中,从onServiceConnected()回调方法接受Binder,并使用提供的方法调用绑定服务
四、Broadcast Receiver
1、广播:
① 广播的定义:在Android中,Broadcast是一种广泛运用的在应用程序之间传输信息的机制,Android中我们要发送的广播内容是一个Intent,这个Intent中可以携带我们要传送的数据。
① 广播的使用场景:
A. 同一APP具有多个进程的不同组件之间的消息通信(定位地图进程与主进程间通信)
B. 不同APP之间的组件之间消息通信
② 广播的种类:
A. Normal Broadcast:Context.sendBroadcast (普通广播)
B. System Broadcast:Context.sendOrderdBroadcast (有序广播)
C. Local Broadcast:只在自身APP内传播 (本地广播)
2、实现广播-receiver
① 静态注册:注册完成就一直运行(写在AndroidMainfest.xml里,进程杀死仍能收到广播)
② 动态注册:跟随Activity的生命周期(在代码中调用registerReceiver()进行注册,在onDestroy方法里调用unregisterReceiver()方法注销,注销后应将receiver设为null,避免引起内存泄漏)
3、内部实现机制
① 自定义广播接受者BroadcastReceiver,并复写onReceive()方法;
② 通过Binder机制向AMS(Activity Manager Service,负责四大组件的启动,切换和调度,以及应用程序的管理和调度工作)进行注册;
③ 广播发送者通过Binder机制向AMS发送广播;
④ AMS查找符合相应条件(IntentFilter/Permission等)的BroadcastReceiver,将广播发送到BroadcastReceiver(一般情况下是Activity)相应的消息循环队列中;
⑤ 消息循环执行拿到此广播,回调BroadcastReceiver中的onReceive()方法。
4、LocalBroadcastManager详解(本地广播)
优点:
① 使用它发送的广播将只在自身APP内传播,因此你不必担心泄露隐私数据。
② 其他APP无法对你的APP发送该广播,因为你的APP根本就不可能接受到非自身应用发送的该广播,因此你不必担心有安全漏洞可以利用。
③ 比系统的全局广播更加高效。
内部实现:
① LocalBroadcastManager高效的原因主要是因为它内部是通过Handler实现的,它的sendBroadcast()方法含义并非和我们平时所用的一样,它的sendBroadcast()方法其实是通过Handler发送一个message实现的;
② 既然是它内部是通过Handler来实现广播发送的,那么相比与系统广播通过Binder实现那肯定是更高效了,同时使用Handler来实现,别的应用无法向我们的应用发送该广播,而我们应用内发送的广播也不会离开我们的应用;
③ LocalBroadcastManager内部协作主要是靠这两个Map集合:mReceivers和mActions,当然还有一个List集合mPendingBroadcasts,这个主要就是存储待接收的广播对象。
五、WebView安全漏洞问题
1、Webview常见的一些坑
① Android API level 16以及之前的版本存在远程代码执行安全漏洞,该漏洞源于程序没有正确限制使用WebView.addJavascriptInterface方法,远程攻击者可以通过Java
Reflection API利用该漏洞执行任意Java对象的方法
② WebView在布局文件中的使用:WebView写在其他容器中时(需要先把WebView在这个容器中销毁再调用WebView的onDestroy方法)
③ Jsbridge:构建桥,一端是本地,一端是web端,让本地native端可以调用远端web js代码,同时让远端web可以调用本地native的代码(不是坑)
④ webviewClient.onPageFinished(页面加载完回调,若正在加载的网页出现跳转,方法会被调用无数次)àwebChromeClient.onProgressChanged(当webView需要加载各种网页且完成一些操作时最好使用该方法)
⑤ 后台耗电:WebView加载网页时会自己开启线程,如果没有将WebView很好的销毁,残余线程就会一直在后台运行,使后台耗电量居高不下(css.exit)
⑥ WebView硬件加速导致页面渲染问题:容易出现页面加载白块、闪烁(设置WebView暂时关闭硬件加速)
2、关于WebView的内存泄漏问题
① 独立进程,简单粗暴,不过可能涉及到进程间通信。
② 动态添加WebView,对传入WebView中使用的Context使用弱引用。动态添加WebView意思在布局创建个ViewGroup用来放置WebView,Activity创建时add进来,在Activity停止时在容器中remove掉再调用onDestroy。
六、Binder
1、Linux内核的基础知识
① 进程隔离/虚拟地址空间不同,数据不共享
② 系统调用(只可访问许可的资源,将内核层和用户空间分隔开,通过系统调用在用户空间访问内核资源)
③ Binder驱动(运行在内核空间当中,各个用户进程通过Binder通信内核进行交互)
2、Binder通信机制介绍
① 为什么使用Binder
A. Android使用的Linux内核拥有非常多的跨进程通信机制
B. 性能(相比传统socket更加高效)
C. 安全(协议本身支持双方身份校验)
② Binder通信模型
A. 电话基站:Binder驱动(内核)
B. 通信录:serviceManager
③ Binder通信机制原理
A. Service在ServiceManager表中注册它的方法;
B. Client到ServiceManager表中查询是否有目标调用方法,ServiceManager返回给Client一个代理对象的方法(空方法),Client调用该代理对象方法时返回给内核驱动,内核驱动接收到代理对象的方法后调用Service端的对应方法,Service端把结果返回给ServiceManager,ServiceManager再把结果返回给Client端。
④ 什么是Binder
A. 通常意义下,Binder指的是一种通信机制;
B. 对于Service进程来说,Binder指的是Binder本地对象/对于Client来说,Binder指的是Binder代理对象;
C. 对于传输过程而言,Binder是可以进行跨进程传递的对象。
3、AIDL(Android Interface Definition Language)
AIDL是一种接口定义语言,借助它,你可以定义接口,使得客户端和服务端之间实现进程间通信。对android来说, 一个进程无法通过正常的方法来访问另一个进程的内存空间。可以说,他们需要把对象分解成操作系统可以理解的原子类型,然后使对象突破限制在不同进程之间进行传输。具体实现这种机制的代码写起来非常枯燥,所以android为你提供了AIDL语言来进行处理。
① asInterface方法里表明,如果A和B属于同一进程则不会走跨进程,如果是非同一线程,则会返回一个代理类,然后通过代理对象来获取远端的数据;
② onTransact方法:根据AIDL函数返回的编号来进行相应的方法调用。
注意:
a.只有当你需要来自不同应用的客户端通过IPC通信来访问你的服务时,并且想在服务里处理多线程的业务,这时就需要使用AIDL。
b.如果你不需要同时对几个应用进程IPC操作,你最好通过实现Binder接口来创建你的接口。
c.如果你仍需要执行IPC操作,但不需要处理多线程,使用Messenger来实现接口即可。
d.无论如何,在实现AIDL之前确保你完全理解Bound Service相关知识。