写点什么

2020 上半年百度 Android 岗(初级到高级)面试真题全收录 + 解析

用户头像
Android架构
关注
发布于: 2 小时前

4.Service

4.1、服务启动一般有几种,服务和 activty 之间怎么通信,服务和服务之间怎么通信


方式:1、startService:onCreate()--->onStartCommand() ---> onDestory()如果服务已经开启,不会重复的执行 onCreate(), 而是会调用 onStartCommand()。一旦服务开启跟调用者(开启者)就没有任何关系了。 开启者退出了,开启者挂了,服务还在后台长期的运行。 开启者不能调用服务里面的方法。


2、bindService:onCreate() --->onBind()--->onunbind()--->onDestory()bind 的方式开启服务,绑定服务,调用者挂了,服务也会跟着挂掉。 绑定者可以调用服务里面的方法。通信:1、通过 Binder 对象。2、通过 broadcast(广播)。


4.2、如何保证 Service 不被杀死?


Android 进程不死从 3 个层面入手:


A.提供进程优先级,降低进程被杀死的概率方法一:监控手机锁屏解锁事件,在屏幕锁屏时启动 1 个像素的 Activity,在用户解锁时将 Activity 销毁掉。方法二:启动前台 service。方法三:提升 service 优先级:在 AndroidManifest.xml 文件中对于 intent-filter 可以通过 android:priority = "1000"这个属性设置最高优先级,1000 是最高值,如果数字越小则优先级越低,同时适用于广播。


B. 在进程被杀死后,进行拉活方法一:注册高频率广播接收器,唤起进程。如网络变化,解锁屏幕,开机等方法二:双进程相互唤起。方法三:依靠系统唤起。方法四:onDestroy 方法里重启 service:service + broadcast 方式,就是当 service 走 ondestory 的时候,发送一个自定义的广播,当收到广播的时候,重新启动 service;


C. 依靠第三方根据终端不同,在小米手机(包括 MIUI)接入小米推送、华为手机接入华为推送;其他手机可以考虑接入腾讯信鸽或极光推送与小米推送做 A/B Test。

5.BroadcastReceiver

5.1、广播注册一般有几种,各有什么优缺点?


第一种是常驻型(静态注册):当应用程序关闭后如果有信息广播来,程序也会被系统调用,自己运行。第二种不常驻(动态注册):广播会跟随程序的生命周期。动态注册优点: 在 android 的广播机制中,动态注册优先级高于静态注册优先级,因此在必要情况下,是需要动态注册广播接收者的。缺点: 当用来注册的 Activity 关掉后,广播也就失效了。静态注册优点: 无需担忧广播接收器是否被关闭,只要设备是开启状态,广播接收器就是打开着的。

6.Fragmengt

6.1、activty 和 Fragmengt 之间怎么通信,Fragmengt 和 Fragmengt 怎么通信?


(一)Handler(二)广播(三)事件总线:EventBus、RxBus、Otto(四)接口回调(五)Bundle 和 setArguments(bundle)

7.View

7.1、自定义 view 效率高于 xml 定义吗?说明理由。


自定义 view 效率高于 xml 定义:1、少了解析 xml。2.、自定义 View 减少了 ViewGroup 与 View 之间的测量,包括父量子,子量自身,子在父中位置摆放,当子 view 变化时,父的某些属性都会跟着变化。


7.2、ListView 卡顿原因


Adapter 的 getView 方法里面 convertView 没有使用 setTag 和 getTag 方式;在 getView 方法里面 ViewHolder 初始化后的赋值或者是多个控件的显示状态和背景的显示没有优化好,抑或是里面含有复杂的计算和耗时操作;在 getView 方法里面 inflate 的 row 嵌套太深(布局过于复杂)或者是布局里面有大图片或者背景所致;Adapter 多余或者不合理的 notifySetDataChanged;listview 被多层嵌套,多次的 onMessure 导致卡顿,如果多层嵌套无法避免,建议把 listview 的高和宽设置为 match_parent. 如果是代码继承的 listview,那么也请你别忘记为你的继承类添加上 LayoutPrams,注意高和宽都 mactch_parent 的;


7.3、LinearLayout、FrameLayout、RelativeLayout 性能对比,为什么?


