Android面试题

Android面试题,第1张

整理八个常见的Android面试题。

1.handler如何进行线程间通信?

负责跨线程通信,这是因为在主线程不能做耗时 *** 作,而子线程不能更新UI,所以当子线程中进行耗时 *** 作后需要更新UI时,通过Handler将有关UI的 *** 作切换到主线程中执行。  

具体分为四大要素:

 Message(消息):需要被传递的消息,消息分为硬件产生的消息(如按钮、触摸)和软件生成的消息。

 MessageQueue(消息队列):负责消息的存储与管理,负责管理由 Handler发送过来的Message。   

Handler(消息处理器):负责Message的发送及处理。主要向消息池发送各种消息事件(Handler.sendMessage())和处理相应消息事件(Handler.handleMessage()),按照先进先出执行,内部使用的是单链表的结构。

Looper(消息池):负责关联线程以及消息的分发,在该线程下从 MessageQueue获取 Message,分发给Handler       

流程:在主线程创建的时候会创建一个Looper,同时也会在在Looper内部创建一个消息队列。而在创键Handler的时候取出当前线程的Looper,并通过该Looper对象获得消息队列,然后Handler在子线程中通过MessageQueue.enqueueMessage在消息队列中添加一条Message。通过Looper.loop() 开启消息循环不断轮询调用 MessageQueue.next(), 取得对应的Message并且通过Handler.dispatchMessage传给Handler,最终调用Handler.handlerMessage处理消息。  

2. Service的使用

Service主要用于组件之间交互(例如:与Activity、ContentProvider、BroadcastReceiver进行交互)、后台执行耗时 *** 作等(例如下载文件,播放音乐等,但Service在主线程运行时长不能超过20s,否则会出现ANR,耗时 *** 作一般建议在子线程中进行 *** 作)。

1.启动模式

此模式通过 startService()方法启动,此服务可以在后台一直运行,不会随启动组件的消亡而消亡。只能执行单一 *** 作,无法返回结果给调用方,常用于网络下载、上传文件,播放音乐等。

2.绑定模式

此模式 通过绑定组件(Activity等)调用 bindService() 启动,此服务随绑定组件的消亡而解除绑定。

3.内存泄漏定位

LeakCanary需要在项目代码中集成,当内存泄漏发生时,LeakCanary 会d窗提示并生成对应的堆存储信息记录, Android Memory Monitor 生成的对储存信息文件可以配置 MAT 一起来分析使用,使用 adb shell dumpsys meminfo [PackageName],可以打印出指定包名的应用内存信息

4.ANR如何分析定位

造成ANR的常见原因:

1.主线程的耗时 *** 作,如复杂的layout/for循环,IO等

2.主线程被子线程同步锁block

3.主线程被Binder对端block

4.Binder被占满导致的主线程无法和SystemServer通信

5.得不到系统资源(CPU/Memory/IO)

分析过程:

1.根据log确定ANR发生的时间,关键字:am_anr /ANR in,同时关注CPU/内存、IO的情况

2.获取ANR产生的trace文件,看时间能不能对的上,判断是不是案发现场,然后关注主线程是否存在耗时、死锁、等锁等问题。

3.结合代码分析问题。 1adb pull data/anr/traces.txt .

5.卡顿解决

一、什么是卡顿呢?

  APP中主要表现在页面的刷新,滑动时的流畅度。例如玩游戏的时候卡,或者听歌的时候画面滞帧,也就是通常人们所说的“卡”。开发者中有一个卡顿16ms原则,每一帧渲染时间不能超过16ms,应达到60帧每秒,如果UI渲染过慢,就会发生丢帧,丢帧的出现就会产生画面的不连贯性,就是卡顿。

二、引起应用卡顿的原因

  1、UI造成的卡顿

  A.过度绘制。过度绘制就是在同一帧情况下对同一块像素区域进行重复绘制。这样会加重GPU跟CPU的渲染压力,导致渲染时间过长。

  B.布局嵌套过多。布局嵌套过多过于复杂也会导致CPU跟GPU的渲染,计算,绘制压力。

  C.动画执行次数过多。

  2、执行耗时 *** 作。文件读写,数据 *** 作,较大数据初始化等较为耗时的 *** 作阻塞线程。

  3、频繁GC。执行GC的时候,所有 *** 作都需要暂停,等到GC结束后,才能继续执行 *** 作。这样就可能会阻塞CPU跟GPU的渲染,计算跟绘制。

