美文网首页
Android 面试题

Android 面试题

作者: android_yiluo | 来源:发表于2020-08-24 19:51 被阅读0次

    1、RecyclerView和ListView的区别

    缓存上:前者缓存的是View+ViewHolder+flag,不用每次调用findViewById,后者则只是缓存View

    刷新数据方面,前者提供了局部刷新,后者则全部刷新

    2、recyclerView嵌套卡顿解决如何解决

    设置预加载的数量LinearLayoutManager.setInitialPrefetchItemCount(4),默认是预加载2个,

    设置子项缓存,

    设置自带滑动冲突解决属性rv.setHasFixedSize(true);      

      rv.setNestedScrollingEnabled(false);

    可以完美解决,不过Google不推荐RecyClerView嵌套使用,需要嵌套尽量找类似于ExpandableListView 第三方控件来解决

    3、谈MVC ,MVP,MVVM

    MVC:View是可以直接访问Model的!从而,View里会包含Model信息,不可避免的还要包括一些 业务逻辑。 在MVC模型里,更关注的Model的不变,而同时有多个对Model的不同显示,及View。所以,在MVC模型里,Model不依赖于View,但是 View是依赖于Model的。不仅如此,因为有一些业务逻辑在View里实现了,导致要更改View也是比较困难的,至少那些业务逻辑是无法重用的。

    MVP:MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负 责显示。作为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从直接Model中读取数据而不是通过 Controller。

    MVVM:数据双向绑定,通过数据驱动UI,M提供数据,V视图,VM即数据驱动层

    4 、Android性能优化

    布局优化: 减少布局层级,使用ViewStub提高显示速度,布局服用,尽可能少使用warp_content,删除空间中无用的属性,避免过度绘制移除window默认背景,按需显示展位图,自定义View优化,使用canvas.clipRect()识别可见区域

    启动速度:采用分布加载,异步加载,延期加载提高应用初始化速度,采用线程初始化数据等,合理的刷新机制

    内存方面:防止内存泄露,使用一些第三方工具检测解决

    代码优化:遵循Java生命周期

    安装包优化:删除无用资源,优化图片,代码混淆,避免重复库存在,插件化

    5、Fragment中add与replace的区别?

    add不会重新初始化fragment,replace每次都会;

    添加相同的fragment时,replace不会有任何变化,add会报IllegalStateException 异常;

    replace 先 remove 掉相同 id 的所有 fragment,然后在add 当前的这个 fragment,而 add 是覆盖前一个fragment。所以如果使用 add 一般会伴随 hide()和show(),避免布局重叠;

    使用 add,如果应用放在后台,或以其他方式被系统销毁,再打开时,hide()中引用的 fragment 会销毁,所以依然会出现布局重叠 bug,可以使用 replace 或使用 add时,添加一个 tag 参数;

    6、如何避免OOM?

    1.使用更加轻量的数据结构:如使用ArrayMap/SparseArray替代HashMap,HashMap更耗内存,因为它需要额外的实例对象来记录Mapping操作,SparseArray更加高效,因为它避免了Key Value的自动装箱,和装箱后的解箱操作

    2.便面枚举的使用,可以用静态常量或者注解@IntDef替代

    3.Bitmap优化:

    a.尺寸压缩:通过InSampleSize设置合适的缩放

    b.颜色质量:设置合适的format,ARGB_6666/RBG_545/ARGB_4444/ALPHA_6,存在很大差异

    c.inBitmap:使用inBitmap属性可以告知Bitmap解码器去尝试使用已经存在的内存区域,新解码的Bitmap会尝试去使用之前那张Bitmap在Heap中所占据的pixel data内存区域,而不是去问内存重新申请一块区域来存放Bitmap。利用这种特性,即使是上千张的图片,也只会仅仅只需要占用屏幕所能够显示的图片数量的内存大小,但复用存在一些限制,具体体现在:在Android 4.4之前只能重用相同大小的Bitmap的内存,而Android 4.4及以后版本则只要后来的Bitmap比之前的小即可。使用inBitmap参数前,每创建一个Bitmap对象都会分配一块内存供其使用,而使用了inBitmap参数后,多个Bitmap可以复用一块内存,这样可以提高性能

    4.StringBuilder替代String: 在有些时候,代码中会需要使用到大量的字符串拼接的操作,这种时候有必要考虑使用StringBuilder来替代频繁的“+”

    5.避免在类似onDraw这样的方法中创建对象,因为它会迅速占用大量内存,引起频繁的GC甚至内存抖动

    6.减少内存泄漏也是一种避免OOM的方法

    7、如何实现进程保活

    a: Service 设置成 START_STICKY kill 后会被重启(等待5秒左右),重传Intent,保持与重启前一样

    b: 通过 startForeground将进程设置为前台进程, 做前台服务,优先级和前台应用一个级别,除非在系统内存非常缺,否则此进程不会被 kill

    c: 双进程Service: 让2个进程互相保护对方,其中一个Service被清理后,另外没被清理的进程可以立即重启进程

    d: 用C编写守护进程(即子进程) : Android系统中当前进程(Process)fork出来的子进程,被系统认为是两个不同的进程。当父进程被杀死的时候,子进程仍然可以存活,并不受影响(Android5.0以上的版本不可行)联系厂商,加入白名单

    e.锁屏状态下,开启一个一像素Activity

    8、说下冷启动与热启动是什么,区别,如何优化,使用场景等。

    app冷启动: 当应用启动时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用, 这个启动方式就叫做冷启动(后台不存在该应用进程)。冷启动因为系统会重新创建一个新的进程分配给它,所以会先创建和初始化Application类,再创建和初始化MainActivity类(包括一系列的测量、布局、绘制),最后显示在界面上。

    app热启动: 当应用已经被打开, 但是被按下返回键、Home键等按键时回到桌面或者是其他程序的时候,再重新打开该app时, 这个方式叫做热启动(后台已经存在该应用进程)。热启动因为会从已有的进程中来启动,所以热启动就不会走Application这步了,而是直接走MainActivity(包括一系列的测量、布局、绘制),所以热启动的过程只需要创建和初始化一个MainActivity就行了,而不必创建和初始化Application

    冷启动的流程

    当点击app的启动图标时,安卓系统会从Zygote进程中fork创建出一个新的进程分配给该应用,之后会依次创建和初始化Application类、创建MainActivity类、加载主题样式Theme中的windowBackground等属性设置给MainActivity以及配置Activity层级上的一些属性、再inflate布局、当onCreate/onStart/onResume方法都走完了后最后才进行contentView的measure/layout/draw显示在界面上

    冷启动的生命周期简要流程::

    Application构造方法 –> attachBaseContext()–>onCreate –>Activity构造方法 –> onCreate() –> 配置主体中的背景等操作 –>onStart() –> onResume() –> 测量、布局、绘制显示

    冷启动的优化主要是视觉上的优化,解决白屏问题,提高用户体验,所以通过上面冷启动的过程。能做的优化如下:

    减少 onCreate()方法的工作量

    不要让 Application 参与业务的操作

    不要在 Application 进行耗时操作

    不要以静态变量的方式在 Application 保存数据

    减少布局的复杂度和层级

    减少主线程耗时

    为什么冷启动会有白屏黑屏问题?原因在于加载主题样式Theme中的windowBackground等属性设置给MainActivity发生在inflate布局当onCreate/onStart/onResume方法之前,而windowBackground背景被设置成了白色或者黑色,所以我们进入app的第一个界面的时候会造成先白屏或黑屏一下再进入界面。解决思路如下

    1.给他设置 windowBackground 背景跟启动页的背景相同,如果你的启动页是张图片那么可以直接给 windowBackground 这个属性设置该图片那么就不会有一闪的效果了

    <style name=``"Splash_Theme"` `parent=``"@android:style/Theme.NoTitleBar"``>`

        <item name=``"android:windowBackground"``>@drawable/splash_bg</item>`

        <item name=``"android:windowNoTitle"``>``true``</item>`

    </style>`

    2.采用世面的处理方法,设置背景是透明的,给人一种延迟启动的感觉。,将背景颜色设置为透明色,这样当用户点击桌面APP图片的时候,并不会"立即"进入APP,而且在桌面上停留一会,其实这时候APP已经是启动的了,只是我们心机的把Theme里的windowBackground 的颜色设置成透明的,强行把锅甩给了手机应用厂商(手机反应太慢了啦)

    <style name=``"Splash_Theme"` `parent=``"@android:style/Theme.NoTitleBar"``>`

        <item name=``"android:windowIsTranslucent"``>``true``</item>`

        <item name=``"android:windowNoTitle"``>``true``</item>`

    </style>`

    3.以上两种方法是在视觉上显得更快,但其实只是一种表象,让应用启动的更快,有一种思路,将 Application 中的不必要的初始化动作实现懒加载,比如,在SpashActivity 显示后再发送消息到 Application,去初始化,这样可以将初始化的动作放在后边,缩短应用启动到用户看到界面的时间

    9、wait和 sleep 的区别

    wait是Object的方法,wait是对象锁,锁定方法不让继续执行,当执行notify方法后就会继续执行,sleep 是Thread的方法,sleep 是使线程睡眠,让出cpu,结束后自动继续执行

    10、String,StringBuffer,StringBuilder的区别

    String不可改变对象,一旦创建就不能修改

    StringBuffer创建之后,可以去修改

    StringBuilder也可修改,执行效率高于StringBuffer,不安全

    当字符赋值少使用String

    字符赋值频繁使用StringBuilder

    当多个线程同步操作数据,使用StringBuffer

    11、进程和线程的区别

    概念:进程包括多个线程,一个程序一个进程,多线程的优点可以提高执行效率,提高资源利用率

    创建:Thread类和Runnable接口,

    常用方法有:

    start()用于启动线程

    run()调用线程对象中的run方法

    join()合并插队到当前线程

    sellp()睡眠释放cpu资源

    setPriority()设置线程优先级

    12、隐式Intent与显示Intent的区别

    显示intent效率高,系统直接精确定位要启用的组件,但耦合度也高,如果通过这种方式调用一些系统组件的话,容易因为版本更新,类名、包名、包结构变化等原因导致程序崩溃。隐式意图能够降低程序的耦合度,但由于每次意图执行的时候,系统都会搜索所有可用的intentfilter,来查看是否有匹配的内容,所以效率更低。

    相关文章

      网友评论

          本文标题:Android 面试题

          本文链接:https://www.haomeiwen.com/subject/vbqojktx.html