三、常用开发技术面试题
Android性能优化:
1、布局优化
布局优化的思想就是减少布局文件的层级,这个道理很浅显,布局文件少了,绘制事件就少了,响应速度就会提升
1、1使用一些低耗的控件比如ViewGroup,LinearLayout,懒加载控件ViewStub等
2、绘制优化
绘制优化主要是指避免在view的onDraw方法中进行大量的操作,它会直接影响界面的响应速度
2、1避免在onDraw方法中进行局部变量,应为onDraw方法会频繁创建,这样会产生大量的临时变量占用内存,销毁 这些临时变量会频繁的执行gc,降低效率
2、2onDraw方法中不要执行耗时操作,它运行在主线程,容易造成anr
3、内存泄漏优化
具体详见下面
4、响应速度和ANR优化
核心思想是避免在主线程中进行耗时操作,这些主线程一般指服务、广播onReceiver,主线程等,如果在activity中左过多操作会引起黑白屏和ANR错误,
5、ListView优化
复用convertView、使convertView绑定viewHolder、翻页加载、使用缓存
6、线程优化
使用线程池。
Android内存泄漏相关:
什么是内存泄漏:内存泄漏就是应用程序申请内存,申请内存的对象不会被释放,这样就会导致内存泄漏
内存泄漏带来哪些问题:
1、应用可用内存减少,增加内存压力
2、会频繁的出发GC, 降低应用的性能
3、当没有可用内存时,会导致OOM程序异常
内存泄漏中的常见场景&解决方案
1、单例引起的内存泄漏
单例的生命周期跟随整个应用程序,对于单例我们有这几种优化
1、1懒加载,用到的时候在进行初始化
1、2避免在单例中引用activity的context上下文,这样被引用的activity就不会释放
1、3尽量少使用单例
2、静态变量引起的内存泄漏
在开发过程中,尽量不要对上下文,自定义类,自定义属性进行statice修饰,常量除外,因为一旦静态变量应用了上下文,那么当前上下文坐在的activity就不会被释放,导致内存泄漏
3、属性动画引起的内存泄漏
android3.0以后google提供属性动画,属性动画中有一个类循环播放的动画,如果页面离开,动画不关闭就会导致内存泄漏
4、handler以及内部类造成的内存泄漏
Handler主要用于主线程跟子线程进行通信,Handler允许发送延迟消息,如果发送延迟消息期间关闭了activity就会造成内训泄露
非静态内部类会持有外部类的引用,如果在耗时操作期间关闭的页面也会导致内存泄漏
解决办法:
定义静态内部类、对外引用弱引用
ondestory中执行handler.removeCallbackAndMessage(null)
内训泄露工具排查
1、Android profile 是 Android Studio 提供的 代码扫描分析工具,包括CPU真用、网络请求、内存占用等情况查看,它可以帮助我们发现代码机构 / 质量问题,
2、LeakCanary 是 Square 公司开源的「Android 和 Java 的内存泄漏检测库」,Square 出品,必属精品,功能很强
指纹解锁开发
1、添加权限use_fingerprint
2、获取当前指纹上下文对象FingerprintManager
FingerprintManager fingerprint2 = (FingerprintManager) getSystemService(Context.FINGERPRINT_SERVICE);
3、执行三个方法
fingerprint.isHardwareDetected(); // 判断设备是否支持指纹解锁
fingerprint.hasEnrolledFingerprints(); //判断设备是否以保存过指纹信息,至少需要保存过一个
对验证结果进行处理: onAuthenticationError、 onAuthenticationSuccess、 onAuthenticationFailed
浅谈安卓apk加固原理和实现
apk加固
请例举Android中常用布局类型,并简述其用法以及排版效率
Android中常用布局分为传统布局和新型布局
传统布局(编写XML代码、代码生成):
框架布局(FrameLayout):
线性布局(LinearLayout):
绝对布局(AbsoluteLayout):
相对布局(RelativeLayout):
表格布局(TableLayout):
新型布局(可视化拖拽控件、编写XML代码、代码生成):
约束布局(ConstrainLayout):
对于嵌套多层View而言,其排版效率:LinearLayout = FrameLayout >> RelativeLayout
使用过什么图片加载库?Glide的源码设计哪里很微妙?
参考回答:
图片加载库:Fresco、Glide、Picasso等
Glide的设计微妙在于:
Glide的生命周期绑定:可以控制图片的加载状态与当前页面的生命周期同步,使整个加载过程随着页面的状态而启动/恢复,停止,销毁
Glide的缓存设计:通过(三级缓存,Lru算法,Bitmap复用)对Resource进行缓存设计
Glide的完整加载过程:采用Engine引擎类暴露了一系列方法供Request操作
如何对APK瘦身?
一个完整APK包含以下目录(将APK文件拖到Android Studio):
META-INF/:包含CERT.SF和CERT.RSA签名文件以及MANIFEST.MF清单文件。
assets/:包含应用可以使用AssetManager对象检索的应用资源。
res/:包含未编译到的资源 resources.arsc。
lib/:第三方库
classes.dex:包含以Dalvik / ART虚拟机可理解的DEX文件格式编译的类。
AndroidManifest.xml:包含核心Android清单文件。该文件列出应用程序的名称,版本,访问权限和引用的库文件。
lib、class.dex和res占用了超过90%的空间,所以这三块是优化Apk大小的重点
减少res,压缩图文文件
我们通常会放置多套不同分辨率的图片以适配不同的屏幕,在实际使用中,只保留一到两套就足够了(xxhdpi),可以使用webp格式图片等
减少dex文件大小
添加资源混淆,代码混淆在压缩apk的同时,也提升了安全性。
减少lib文件大小
由于引用了很多第三方库,lib文件夹占用的空间通常都很大,特别是有so库的情况下。很多so库会同时引入armeabi、armeabi-v7a和x86这几种类型,这里可以只保留armeabi或armeabi-v7a的其中一个就可以了,实际上微信等主流app都是这么做的。
简述多渠道打包及原理和常用操作?
根据不同的包标识,配合自动化埋点,应用在请求网络的时候携带渠道信息,方便后台做运营统计,比如说统计我们的应用在不同应用市场的下载量等信息
这里以友盟统计为例
1、首先在manifest.xml文件中设置动态渠道变量:
2、接着在app目录下的build.gradle中配置productFlavors,也就是配置打包的渠道:
3、最后Build菜单下执行signed APK,输入key路径和密码,选择release,选择渠道进行打包即可
图片优化,以及图片加载框架的使用,如Picasso、 Fresco、Glide等?
1)尽量使用小的图片,对图片进行压缩,bitmapfactory.options图片配置类,insimplesize进行缩放,设置图片的编码方式;对图片使用软引用,内存不够时即时释图片内存;对图片的复用,三级缓存的使用;
即时回收不再使用的bitmap对象;
2)Picasso,不支持gif,缓存的是Argb8888的原图,占用内存较大,图片的框架使用了OkHttp缓存机制,使用Http协议缓存,也是异步加载.
3)Fresco,框架是FaceBook公司推出的,适合批量加载图片,底层是通过三级缓存(2级内存,1级磁盘)
加载成功后自动替换成目标图片
4)glide,Google公司14年推出来的,可以加载GIF图,也可以根据指定图片清晰度,底层的原理:为Bitmap维护一个对象池,对象池的目的是通过减少对象的分配,以重用来提高性能.对象池也可以帮助提高滚动的性能。API简洁易调用
如何对 Android 应用进行性能分析
如果不考虑使用其他第三方性能分析工具的话,我们可以直接使用 ddms 中的工具,其实 ddms 工具已经非常的强大了。ddms 中有 traceview、heap、allocation tracker 等工具都可以帮助我们分析应用的方法执行时间效率和内存使用情况。
Traceview 是 Android 平台特有的数据采集和分析工具,它主要用于分析 Android 中应用程序的 hotspot(瓶颈)。Traceview 本身只是一个数据分析工具,而数据的采集则需要使用 AndroidSDK 中的 Debug 类或者利用 DDMS 工具。
heap 工具可以帮助我们检查代码中是否存在会造成内存泄漏的地方。
allocation tracker 是内存分配跟踪工具
自定义View相关方法
自定义控件的实现有三种方式,分别是:组合控件、自绘控件和继承控件。
1、自定义属性的声明和获取
分析需要的自定义属性
在res/values/attrs.xml定义声明
在layout文件中进行使用
在View的构造方法中进行获取
2、测量onMeasure、布局onLayout(ViewGroup)、绘制onDraw
3、onTouchEvent、onInterceptTouchEvent(ViewGroup)
4、状态的恢复与保存
优化自定义 View
1、对于频繁调用的方法,尽量减少不必要的代码,比如onDraw方法,它运行在UI上,使用不当不仅会导致内存紧张,还会导致UI卡顿
2、layout:我们都知道调用requestLayout,他会遍历整个view层级来计算当前view得大小,因此要较少调用次数
3、UI尽量扁平化,不要过于复杂,如果很复杂建议使用viewGroup
TCP的3次握手和四次挥手
三次握手是指,客户端与服务端需要发送三次包
1、客户端向服务端发送请求连接, 等待回应
2、服务器接收到请求,并向客户端发送相应
3、客户端得到服务器发送请求的相应后,向服务器发送数据包
TCP与UDP的区别
TCP UDP
是否连接 面向连接 面向非连接
传输可靠性 可靠 不可靠
应用场合 传输大量数据 少量数据
速度 慢 快
HTTP与HTTPS的区别以及如何实现安全性
HTTP 是明文连接不安全,HTTPS是加密连接,ssl加密安全
HTTPS需要申请证书,http不需要
HTTP 速度快,HTTPS速度慢
请解释安卓为啥要加签名机制? 谈谈你对安卓签名的理解?
Android的签名机制包含有消息摘要、数字签名和数字证书
消息摘要:在消息数据上,执行一个单向的 Hash 函数,生成一个固定长度的Hash值
数字签名:一种以电子形式存储消息签名的方法,一个完整的数字签名方案应该由两部分组成:签名算法和验证算法
数字证书:一个经证书授权(Certificate Authentication)中心数字签名的包含公钥拥有者信息以及公钥的文件
(三)数据库
sqlite升级,增加字段的语句
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
升级一定要newVersion+1,否则不会走onUpgrade方法
增加字段:alter table [表名] add column [字段id] [字段类型]
(四)算法
GC算法(各种算法的优缺点以及应用场景)
1、引用计数法
每个对象头部都会有一个counter,对象被引用一次计数器就会+1,不会引用就会-1,为0就会被gc等待回收
由循环引用的问题
2、可达性算法
以当前节点为根节点,向上搜索,如果找到父节点则被引用,没有就没有被引用,解决循环引用问题
一张Bitmap所占内存以及内存占用的计算
getByteCount()
public final int getByteCount() { return getRowBytes() * getHeight();}
(五)插件化、模块化、组件化、热修复、增量更新、Gradle
对热修复(热更新)和插件化的理解
热更新流程:
1、线上检测验证的bug
2、拉出bugfix分支并在分支上修复问题
3、jenkins构建和补丁生成
4、app通过推送或者拉取的方法获取补丁
5、将bugfix代码同步到主干目录上
热更新原理:
1、Android类加载机制
PathClassLoader:主要加载系统的类
DexClassLoader:主要加载Dex文件,jar、apk包等
2、热修复机制
1、dexElements:放新文件和旧文件的集合
2、ClassLoader会遍历dexElements数组
描述:在ClassLoader中创建一个dexElements文件的数组,根据线上的类文件,把线上的类文件打包成dex文件放到dexElements数组的最前面,ClassLoader会优先加载最前面的dex文件,这样就完成了新文件替换旧文件的机制
插件化原理分析
1、插件化的来源:
我们都知道app在开发维护过程中随着版本迭代,代码会越来越多,功能也会越来越多
银行业务众多,一个团队开发至少十几个人,每个人都有负责一个模块的时候,如果某个模块更新,那么整个app 就会随着更新,浪费时间、人力。因此面对这种情况,插件化能很好的解决问提
插件化是指将 APK 分为宿主和插件的部分。把需要实现的模块或功能当做一个独立的提取出来,在 APP 运行时,我们可以动态的载入或者替换插件部分,减少宿主的规模
宿主: 就是当前运行的APP。
插件: 相对于插件化技术来说,就是要加载运行的apk类文件。
2、插件化所要解决的问题:
2.1动态加载apk:
PathClassLoader:主要加载系统类文件
DexClassLoader主要动态加载dex文件常用于热修复机制
所谓的动态加载apk主要是通过DexClassloader加载dex类文件来实现,并通过反射来动态的获取dex文件的方法、属性和类文件信息
2.2资源加载:
一个apk访问另一个apk资源的时候,只能通过反射来访问被访问apk资源,通过assestManager
2.3代码加载:
通过反射生命周期来实现
模块化实现(好处,原因)
定义:模块化是一种处理复杂系统分解为更好的可管理模块的方式
每个团队负责不同的模块,提升开发,测试效率
每个模块实际上也是一个完整的项目,可以进行单独编译,调试
模块功能比较单一,可在多个项目中使用
项目组件化的理解
引入组件化的原因:项目随着需求的增加规模变得越来越大,规模的增大导致了各种业务错中复杂的交织在一起, 每个业务模块之间,代码没有约束,带来了代码边界的模糊,代码冲突时有发生, 更改一个小问题可能引起一些新的问题, 牵一发而动全身,增加一个新需求,需要熟悉相关的代码逻辑,增加开发时间
避免重复造轮子,可以节省开发和维护的成本。
可以通过组件和模块为业务基准合理地安排人力,提高开发效率。
不同的项目可以共用一个组件或模块,确保整体技术方案的统一性。
为未来插件化共用同一套底层模型做准备。
组件化开发流程就是把一个功能完整的App或模块拆分成多个子模块(Module),每个子模块可以独立编译运行,也可以任意组合成另一个新的 App或模块,每个模块即不相互依赖但又可以相互交互,但是最终发布的时候是将这些组件合并统一成一个apk,遇到某些特殊情况甚至可以升级或者降级
举个简单的模型例子
App是主application,ModuleA和ModuleB是两个业务模块(相对独立,互不影响),Library是基础模块,包含所有模块需要的依赖库,以及一些工具类:如网络访问、时间工具等
描述清点击 Android Studio 的 build 按钮后发生了什么(apk打包流程)
流程概述:
1、打包资源文件,生成R.java文件
2、处理aidl文件,生成相应java 文件
3、编译工程源代码,生成相应class 文件
4、转换所有class文件,生成classes.dex文件
5、打包生成apk6、对apk文件进行签名7、对签名后的apk文件进行对其处理
在 AndroidStudio 工程点击 Run 按钮, 实际上做了什么操作呢?
1、检查项目和读取基本配置
2、Gradle Build
3、Apk Install & LaunchActivity
(六)架构设计和设计模式
谈谈你对Android设计模式的理解
什么是设计模式
设计模式是一种解决方案,它代表了实现代码的最佳实践
设计模式的作用
设计模式就是用来解决软件设计中应对变化,提高软件复用性。设计模式使软件更加可维护、可拓展、更加稳定、可复用性强
常见的设计模式
单例、观察者、工厂、状态机模式
MVC MVP MVVM原理和区别
用到的一些开源框架,介绍一个看过源码的,内部实现过程。
从0设计一款App整体架构,如何去做?
1、需求分析,确定功能
2、根据功能,确定模块化开发或者组件化开发
3、根据业务模块确定架构MVC、MVP、MVVM
4、根据架构模式进行编码、优化
Binder机制及底层实现
1、为什么要使用Binder
android使用linux内核,它里面有非常多的进程通信机制
性能,手机注重性能,
安全,支持通信双方进行身份校验
2、Binder的通信模型
(七)性能优化
如何对Android 应用进行性能分析以及优化?
性能分析工具:traceview、heap、allocation tracker
traceview:数据采集和分析工具
heap:工具可以帮助我们检查代码中是否存在会造成内存泄漏的地方
用IDE如何分析内存泄漏?
Android Profiler内存分析工具
通过Profiler可以查看CPU、Memory和Network的调用情况。
Java多线程引发的性能问题,怎么解决?
java中多线程除了能解决耗时操作,但是线程的开销是非常占用资源的。
1、线程的生命周期开销高,线程从创建到销毁时间不固定
2、线程是一种有线cpu资源,过多的线程会占用更多的cpu资源
3、线程超过jvm内存限制会引起OOM问题
解决办法:
1、使用线程池,更好的利用资源
线程池有核心线程数、缓冲线程数、最大线程数,可根据线程的轻重缓急来合理分配资源
启动页白屏及黑屏解决?
首先我们分析一下为什么会有黑白屏问题:
1、启动app,系统进程会创建一个新的进程启动当前app,当然这个启动是有时间的。这个时间段界面呈现假死状态,android为我们解决的办法是在mainfest配置文件中设置不同的主题来展示黑屏或者白屏。也就是预览窗口
2、 针对这个问题,我的解决方案是,
可以在drawable文件夹下定义一个启动xml文件
添加一个主题style,设置名字为SplashAppTheme ,给android:windowBackground 指定xml文件
在清单文件中给启动页activity的Theme单独设置我们刚才添加的主题
- true
- true
- @drawable/layer_splash
怎么保证应用启动不卡顿?
应用卡顿的原因是界面绘制频繁,主线程做了过多的耗时操作
如何保持应用的稳定性
1、用户体验、流畅的运行app
2、软件崩溃,最主要的OOM问题
3、性能分析
RecyclerView和ListView的性能对比
ListView 回收机制基于RecyclerBin(mActivitysViews、mSpacpViews)
RecyclerView 回收机制Recycler(mCachesViews、Viewpool)
ListView的优化
1、复用convertView
2、使convertView绑定View Holder
3、翻页加载
4、使用缓存
Bitmap如何处理大图,如一张30M的大图,如何预防OOM
Bitmap加载一张30M的大图为了避免引起OOM,需要使用采样率进行展示(根据屏幕不影响分辨率情况下展示),流程
1、将BitmapFactory.Options的inJustDecodeBounds设为true并加载图片
2、从BitmapFactory.Options获取图片的outWidth、outHeight
3、根据采样率的规则结合目标View的大小和outWidth和outHeight计算出采样率inSampleSize
4、将BitmapFactory.Options的inJustDecodeBounds设为false重新加载图片
java中的四种引用的区别以及使用场景
强应用:当前对象如果是强引用,它会一直存在内存中,生命周期跟随程序生命周期,宁愿抛出OOM也不会被回收
软引用:当前对象如果是软引用,内存充足时不会被回收,内存不足时会优先回收
弱引用:不管内存充足与否,只要被GC扫描到就会被回收。
虚引用:与弱引用一样,随时会被回收?
(八)NDK、jni、Binder、AIDL、进程通信有关
请介绍一下NDK
NDK是Android提供的工具集合,通过NDK,可以更方便的使用JNI访问本地代码。具有如下好处:
1、提高代码的安全性,因为so库反编译困难
2、可以很方便的使用目前C/C++开源库
3、便于平台间的移植
4、提高程序在某些特定情况下的执行效率
什么是NDK库?
一些里库的集合,比如log库,第三方的openssl库,主要是方便调用
jni用过吗?
JNI是为了java调用c、c++封装的一层接口
JNI调用本代码开发流程:静态注册、动态注册
静态注册
1、在java中生命native方法
2、用c、c++代码实现native方法
3、编译运行
动态注册
1、我们知道Java Native函数和JNI函数时一一对应的,JNI中就有一个叫JNINativeMethod的结构体来保存这个对应关系,实现动态注册方就需要用到这个结构体
JNI调用java流程:
1、先通过类名找到类
2、根据方法名找到方法id
3、直接调用,如果类为非静态类,需要先构造类对象
类型签名: 类:L+包名+类名
方法:(参数类型) + 返回值类型
基本类型:[ + 类型
Java如何调用c、c++语言?
Java支持跨平台开发,android为了java和本地代码进行交互,定义了jni,jni是java为了调用c、c++代码封装的一层接口
jni如何调用java层代码?
1、根据类名找到类
2、根据方法名找到方法id
3、直接调用方法,如果类为非静态类,需要先构造类对象
进程间通信的方式?
Bundle、文件共享、ContentProvider、AIDL
Binder机制
直观的说Binder是一个类,它实现了IBinder接口
简述IPC?
什么是IPC?
IPC简称进程间通信,是指两个进程之间进行数据交换的过程
为什么要用IPC(从多进程通信会造成哪些方面的问题)
1、静态成员或单例模式失效
我们都知道Android中不同进程系统会分配不同的虚拟机,每个虚拟机在内存分配中都有单独的内存地址,不同的虚拟机访问同一个类对象会产生多分副本,因此从一个进程改变静态变量,在另一个进程访问不会发生癌变
2、线程同步完全失效。内存不同线程锁对象也不同
3、SharedPreferences失效,它本身不支持多进程读写,容易引起数据丢失
4、Application会多次创建
什么是AIDL?
AIDL解决了什么问题?
AIDL如何使用?
Android 上的 Inter-Process-Communication 跨进程通信时如何工作的?
谈谈对多进程开发的理解以及多进程应用场景
主要谈谈android
android中默认情况下,同意应用会运行在一个进程中,android:process可以指定不同进程
(九)framework层、ROM定制、Ubuntu、Linux之类的问题
谈谈对jvm的理解
1 虚拟机并不神秘,在操作系统的角度看来,它只是一个普通进程。
2 这个叫做虚拟机的进程比较特殊,它能够加载我们编写的class文件。如果把JVM比作一个人,那么class文件就是我们吃的食物。
3 加载class文件的是一个叫做类加载器的子系统。就好比我们的嘴巴,把食物吃到肚子里。
4 虚拟机中的执行引擎用来执行class文件中的字节码指令。就好比我们的肠胃,对吃进去的食物进行消化。
5 虚拟机在执行过程中,要分配内存创建对象。当这些对象过时无用了,必须要自动清理这些无用的对象。清理对象回收内存的任务由垃圾收集器负责。就好比人吃进去的食物,在消化之后,必须把废物排出体外,腾出空间可以在下次饿的时候吃饭并消化食物。
对Dalvik、ART虚拟机有什么了解?
JVM是java虚拟机,运行的是java字节码,将字节码保存在class文件,java通过节码class文件来执行
Dalvik是安卓虚拟机,运行的字节码有java字节码转化过来,保存在dex文件中,dev通过执行dex文件来执行字节码
类加载机制
负责加载java字节码,并将字节码转化成.class文件的实例
谈谈对ClassLoader(类加载器)的理解
JVM类加载机制分为五个部分:
加载:主要在内存中生成一个类的Class对象
验证:确保Class中的字节流包含的信息符合虚拟机的要求
准备:为方法区中的变量分配内存控件
解析:虚拟机将常量池中的符号引用替换为直接引用的过程
初始化:真正的执行java代码
谈谈对动态加载(OSGI)的理解
定义:动态加载就是在程序运行过程中动态的获取类的方法、属性、类信息
作用:通过对类的动态加载,我们只需要关注类的改变,而不需要关注实现动态加载相关代码的操作
例如:反射……
内存对象的循环引用及避免
A被B引用,B引用C,C引用A,引用计数法不会解决循环引用,会导致内存泄漏,
1、可达性回收算法
2、尽量避免循环引用
内存回收机制、GC回收策略、GC原理时机以及GC对象
1、java内存分配:
堆:主要存放对象和数组,gc管理
栈:虚拟机栈和本地方法栈
方法区:主要是类、静态变量、常量和编译之后的.class字节码
2、GC回收机制(判断是否可以回收):
引用计数法:
原理:通过一个计数器对对象进行计数,对象被引用时+1,引用失效时-1;当计数为0时则说明可以被回收;
缺点:很难解决对象的相互循环引用问题
可达性算法:“GC Roots”作为对象起始点向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的
3、GC回收机制:(如何回收)
标记清除算法:直接回收没有标记的对象,缺点:容易产生碎片
标记整理算法:将未标记的对象移动到端最后,然后清除
复制算法:将内存分为A、B两块,将A中的对象复制到B中,然后再把A中清除,缺点:牺牲一般内存
分代回收算法:新生代和老年代;整合了标记整理算法和复制算法
4、GC回收机制:(执行回收)
Scavenge GC:当对象申请内存失败时出触发
Full GC :对整个堆进行整理
大体说清一个应用程序安装到手机上时发生了什么
简述Activity启动全部过程
1、点击App图标后通过startActivity远程调用到AMS中,AMS中将新启动的activity以activityrecord的结构压入activity栈中,并通过远程binder回调到原进程,使得原进程进入pause状态,原进程pause后通知AMS我pause了
2、此时AMS再根据栈中Activity的启动intent中的flag是否含有new_task的标签判断是否需要启动新进程,启动新进程通过startProcessXXX的函数
3、启动新进程后通过反射调用ActivityThread的main函数,main函数中调用looper.prepar和lopper.loop启动消息队列循环机制。最后远程告知AMS我启动了。AMS回调handleLauncherAcitivyt加载activity。在handlerLauncherActivity中会通过反射调用Application的onCreate和activity的onCreate以及通过handleResumeActivity中反射调用Activity的onResume
Android为每个应用程序分配的内存大小是多少?
起初是30M,后来google取消了这个限制,可以用过android:largeHeap="true" 来设置
进程保活的方式
1、android进程的优先级
前台进程:当前正在与用户操作的进程
可见进程:没有其他组件,但内容可见
服务进程:执行与前台进程相关的操作
后台进程:用来回收内存,LRU算法
空进程:
2、android进程的回收策略
Low memory kill:比较复杂的评分机制,对进程进行打分,评分高的进程为bad进程,杀死并释放内存
OOM_ODJ:判断进程的优先级,优先级越低,low memory kill就会启动
3、进程保活方案
利用系统广播拉活:通过广播监听被杀死就立即拉活
利用startForground:调用startForground开启一个前台进程,降低oom_odj值,提升进程优先级
目前比较有效的方法有JobScheduler :
如何保证一个后台服务不被杀死?(相同问题:如何保证service在后台不被kill?)比较省电的方式是什么?
1、通过android:priority = 1000提升服务的优先级
2、在onDestroy中通过通知来重启服务
3、通过startForground将服务至于前台:开发者在后台创建job,当某些条件被允许时,后台进程开始工作。
随着系统的更新,很多进程保活方案失效
App中唤醒其他进程的实现方式
1、自定义启动协议:
2、Activity中获取其它进程传递的Data数据
3、正则匹配要跳转的界面
4、在调用方APP使用指定协议跳转
介绍你做过的哪些项目
都使用过哪些框架、平台?
都使用过哪些自定义控件?
研究比较深入的领域有哪些?
最近都读哪些书?
android开发艺术探究,希望多了解一下IPC通信方式和Binder机制。以及四大组件原理
自己最擅长的技术点,最感兴趣的技术领域和技术点
项目中用了哪些开源库,如何避免因为引入开源库而导致的安全性和稳定性问题