最后
希望大家能有一个好心态,想进什么样的公司要想清楚,并不一定是大公司,我选的也不是特大厂。当然如果你不知道选或是没有规划,那就选大公司!希望我们能先选好想去的公司再投或内推,而不是有一个公司要我我就去!还有就是不要害怕,也不要有压力,平常心对待就行,但准备要充足。最后希望大家都能拿到一份满意的 offer !如果目前有一份工作也请好好珍惜好好努力,找工作其实挺累挺辛苦的。
这里附上上述的面试题相关的几十套字节跳动,京东,小米,腾讯、头条、阿里、美团等公司19年的面试题。把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。
由于篇幅有限,这里以图片的形式给大家展示一小部分。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
GC 回收算法有以下四种:
**分代收集算法:**是当前商业虚拟机都采用的一种算法,根据对象存活周期的不同,将 Java 堆划分为新生代和老年代,并根据各个年代的特点采用最适当的收集算法。
**新生代:**大批对象死去,只有少量存活。使用『复制算法』,只需复制少量存活对象即可。
复制算法:把可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用尽后,把还存活着的对象『复制』到另外一块上面,再将这一块内存空间一次清理掉。实现简单,运行高效。在对象存活率较高时就要进行较多的复制操作,效率将会变低
**老年代:**对象存活率高。使用『标记 — 清理算法』或者『标记 — 整理算法』,只需标记较少的回收对象即可。
标记 - 清除算法:首先『标记』出所有需要回收的对象,然后统一『清除』所有被标记的对象。标记和清除两个过程的效率都不高,清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。
标记 - 整理算法:首先『标记』出所有需要回收的对象,然后进行『整理』,使得存活的对象都向一端移动,最后直接清理掉端边界以外的内存。标记整理算法会将所有的存活对象移动到一端,并对不存活对象进行处理,因此其不会产生内存碎片
推荐文章:图解 Java 垃圾回收机制(https://blog.csdn.net/justloveyou_/article/details/71216049)
6、内存泄露和内存溢出的区别 ?AS 有什么工具可以检测内存泄露
-
内存溢出 (out of memory):是指程序在申请内存时,没有足够的内存空间供其使用,出现 out of memory;比如申请了一个 integer,但给它存了 long 才能存下的数,那就是内存溢出。
-
内存泄露 (memory leak):是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。memory leak 会最终会导致 out of memory!
-
查找内存泄漏可以使用 Android Studio 自带的 AndroidProfiler 工具或 MAT
7、性能优化,怎么保证应用启动不卡顿?黑白屏怎么处理?
应用启动速度:取决于你在 application 里面时候做了什么事情,比如你集成了很多 sdk,并且 sdk 的 init 操作都需要在主线程里实现所以会有卡顿的感觉。在非必要的情况下可以把加载延后或则开启子线程处理
另外,影响界面卡顿的两大因素,分别是界面绘制和数据处理:
-
布局优化 (使用 include,merge 标签,复杂布局推荐使用 ConstraintLayout 等)
-
onCreate () 中不执行耗时操作 把页面显示的 View 细分一下,放在 AsyncTask 里逐步显示,用 Handler 更好。这样用户的看到的就是有层次有步骤的一个个的 View 的展示,不会是先看到一个黑屏,然后一下显示所有 View。最好做成动画,效果更自然。
-
利用多线程的目的就是尽可能的减少 onCreate () 和 onReume () 的时间,使得用户能尽快看到页面,操作页面。
-
减少主线程阻塞时间。
-
提高 Adapter 和 AdapterView 的效率。
推荐文章:Android 性能优化之内存检测、卡顿优化、耗电优化、APK 瘦身
(https://blog.csdn.net/csdn_aiyang/article/details/74989318)
黑白屏产生原因:当我们在启动一个应用时,系统会去检查是否已经存在这样一个进程,如果不存在,系统的服务会先检查 startActivity 中的 intent 的信息,然后在去创建进程,最后启动 Acitivy,即冷启动。而启动出现白黑屏的问题,就是在这段时间内产生的。系统在绘制页面加载布局之前,首先会初始化窗口(Window),而在进行这一步操作时,系统会根据我们设置的 Theme 来指定它的 Theme 主题颜色,我们在 Style 中的设置就决定了显示的是白屏还是黑屏。
-
windowIsTranslucent 和 windowNoTitle,将这两个属性都设置成 true (会有明显的卡顿体验,不推荐)
-
如果启动页只是是一张图片,那么为启动页专一设置一个新的主题,设置主题的 android:windowBackground 属性为启动页背景图即可
-
使用 layer-list 制作一张图片 launcher_layer.xml,将其设置为启动页专一主题的背景,并将其设置为启动页布局的背景。
推荐文章:Android 启动页解决攻略
(https://blog.csdn.net/zivensonice/article/details/51691136)
8、强引用置为 null,会不会被回收?
参考回答:不会立即释放对象占用的内存。如果对象的引用被置为 null,只是断开了当前线程栈帧中对该对象的引用关系,而 垃圾收集器是运行在后台的线程,只有当用户线程运行到安全点 (safe point) 或者安全区域才会扫描对象引用关系,扫描到对象没有被引用则会标记对象,这时候仍然不会立即释放该对象内存,因为有些对象是可恢复的(在 finalize 方法中恢复引用 )。只有确定了对象无法恢复引用的时候才会清除对象内存。
9、ListView 跟 RecyclerView 的区别:
动画区别:
-
在 RecyclerView 中,内置有许多动画 API,例如:notifyItemChanged (), notifyDataInserted (), notifyItemMoved () 等等;如果需要自定义动画效果,可以通过实现(RecyclerView.ItemAnimator 类)完成自定义动画效果,然后调用 RecyclerView.setItemAnimator ();
-
但是 ListView 并没有实现动画效果,但我们可以在 Adapter 自己实现 item 的动画效果;
刷新区别:
-
ListView 中通常刷新数据是用全局刷新 notifyDataSetChanged (),这样一来就会非常消耗资源;本身无法实现局部刷新,但是如果要在 ListView 实现局部刷新,依然是可以实现的,当一个 item 数据刷新时,我们可以在 Adapter 中,实现一个 onItemChanged () 方法,在方法里面获取到这个 item 的 position(可以通过 getFirstVisiblePosition ()),然后调用 getView () 方法来刷新这个 item 的数据;
-
RecyclerView 中可以实现局部刷新,例如:notifyItemChanged ();
缓存区别:
-
RecyclerView 比 ListView 多两级缓存,支持多个离 ItemView 缓存,支持开发者自定义缓存处理逻辑,支持所有 RecyclerView 共用同一个 RecyclerViewPool (缓存池)。
-
ListView 和 RecyclerView 缓存机制基本一致,但缓存使用不同
推荐文章:
-
【腾讯 Bugly 干货分享】Android ListView 与 RecyclerView 对比浅析 — 缓存机制(https://zhuanlan.zhihu.com/p/23339185)
-
ListView 与 RecyclerView 简单对比(https://blog.csdn.net/shu_lance/article/details/79566189)
-
Android 开发:ListView、AdapterView、RecyclerView 全面解析(https://www.jianshu.com/p/4e8e4fd13cf7)
10、ListView 的 adapter 是什么 adapter?
-
BaseAdapter:抽象类,实际开发中我们会继承这个类并且重写相关方法,用得最多的一个适配器!
-
ArrayAdapter:支持泛型操作,最简单的一个适配器,只能展现一行文字〜
-
SimpleAdapter:同样具有良好扩展性的一个适配器,可以自定义多种效果!
-
SimpleCursorAdapter:用于显示简单文本类型的 listView,一般在数据库那里会用到,不过有点过时,不推荐使用!
11、LinearLayout、FrameLayout、RelativeLayout 性能对比,为什么?
-
RelativeLayout 会让子 View 调用 2 次 onMeasure,LinearLayout 在有 weight 时,也会调用子 View 2 次 onMeasure
-
RelativeLayout 的子 View 如果高度和 RelativeLayout 不同,则会引发效率问题,当子 View 很复杂时,这个问题会更加严重。如果可以,尽量使用 padding 代替 margin。
-
在不影响层级深度的情况下,使用 LinearLayout 和 FrameLayout 而不是 RelativeLayout。
JNI
1、对 JNI 是否了解?
参考回答:Java 的优点是跨平台,但也因为其跨平台的的特性导致其本地交互的能力不够强大,一些和操作系统相关的的特性 Java 无法完成,于是 Java 提供 JNI 专门用于和本地代码交互,通过 JNI,用户可以调用 C、C++ 编写的本地代码
NDK 是 Android 所提供的一个工具集合,通过 NDK 可以在 Android 中更加方便地通过 JNI 访问本地代码,其优点在于:
-
提高代码的安全性。由于 so 库反编译困难,因此 NDK 提高了 Android 程序的安全性
-
可以很方便地使用目前已有的 C/C++ 开源库
-
便于平台的移植。通过 C/C++ 实现的动态库可以很方便地在其它平台上使用
-
提高程序在某些特定情形下的执行效率,但是并不能明显提升 Android 程序的性能
2、如何加载 NDK 库 ?如何在 JNI 中注册 Native 函数,有几种注册方法 ?
public class JniTest{
//加载NDK库
static{
System.loadLirary(“jni-test”);
}
}
注册 JNI 函数的两种方法:
-
静态方法
-
动态注册
推荐文章:
-
注册 JNI 函数的两种方式(https://blog.csdn.net/wwj_748/article/details/52347341)
-
Android JNI 篇 - 从入门到放弃(https://www.jianshu.com/p/3dab1be3b9a4)
3、你用 JNI 来实现过什么功能 ?怎么实现的 ?(加密处理、影音方面、图形图像处理)
参考回答:推荐文章:Android JNI 篇 - ffmpeg 获取音视频缩略图(https://www.jianshu.com/p/411761bd5f5b)
设计模式
1、你所知道的设计模式有哪些?
-
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
-
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
-
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
2、谈谈 MVC、MVP 和 MVVM,好在哪里,不好在哪里 ?
MVC:
-
视图层 (View) 对应于 xml 布局文件和 java 代码动态 view 部分
-
控制层 (Controller) MVC 中 Android 的控制层是由 Activity 来承担的,Activity 本来主要是作为初始化页面,展示数据的操作,但是因为 XML 视图功能太弱,所以 Activity 既要负责视图的显示又要加入控制逻辑,承担的功能过多。
-
**模型层 (Model)**针对业务模型,建立数据结构和相关的类,它主要负责网络请求,数据库处理,I/O 的操作。
总结:具有一定的分层,model 彻底解耦,controller 和 view 并没有解耦层与层之间的交互尽量使用回调或者去使用消息机制去完成,尽量避免直接持有 controller 和 view 在 android 中无法做到彻底分离,但在代码逻辑层面一定要分清业务逻辑被放置在 model 层,能够更好的复用和修改增加业务。
**MVP:**通过引入接口 BaseView,让相应的视图组件如 Activity,Fragment 去实现 BaseView,实现了视图层的独立,通过中间层 Preseter 实现了 Model 和 View 的完全解耦。MVP 彻底解决了 MVC 中 View 和 Controller 傻傻分不清楚的问题,但是随着业务逻辑的增加,一个页面可能会非常复杂,UI 的改变是非常多,会有非常多的 case,这样就会造成 View 的接口会很庞大。
**MVVM:**MVP 中我们说过随着业务逻辑的增加,UI 的改变多的情况下,会有非常多的跟 UI 相关的 case,这样就会造成 View 的接口会很庞大。而 MVVM 就解决了这个问题,通过双向绑定的机制,实现数据和 UI 内容,只要想改其中一方,另一方都能够及时更新的一种设计理念,这样就省去了很多在 View 层中写很多 case 的情况,只需要改变数据就行。
三者如何选择?
-
如果项目简单,没什么复杂性,未来改动也不大的话,那就不要用设计模式或者架构方法,只需要将每个模块封装好,方便调用即可,不要为了使用设计模式或架构方法而使用。
-
对于偏向展示型的 app,绝大多数业务逻辑都在后端,app 主要功能就是展示数据,交互等,建议使用 mvvm。
最后
分享一份NDK基础开发资料
分享内容包括不限于高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
开发资料**
[外链图片转存中…(img-CSdTxq8K-1714888118000)]
分享内容包括不限于高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!