看到了一个Android面试指南的网站,强力推荐:
Android校招面试指南
以下可能并不是确切的面试问题,但都涉及到了。
Android面试
1. HTTP与HTTPS
http
超文本传输协议,https
安全套接字层超文本协议,由SSL+HTTP
协议构建,可进行加密传输、身份认证的网络协议,是在传输层进行加密的。
区别:
-
https
协议需要ca申请证书。 -
http
是明文数据传输,https
则是具有安全性的ssl
加密传输协议。 - 采用完全不同的连接方式,其端口也不同,
http
是80
,https
是445
。
HTTPS
工作原理:
- 客户端访问服务器,发起请求,要求建立SSL连接。
- 服务器接到请求,将网站证书信息(包含公钥)发一份给客户端。
- 客户端与服务器端协商SSL安全等级,即协商信息加密等级。
- 双方同意安全等级,建立会话密钥(客户端生成的随机值,私钥,对称加密),利用证书信息的公钥将会话密钥加密。
- 服务器利用自己的私钥解密会话密钥。
- 服务器与客户端通过会话密钥(私钥)进行通信。
HTTPS
的优势:
- 可认证用户和服务器,确保数据发送到正确的客户机和服务器。
- 加密传输、身份认证,更安全,可防止数据在传输过程中不被窃取、改变,确保数据的完整性。防止:嗅探可以监测访问了哪些页面(保密性)。ISP(网络运营商)植入广告(完整性/防篡改)。域名欺骗、域名劫持(真实性/防假冒)。
- 虽然不是绝对安全,但它大幅增加了中间人攻击的成本。
HTTPS
的劣势
- 该协议握手阶段比较费时。
- 连接缓存不如HTTP高效,会增加数据开销和功耗。
- SSL证书需要钱,功能越强大的证书费用越高。
- SSL证书通常需要绑定IP,不能在同一IP上绑定多个域名,IPv4资源不可能支撑这个消耗。
- HTTPS协议的加密范围也比较有限,在黑客攻击、拒绝服务攻击、服务器劫持等方面几乎起不到什么作用。最关键的,SSL证书的信用链体系并不安全,特别是在某些国家可以控制CA根证书的情况下,中间人攻击一样可行。
其他:
- TCP是传输层协议,HTTP、HTTPS是应用层协议。
- 对称加密是加密和解密都是使用同一个密钥,非对称加密则加密和解密采用不同的密钥。显然非对称加密比对称加密更安全,然而性能通常较差,实现比较复杂。
- SSL称安全套接层,标准化后称TLS协议,称传输层安全协议。两者可视为同一东西的不同阶段。
参考:
http://www.techug.com/post/https-ssl-tls.html
https://www.cnblogs.com/lovesong/p/5186200.html
http://blog.csdn.net/xionghuixionghui/article/details/68569282
2. Android虚拟机相关
Dalvik虚拟机
用于Android平台的Java虚拟机,Dalvik虚拟机运行在Android的运行时库层。主要负责完成对象生命周期管理、堆栈管理、线程管理、安全和异常管理,以及垃圾回收等。另外,Dalvik早期并没有JIT编译器,直到Android2.2才加入了对JIT的技术支持。
Dalvik虚拟机特点
- 体积小,占用内存空间小;
- 专有的DEX可执行文件格式,体积更小,执行速度更快;
- 常量池采用32位索引值,寻址类方法名,字段名,常量更快;
- 基于寄存器架构,并拥有一套完整的指令系统;
- 提供了对象生命周期管理,堆栈管理,线程管理,安全和异常管理以及垃圾回收等重要功能;
- 所有的Android程序都运行在Android系统进程里,每个进程对应着一个Dalvik虚拟机实例。
和Java虚拟机的区别
- Java虚拟机运行的是Java字节码,Dalvik虚拟机运行的是Dalvik字节码。
- Java虚拟机通过解码class文件中的内容来运行程序,所有的Dalvik字节码由Java字节码转换而来,并被打包到一个DEX(Dalvik Executable)可执行文件中。Dalvik虚拟机通过解释DEX文件来执行这些字节码。
- Dalvik与JVM之间最大的区别:Java虚拟机与Dalvik虚拟机架构不同。Java虚拟机基于栈架构,程序在运行时虚拟机需要频繁的从栈上读取或写入数据,这个过程需要更多的指令分派与内存访问次数,会耗费不少CPU时间。Dalvik虚拟机基于寄存器架构。数据的访问通过寄存器间直接传递,这样的访问方式比基于栈方式要快很多。
ART虚拟机与Dalvik虚拟机的区别
ART代表Android Runtime,其处理应用程序执行的方式完全不同于Dalvik。
Dalvik的做法是:开发者编译后的应用代码需要通过一个解释器在用户的设备上运行,这一机制并不高效,但让应用能更容易在不同硬件和架构上运行。
ART的做法是:在应用安装时就预编译字节码到机器语言,这一机制叫Ahead-Of-Time(AOT)编译。在移除解释代码这一过程后,应用程序执行将更有效率,启动更快。
ART优点:
- 系统性能的显著提升。
- 应用启动更快、运行更快、体验更流畅、触感反馈更及时。
- 更长的电池续航能力。
- 支持更低的硬件。
ART缺点:
- 更大的存储空间占用,可能会增加10%-20%。
- 更长的应用安装时间。
ART虚拟机相对于Dalvik虚拟机的提升
- 预编译阶段:完全抛弃了Dalvik的JIT,使用了AOT直接在安装时将其完全翻译成native code。使得虚拟机执行指令的速度又一重大提升。
- 垃圾回收机制:Dalvik非并发GC,ART部分并发GC,且对内存进行了重新分配管理。
- 提高内存使用,减少碎片化:Dalvik内存管理特点是内存碎片化严重。
https://www.cnblogs.com/Jason-Jan/p/8459105.html
3. Bitmap压缩策略
http://www.cnblogs.com/Jason-Jan/p/8461078.html
4. Android的IPC(进程间通信)
IPC指进程间通信或跨进程通信,指两个进程间进行数据交换的过程。
Android中IPC的使用
只有面对多进程的情况才需要考虑进程间通信。
- 自身需要采用多进程模式来实现。
- 其他的应用获取数据。
Android中IPC带来的问题
- 所有运行在不同进程中的四大组件,只要它们之间需要通过内存来共享数据,都会共享失败。
- 静态成员和单例模式完全失效(不同的虚拟机中访问同一个对象会产生多分副本)。
- 线程同步机制完全失效(不在同一块内存,不管是所对象还是锁全局类都无法保证线程同步)。
- SharePreferences的可靠性下降(不支持两个进程同时写操作)
- Application会多次创建(因为创建新进程会分配独立虚拟机,相当于启动一个新的应用)。
Android中各种IPC方式
- Bundle,由于
Bundle
实现了Parcelable
接口。 - 文件共享,两个进程通过读写同一个文件来交换数据。文件共享方式适合在对数据同步要求不高的进程间进行通信。但是不建议使用
SharedPreference
,因为系统对它的读写有一定的缓存策略,内存中会有一份SharedPreferences
文件的缓存。 - Messenger,Messenger可以理解为信使,是一种轻量级的IPC方案,它的底层实现是AIDL,通过它可以再不同进程中传递Message对象。一次处理一个请求。
- AIDL,是一种android内部进程通信接口的描述语言。可以处理发送到服务器端大量的并发请求(不同与Messenger的串行处理方式)。
- ContentProvider,是Android中提供的专门用于不同应用间进行数据共享的方式,天生适合进程间通信。
- Socket,两个进程可以通过Socket来实现信息的传输,Socket本身可以支持传输任意字节流。
参考:
https://www.cnblogs.com/pear-lemon/p/6547734.html
5. Window、Activity、View
- Window:视图的承载器,是一个抽象类,实际在Activity中持有的是其子类PhoneWindow,内部持有一个 DecorView,通过创建DecorView来加载Activity中设置的布局R.layout.activity_main。Window 通过WindowManager将DecorView加载其中,并将DecorView交给ViewRoot,进行视图绘制以及其他交互。
- Activity,不负责视图控制,控制生命周期和处理事件。一个Activity包含了一个Window,Activity就像一个控制器,统筹视图的添加与显示,以及通过其他回调方法,来与Window、以及View进行交互。
- DecorView,FrameLayout的子类,顶级View。一般情况下它内部包含一个竖直方向的LinearLayout,包含延迟加载视图、标题栏、内容栏三层。在Activity中通过setContentView所设置的布局文件其实就是被加到内容栏之中的,成为其唯一子View。
- ViewRoot,所有View的绘制以及事件分发等交互都是通过它来执行或传递的。对应ViewRootImpl类,它是连接WindowManagerService和DecorView的纽带,View的三大流程(测量(measure),布局(layout),绘制(draw))均通过ViewRoot来完成。既非View的子类,也非View的父类,但是,它实现了ViewParent接口,这让它可以作为View的名义上的父视图。RootView继承了Handler类,可以接收事件并分发,Android的所有触屏事件、按键事件、界面刷新等事件都是通过ViewRoot进行分发的。
总结:
- Activity就像个控制器,不负责视图部分。
- Window像个承载器,装着内部视图。
- DecorView就是个顶层视图,是所有View的最外层布局。
- ViewRoot像个连接器,负责沟通,通过硬件的感知来通知视图,进行用户之间的交互。
参考:
http://www.cnblogs.com/Jason-Jan/p/8455118.html
6. Android中的几种动画
- FrameAnimation(逐帧动画),将多张图片组合起来进行播放。
- TweenAnimation(补间动画),是对某个View进行一系列的动画的操作,包括淡入淡出(Alpha),缩放(Scale),平移(Translate),旋转(Rotate)四种模式。
- PropertyAnimation(属性动画),属性动画不再仅仅是一种视觉效果了,而是一种不断地对值进行操作的机制,并将值赋到指定对象的指定属性上,可以是任意对象的任意属性。
7. Android 异步消息处理机制
Handler 、 Looper 、Message 这三者都与Android异步消息处理线程相关的概念。
Looper负责的就是创建一个MessageQueue,然后进入一个无限循环体不断从该MessageQueue中读取消息,而消息的创建者就是一个或多个Handler 。
- 首先
Looper.prepare()
在本线程中保存一个Looper
实例,然后该实例中保存一个MessageQueue
对象;因为Looper.prepare()
在一个线程中只能调用一次,所以MessageQueue
在一个线程中只会存在一个。 -
Looper.loop()
会让当前线程进入一个无限循环,不断从MessageQueue
的实例中读取消息,然后回调msg.target.dispatchMessage(msg)
方法。 -
Handler
的构造方法,会首先得到当前线程中保存的Looper
实例,进而与Looper
实例中的MessageQueue
相关联。 -
Handler
的sendMessage
方法,会给msg
的target
赋值为handler
自身,然后加入MessageQueue
中。 - 在构造
Handler
实例时,会重写handleMessage
方法,也就是msg.target.dispatchMessage(msg)
最终调用的方法。 - 注:在Activity的启动代码中,已经在当前UI线程调用了Looper.prepare()和Looper.loop()方法。
http://blog.csdn.net/lmj623565791/article/details/38377229
8. ANR应用无响应
ANR产生的原因通常是在UI线程执行了一些耗时操作(网络操作、SD卡文件操作、数据库操作、大量计算等),导致超时,阻塞了UI线程。
Activity: onCreate(), onResume(), onDestroy(),
onKeyDown(), onClick()等,超时时间5s
Application: onCreate(), onTerminate()等,超时时间5s
Service: onCreate(), onStart(), onDestroy()等,超时时间20s
BroadcastReceiver:onReceiver(),前台APP广播超时时间是10s,后台App是60s
避免:
- UI线程尽量只做跟UI相关的工作。
- 耗时操作(如数据库操作,I/O等)放入单独的线程处理。
- 尽量用Handler来处理UI线程和别的线程之间的交互。
9. Activity锁屏状态下的生命周期
对于锁屏状态,分两种情况考虑,一种是屏幕方向不会发生改变,一种是在清单文件中没有设置,屏幕方向可以发生改变。
屏幕方向不变
在清单文件中指定了屏幕方向,则Activity在锁屏和开启屏幕的时候执行的方法和顺序是:MainActivity onPause--->MainActivity onStop--->MainActivity onRestart--->MainActivity onStart--->MainActivity onResume
屏幕方向可变
- 在清单文件中没有对屏幕进行设置,则Activity在锁屏时候执行的方法和顺序是:
MainActivity onPause--->MainActivity onStop--->MainActivity onDestory--->MainActivity onCreate--->MainActivity onStart--->MainActivity onResume--->MainActivity onPause
销毁之后又新建。 - 在开启屏幕的时候,Activity执行的方法及顺序是:
MainActivity onResume--->MainActivity onPause--->MainActivity onStop--->MainActivity onDestory--->MainActivity onCreate--->MainActivity onStart--->MainActivity onResume
。对于这种,锁屏后再次开启屏幕会销毁两次,重建两次。当设置了android:configChanges="keyboardHidden|orientation"
之后就不会再重新走onCreate方法,不会再两次创建两次销毁
10. Android LowMemoryKiller机制
Android手机经常会自动杀死一些进程。
Andorid的Low Memory Killer
是在标准的Linux lernel
的 OOM
基础上修改而来的一种内存管理机制。当系统内存不足时,杀死不必要的进程释放其内存。
不必要的进程的选择根据有2个:oom_adj
和占用的内存的大小。oom_adj
代表进程的优先级,数值越小,优先级越高,越不容易被杀死;对应每个oom_adj
都可以有一个空闲进程的阀值oom_score_adj
。
Low Memory Killer
的阈值的设定,主要保存在2个文件之中,分别是:
/sys/module/lowmemorykiller/parameters/adj
/sys/module/lowmemorykiller/parameters/minfree
adj
保存着当前系统杀进程的等级,minfree
则是保存着对应的内存阀值。
11. Android多线程
在Android中常用的多线程操作有Handler、AsyncTask、IntentService
。
Handle具体操作:
在主线程创建Handle
实例,并实现handlmessage()
方法;在线程中执行耗时操作,开启一个线程对应会产生一个looper
,在初始化looper
时会创建一个消息队列MessageQueue()
;执行完耗时操作,通过handle
将消息发送到消息队列中,looper
执行轮询消息队列将消息取出,并交给handle
,handle
根据消息类型做出相应的处理。
AsyncTask具体操作:
-
onPreExecute()
运行在主线程中,开启线程前的准备操作; -
doInBackground()
运行在子线程中,用于处理耗时操作,通过调用publishProcess()
向onProcessUpdata()
推送消息 ; -
onProcessUpdata()
运行在主线程中,当调用publishProcess()
方法时就会开启此方法,接收到推送过来的数据,更新UI进度页面 -
onPostExecute()
运行在主线程中,当子线程耗时操作执行完毕后会调用此方法,doInBackground()
返回的参数传递到这里来用于更新UI ; - 调用
execute()
方法开启AsyncTask
。
IntentService具体操作:
IntentService
和普通的Service
区别在于,IntentService
在oncreate()
方法中单独开启一个线程用于耗时操作;通过onHandleIntent(Intent intent)
方法来处理耗时操作;在耗时操作执行完毕之后,会自动关闭service不用手动关闭 。
http://blog.csdn.net/qq_34358104/article/details/70237068
12. Activity四大启动模式
Activity的四种启动模式: standard、singleTop、singleTask、singleInstance
。
standard-默认模式
该模式是默认的启动模式,即标准模式。每次启动一个Activity都会重新创建一个新的实例。
singleTop-栈顶复用模式
- 当前栈中已有该Activity的实例并且该实例位于栈顶时,不会新建实例,而是复用栈顶的实例,并且会将Intent对象传入,回调onNewIntent方法
- 当前栈中已有该Activity的实例但是该实例不在栈顶时,其行为和standard启动模式一样,依然会创建一个新的实例
- 当前栈中不存在该Activity的实例时,其行为同standard启动模式
standard
和singleTop
启动模式都是在原任务栈中新建Activity
实例,不会启动新的Task
singleTask-栈内复用模式
在这个模式下,如果栈中存在这个Activity的实例就会复用这个Activity,不管它是否位于栈顶,复用时,会将它上面的Activity全部出栈,并且会回调该实例的onNewIntent方法。其实这个过程还存在一个任务栈的匹配,因为这个模式启动时,会在自己需要的任务栈中寻找实例,这个任务栈就是通过taskAffinity属性指定。如果这个任务栈不存在,则会创建这个任务栈。
singleTask启动模式启动Activity时,首先会根据taskAffinity去寻找当前是否存在一个对应名字的任务栈
- 如果不存在,则会创建一个新的Task,并创建新的Activity实例入栈到新创建的Task中去
- 如果存在,则得到该任务栈,查找该任务栈中是否存在该Activity实例
如果存在实例,则将它上面的Activity实例都出栈,然后回调启动的Activity实例的onNewIntent方法
如果不存在该实例,则新建Activity,并入栈
singleInstance-全局唯一模式
该模式具备singleTask模式的所有特性外,与它的区别就是,这种模式下的Activity会单独占用一个Task栈,具有全局唯一性,即整个系统中就这么一个实例,由于栈内复用的特性,后续的请求均不会创建新的Activity实例,除非这个特殊的任务栈被销毁了。以singleInstance模式启动的Activity在整个系统中是单例的,如果在启动这样的Activiyt时,已经存在了一个实例,那么会把它所在的任务调度到前台,重用这个实例。
http://blog.csdn.net/mynameishuangshuai/article/details/51491074
MVC、MVP、MVVM
三种架构的目的都是分离关注,避免将过多的逻辑全部堆积在一个类。
- MVC将应用分成三个主要层级:Model模型层,View视图层和Controller控制层。其实android app的界面开发部分已经是遵从MVC模式,然而xml布局作为View来说功能很无力,所以通常Activity也会承担一部分View的工作。
- MVP由MVC演变而来,MVP将Controller变成Presenter,并且改变了通信方向,这个模式将应用分为三个主要层级:Model, View and Presenter。
- MVVM 模式将 Presenter 改名为 ViewModel,基本上与 MVP 模式完全一致,ViewModel可以理解成是View的数据模型和Presenter的合体,MVVM采用双向绑定(data-binding)。
热更新
快速排序
待补充。。。
-。-