RelativeLayout 会让子 View 调用 2 次 onMeasure,LinearLayout 在有 weight 时,也会调用子 View 2 次 onMeasureRelativeLayout 的子 View 如果高度和 RelativeLayout 不同,则会引发效率问题,当子 View 很复杂时,这个问题会更加严重。如果可以,尽量使用 padding 代替 margin。在不影响层级深度的情况下,使用 LinearLayout 和 FrameLayout 而不是 RelativeLayout。

中场休息

8.数据传输与序列化

8.1Bunder 传递对象为什么需要序列化?Serialzable 和 Parcelable 的区别?


因为 bundle 传递数据时只支持基本数据类型,所以在传递对象时需要序列化转换成可存储或可传输的本质状态(字节流)。序列化后的对象可以在网络、IPC(比如启动另一个进程的 Activity、Service 和 Reciver)之间进行传输,也可以存储到本地。Serializable(Java 自带):Serializable 是序列化的意思,表示将一个对象转换成存储或可传输的状态。序列化后的对象可以在网络上进传输,也可以存储到本地。Parcelable(android 专用):除了 Serializable 之外,使用 Parcelable 也可以实现相同的效果,不过不同于将对象进行序列化,Parcelable 方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是 Intent 所支持的数据类型,这也就实现传递对象的功能了。


8.2、android 中有哪几种解析 xml 的类,官方推荐哪种?以及它们的原理和区别?


DOM 解析优点:1.XML 树在内存中完整存储,因此可以直接修改其数据结构.2.可以通过该解析器随时访问 XML 树中的任何一个节点.3.DOM 解析器的 API 在使用上也相对比较简单.缺点:如果 XML 文档体积比较大时,将文档读入内存是非消耗系统资源的.使用场景:

  • DOM 是与平台和语言无关的方式表示 XML 文档的官方 W3C 标准.

  • DOM 是以层次结构组织的节点的集合.这个层次结构允许开人员在树中寻找特定信息.分析该结构通常需要加载整个文档和构造层次结构,然后才能进行任何工作.

  • DOM 是基于对象层次结构的.


SAX 解析优点:SAX 对内存的要求比较低,因为它让开发人员自己来决定所要处理的标签.特别是当开发人员只需要处理文档中包含的部分数据时,SAX 这种扩展能力得到了更好的体现.缺点:用 SAX 方式进行 XML 解析时,需要顺序执行,所以很难访问同一文档中的不同数据.此外,在基于该方式的解析编码程序也相对复杂.使用场景:对于含有数据量十分巨大,而又不用对文档的所有数据行遍历或者分析的时候,使用该方法十分有效.该方法不将整个文档读入内存,而只需读取到程序所需的文档标记处即可.


Xmlpull 解析 android SDK 提供了 xmlpullapi,xmlpull 和 sax 类似,是基于流(stream)操作文件,后者根据节点事件回调开发者编写的处理程序.因为是基于流的处理,因此 xmlpull 和 sax 都比较节约内存资源,不会像 dom 那样要把所有节点以对象树的形式展现在内存中.xmpull 比 sax 更简明,而且不需要扫描完整个流.

9.Android 进程

9.1、android 中进程的优先级?


1.前台进程:即与用户正在交互的 Activity 或者 Activity 用到的 Service 等,如果系统内存不足时前台进程是最晚被杀死的 2.可见进程:可以是处于暂停状态(onPause)的 Activity 或者绑定在其上的 Service,即被用户可见,但由于失了焦点而不能与用户交互 3.服务进程:其中运行着使用 startService 方法启动的 Service,虽然不被用户可见,但是却是用户关心的,例如用户正在非音乐界面听的音乐或者正在非下载页面下载的文件等;当系统要空间运行,前两者进程才会被终止 4.后台进程:其中运行着执行 onStop 方法而停止的程序,但是却不是用户当前关心的,例如后台挂着的 QQ,这时的进程系统一旦没了有内存就首先被杀死 5.空进程:不包含任何应用程序的进程,这样的进程系统是一般不会让他存在的


9.2、Android 中跨进程通讯的几种方式