三、安卓卡顿解决方法

  1、布局优化:使用merge标签: merge和include结合使用,可以减少布局层级

  2、过度绘制优化:移除不必要的background,比如我们整个页面的背景设置了白色,这样子控件如果再有是白色的就没有必要再设置背景色了。对于自定义的view要减少重复计算和绘制。

  3、动画优化:有些酷炫的动画往往对性能要求比较高,所以可以采用分级方式,判断手机类型,低端手机减少动画。

  4、主线程耗时 *** 作 *** 作优化:主线程也叫UI线程主要的任务是处理用户交互、绘制界面、显示数据、消息处理等工作,如果耗时 *** 作如请求网络数据、 *** 作数据库、读取文件等就不能放在主线程来,可以开启子线程来 *** 作。使用线程池来代替单独创建子线程。

  5、频繁的GC优化:new对象的时候要注意,尽量不要在需要频繁执行的地方New对象。

6、 MVP的结构和优劣点

1)Model (模型层) 在 MVC 中 Model 一般用来保存数据的状态,比如数据存储,网络请求。同时还与View 存在一定的耦合,通过某种事件机制(比如观察者模式) 通知 View 状态的改变来让view 更新。

2)View (视图层)一般由一些GUI 组建组成,同时响应用户的交互行为并触发 Controller 的逻辑,View 还有可能修改Model 的状态 以使其与 Model 同步,View 还会在model 中注册 model 事件的改变。以此来刷新自己并展示给用户。

3)Control (控制层)控制器由View 根据用户行为触发并响应来自view 的用户交互,然后根据view 的事件逻辑来修改对应的Model, Control 并不关心 View 如何展示 相关数据或状态,而是通过修改 Model 来实现view 的数据的刷新。

MVP优点:

模型与视图完全分离,我们可以修改视图而不影响模型;

可以更高效地使用模型,因为所有的交互都发生在一个地方——Presenter内部;

我们可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁;

如果我们把逻辑放在Presenter中,那么我们就可以脱离用户接口来测试这些逻辑(单元测试)。

MVP缺点:

视图和Presenter的交互会过于频繁,使得他们的联系过于紧密。也就是说,一旦视图变更了,presenter也要变更。造成类数量爆炸,代码复杂度和学习成本高,在某些场景下presenter的复用会产生接口冗余。

7、图片的处理,避免oom

BitmapFactory有多种生成Bitmap的方式,其中根据不同的情景有decodeByteArray,decodeFile,decodeResource,decodeStream等多种方式生成Bitmap对象,其中decodeByteArray方法可以对图片的字节数据进行处理,decodeFile可以根据图片的路径处理,decodeResource根据资源文件中的文件进行,decodeStream根据流进行处理,比如网络中的图片。

BitmapFactory.Options这个类有一个布尔值参数inJustDecodeBounds,当inJustDecodeBounds等于true时候,解析程序并不加载当前的图片进入内存,返回的Bitmap等于NULL,虽然Bitmap为空,但是能够从options中获取到当前图片的各种属性信息,比如图片的宽高等。当inJustDecodeBounds为false时候就一切正常,图片加载进入内存了。我们可以根据这一点在图片加载进入内存前对图片进行压缩处理,然后将inJustDecodeBounds=false,进行显示即可。
图片的三级缓存处理技术.三级缓存一般包含三个层级,首先是内存缓存,然后是SD卡缓存,最后是网络下载。

8、App启动流程

启动APP进程:当我们点击Launcher桌面程序的APP图标时,Launcher程序会调用startActivity()函数,通过Binder跨进程通信,发送消息给system_server进程。在system_server进程中,由AMS通过socket通信告知Zygote进程fork出一个子进程(APP进程)。

开启APP主线程:APP进程启动后,会实例化一个ActivityThread,并执行其main函数,同时会创建ApplicationThread、Looper、Handler对象,开启主线程消息循环Looper.loop()。

创建并初始化Application和Activity:ActivityThread的main函数通过调用attach方法进行 Binder 通信,通知system_server进程执行AMS的attachApplication方法。在attachApplication方法中,AMS分别通过bindApplication、scheduleLaunchActivity方法,通知APP进程的主线程Handler,对APP进程的Application和Activity进行初始化,并执行Application、Activity的生命周期。

UI布局和绘制:主线程Handler初始化Activity时,会执行创建PhoneWindow、初始化DecorView的 *** 作,并且添加布局到DecorView的ContentView中。ContentView,对应着Activity的setContentView中设置的layout.xml布局文件所在的最外层父布局。

优化:

1.将Bugly,x5内核初始化,SP的读写,友盟等组件放到子线程中初始化。(子线程初始化不能影响到组件的使用)

2将需要在主线程中初始化但是可以不用立即完成的动作延迟加载(原本是想在入口 Activity 中进行此项 *** 作,不过组件的初始化放在 Application 中统一管理为妙.)

adb shell am start -W 包名/界面名

9. handler asynctask 内存优化

AsynTask内存泄露原因:
在Activity里面AsynTask中执行耗时 *** 作,这个 *** 作并没有因Activity的关闭而停止,当AsynTask持有外部Activity的引用时,AsynTask又没有及时的停止就会导致该Activity不能被回收。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/720544.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-25
下一篇 2022-04-25

发表评论

登录后才能评论

评论列表(0条)

保存