1:访问其他应用程序的 Activity 如调用系统通话应用 2:Content Provider 如访问系统相册 3:广播(Broadcast) 如显示系统时间 4:AIDL 服务


9.3、为什么要用多进程?有哪些方式?怎么使用多进程


我们都知道,android 平台对应用都有内存限制,其实这个理解有点问题,应该是说 android 平台对每个进程有内存限制,比如某机型对对进程限制是 24m,如果应用有两个进程,则该应该的总内存限制是 2*24m。使用多进程就可以使得我们一个 apk 所使用的内存限制加大几倍。所以可以借此图片平台对应用的内存限制,比如一些要对图片、视频、大文件进程处理的好内存的应用可以考虑用多进程来解决应用操作不流畅问题。


开启多进程模式: 在 Android 中 使 用多 进程 只 有 一 种方 法,那 就是 在 AndroidManifest 中 给 四 大 组件(Activity,Service,Receiver,ContentProvider)指定 android:process 属性.除此之外没有其他的办法,也就是说我们无法给一个线程活一个实体类指定其运行时所在的进程.其实还有另一种非常规的多进程方法,那就是通过 JNI 在 native 层去 fork 一个新的进程,但这种方法属于特殊情况,并不是常用的创建多进程的方式,所以我们也暂不考虑这种情况进程名以":"开头的进程属于当前应用的私有进程,其他应用的组件不可以和它跑在同一个进程中,而进程名不以":"开头的进程属于全局进程,其他应用通过 ShareUID 方式可以和它跑在同一个进程中.用多进程的好处与坏处


好处 1)分担主进程的内存压力。当应用越做越大,内存越来越多,将一些独立的组件放到不同的进程,它就不占用主进程的内存空间了。当然还有其他好处,有心人会发现 2)使应用常驻后台,防止主进程被杀守护进程,守护进程和主进程之间相互监视,有一方被杀就重新启动它。Android 后台进程里有很多应用是多个进程的,因为它们要常驻后台,特别是即时通讯或者社交应用,不过现在多进程已经被用烂了。典型用法是在启动一个不可见的轻量级私有进程,在后台收发消息,或者做一些耗时的事情,或者开机启动这个进程,然后做监听等。


坏处:消耗用户的电量。多占用了系统的空间,若所有应用都这样占用,系统内存很容易占满而导致卡顿。应用程序架构会变得复杂,因为要处理多进程之间的通信。这里又是另外一个问题了。多进程的缺陷进程间的内存空间是不可见的。开启多进程后,会引发以下问题:1)Application 的多次重建。2)静态成员的失效。3)文件共享问题。4)断点调试问题。

10.Android 各版本新特性

10.1、Android5.0 新特性


1.MaterialDesign 设计风格 2.支持 64 位 ART 虚拟机(5.0 推出的 ART 虚拟机,在 5.0 之前都是 Dalvik。他们的区别是:Dalvik,每次运行,字节码都需要通过即时编译器转换成机器码(JIT)。ART,第一次安装应用的时候,字节码就会预先编译成机器码(AOT))3.通知详情可以用户自己设计


10.2、Android6.0 新特性


1.动态权限管理 2.支持快速充电的切换 3.支持文件夹拖拽应用 4.相机新增专业模式


10.3、Android7.0 新特性


1.多窗口支持 2.V2 签名 3.增强的 Java8 语言模式 4.夜间模式


10.4、Android8.0(O)新特性


1.通知渠道 (Notification Channel)通知标志休眠通知超时通知设置通知清除 2.画中画模式:清单中 Activity 设置 android:supportsPictureInPicture3.后台限制 4.自动填充框架 5.系统优化 6.等等优化很多


10.5、Android9.0(P)新特性


1.室内 WIFI 定位 2.“刘海”屏幕支持 3.安全增强


10.6、Android10.0 新特性


夜间模式:包括手机上的所有应用都可以为其设置暗黑模式。桌面模式:提供类似于 PC 的体验,但是远远不能代替 PC。屏幕录制:通过长按“电源”菜单中的"屏幕快照"来开启。

11.Bitmap

11.1、Bitmap 使用时候注意什么?


1、要选择合适的图片规格(bitmap 类型)2、降低采样率。BitmapFactory.Options 参数 inSampleSize 的使用,先把 options.inJustDecodeBounds 设为 true,只是去读取图片的大小,在拿到图片的大小之后和要显示的大小做比较通过 calculateInSampleSize()函数计算 inSampleSize 的具体值,得到值之后。options.inJustDecodeBounds 设为 false 读图片资源。3、复用内存。即,通过软引用(内存不够的时候才会回收掉),复用内存块,不需要再重新给这个 bitmap 申请一块新的内存,避免了一次内存的分配和回收,从而改善了运行效率。4、使用 recycle()方法及时回收内存。5、压缩图片。


11.2、如何计算一个 Bitmap 占用内存的大小,怎么保证加载 Bitmap 不产生内存溢出?


在 Bitmap 里有两个获取内存占用大小的方法。(1)getByteCount():API12 加入,代表存储 Bitmap 的像素需要的最少内存。 getAllocationByteCount():API19 加入,代表在内存中为 Bitmap 分配的内存大小,代替了 getByteCount() 方法。 在不复用 Bitmap 时,getByteCount() 和 getAllocationByteCount 返回的结果是一样的。在通过复用 Bitmap 来解码图片时,那么 getByteCount() 表示新解码图片占用内存的大 小,getAllocationByteCount() 表示被复用 Bitmap 真实占用的内存大小(即 mBuffer 的长度)。(2)BitmapFactory.Options.inPreferredConfig:将 ARGB_8888 改为 RGB_565,改变编码方式,节约内存。 BitmapFactory.Options.inSampleSize:缩放比例,可以参考 Luban 那个库,根据图片宽高计算出合适的缩放比例。 BitmapFactory.Options.inPurgeable:让系统可以内存不足时回收内存。


11.3、一张图片加载到手机内存中真正的大小是怎么计算的

12.更新 UI 方式

Activity.runOnUiThread(Runnable)View.post(Runnable),View.postDelay(Runnable, long)(可以理解为在当前操作视图 UI 线程添加队列)HandlerAsyncTaskRxjavaLiveData

13.什么是 ANR 如何避免它?

在 Android 上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称作应用程序无响应(ANR:Application NotResponding)对话框。用户可以选择让程序继续运行,但是,他们在使用你的应用程序时,并不希望每次都要处理这个对话框。因此,在程序里对响应性能的设计很重要这样,这样系统就不会显示 ANR 给用户。

14.AsyncTask 的缺陷和问题,说说他的原理。

AsyncTask 是什么?AsyncTask 是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并在主线程中更新 UI。AsyncTask 是一个抽象的泛型类,它提供了 Params、Progress 和 Result 这三个泛型参数,其中 Params 表示参数的类型,Progress 表示后台任务的执行进度和类型,而 Result 则表示后台任务的返回结果的类型,如果 AsyncTask 不需要传递具体的参数,那么这三个泛型参数可以用 Void 来代替。


关于线程池:AsyncTask 对应的线程池 ThreadPoolExecutor 都是进程范围内共享的,且都是 static 的,所以是 Asynctask 控制着进程范围内所有的子类实例。由于这个限制的存在,当使用默认线程池时,如果线程数超过线程池的最大容量,线程池就会爆掉(3.0 后默认串行执行,不会出现个问题)。针对这种情况,可以尝试自定义线程池,配合 Asynctask 使用。


关于默认线程池:AsyncTask 里面线程池是一个核心线程数为 CPU + 1,最大线程数为 CPU * 2 + 1,工作队列长度为 128 的线程池,线程等待队列的最大等待数为 28,但是可以自定义线程池。线程池是由 AsyncTask 来处理的,线程池允许 tasks 并行运行,需要注意的是并发情况下数据的一致性问题,新数据可能会被老数据覆盖掉。所以希望 tasks 能够串行运行的话,使用 SERIAL_EXECUTOR。


AsyncTask 在不同的 SDK 版本中的区别:调用 AsyncTask 的 execute 方法不能立即执行程序的原因及改善方案通过查阅官方文档发现,AsyncTask 首次引入时,异步任务是在一个独立的线程中顺序的执行,也就是说一次只执行一个任务,不能并行的执行,从 1.6 开始,AsyncTask 引入了线程池,支持同时执行 5 个异步任务,也就是说只能有 5 个线程运行,超过的线程只能等待,等待前的线程直到某个执行完了才被调度和运行。换句话说,如果进程中的 AsyncTask 实例个数超过 5 个,那么假如前 5 都运行很长时间的话,那么第 6 个只能等待机会了。这是 AsyncTask 的一个限制,而且对于 2.3 以前的版本无法解决。如果你的应用需要大量的后台线程去执行任务,那么只能放弃使用 AsyncTask,自己创建线程池来管理 Thread。不得不说,虽然 AsyncTask 较 Thread 使用起来方便,但是它最多只能同时运行 5 个线程,这也大大局限了它的作用,你必须要小心设计你的应用,错开使用 AsyncTask 时间,尽力做到分时,或者保证数量不会大于 5 个,否就会遇到上面提到的问题。可能是 Google 意识到了 AsynTask 的局限性了,从 Android 3.0 开始对 AsyncTask 的 API 做出了一些调整:每次只启动一个线程执行一个任务,完了之后再执行第二个任务,也就是相当于只有一个后台线程在执行所提交的任务。


一些问题:1.生命周期很多开发者会认为一个在 Activity 中创建的 AsyncTask 会随着 Activity 的销毁而销毁。然而事实并非如此。AsynTask 会一直执行,直到 doInBackground()方法执行完毕,然后,如果 cancel(boolean)被调用,那么 onCancelled(Result result)方法会被执行;否则,执行 onPostExecute(Result result)方法。如果我们的 Activity 销毁之前,没有取消 AsyncTask,这有可能让我们的应用崩溃(crash)。因为它想要处理的 view 已经不存在了。所以,我们是必须确保在销毁活动之前取消任务。总之,我们使用 AsyncTask 需要确保 AsyncTask 正确的取消。2.内存泄漏如果 AsyncTask 被声明为 Activity 的非静态内部类,


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


那么 AsyncTask 会保留一个对 Activity 的引用。如果 Activity 已经被销毁,AsyncTask 的后台线程还在执行,它将继续在内存里保留这个引用,导致 Activity 无法被回收,引起内存泄漏。3.结果丢失屏幕旋转或 Activity 在后台被系统杀掉等情况会导致 Activity 的重新创建,之前运行的 AsyncTask 会持有一个之前 Activity 的引用,这个引用已经无效,这时调用 onPostExecute()再去更新界面将不再生效。4.并行还是串行在 Android1.6 之前的版本,AsyncTask 是串行的,在 1.6 之后的版本,采用线程池处理并行任务,但是从 Android 3.0 开始,为了避免 AsyncTask 所带来的并发错误,又采用一个线程来串行执行任务。可以使用 executeOnExecutor()方法来并行地执行任务。


AsyncTask 原理 AsyncTask 中有两个线程池(SerialExecutor 和 THREAD_POOL_EXECUTOR)和一个 Handler(InternalHandler),其中线程池 SerialExecutor 用于任务的排队,而线程池 THREAD_POOL_EXECUTOR 用于真正地执行任务,InternalHandler 用于将执行环境从线程池切换到主线程。InternalHandler 是一个静态的 Handler 对象,为了能够将执行环境切换到主线程,这就要求 sHandler 这个对象必须在主线程创建。由于静态成员会在加载类的时候进行初始化,因此这就变相要求 AsyncTask 的类必须在主线程中加载,否则同一个进程中的 AsyncTask 都将无法正常工作。

草草收尾

上篇2020上半年百度Android岗(初级到高级)面试真题全收录+解析,备战金九银十!(上篇)


写着写着发现篇幅太长,又写不下了,所以放到下一篇讲了,喜欢的小伙伴可以点个收藏关注,插个眼,下集在我的主页,马上更新~


BATJ 大厂面试真题收录大全 PDF 电子书已上传在石墨文档:【BATJ面试大全】需要的小伙伴自取就好了。别忘了给文章点个赞~



参考


https://juejin.im/post/6844904079160770568#heading-147https://juejin.im/post/6844904087566155784

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
2020上半年百度Android岗(初级到高级)面试真题全收录+解析