3.牛批了 Android 2021中高级面试题 一线大厂和二线大厂面试真题精选 (顺丰 附答案)第三套 25k+

23 篇文章 1 订阅
16 篇文章 0 订阅

笔者是面霸,面试500+场       当过考官:面过别人500+场     去过500强,也呆过初创公司。

斩获腾讯、美团,字节跳动,蚂蚁金服,华为、OPPO,offer!我有一套速通大厂技巧分享给你!

12年毕业,专科生,做安卓9年。横扫各大互联网公司,从4k工资现在的4万。我经历了什么?

本系列一共10套面试真题,适合快速找工作的人准备,薪资和公司分别如下。

搞定前3套,可以去二线大厂,秒杀70%公司

搞定前6套,可以去二线和一线大厂,秒杀80%公司 ,面试官在你面前都是弟弟

搞定前10套,一线大厂,秒杀100%公司,中国互联网任你挑 ,横扫北上广深,吊打面试官

 

 第三套顺丰         价值25k+,   难易程度:中等      看完你能进这些公司:

顺丰,网易 ,海康威视,斗鱼,小红书,去哪儿,喜马拉雅,创维,涂鸦智能,51信用卡

强调:一定要搞的非常清晰,细节一个都不能放过,要非常深入,仅仅10题而已

1.MVVM和MVP的一些区别,讲讲你理解的MVVM

2. Kotlin和Java的运算符可以重载么?协程和线程的区别

3.ViewPager和ViewPager2的区别,如何实现懒加载?

4.在onCreate方法中能获取到view的宽高吗?怎么才能获取view的宽高

5.onMeasure、onLayout、onDraw方法的先后顺序,有没有哪些方法可以触发执行,invalidate、layout、postinvalidate方法,还有没有其他方法经常需要重写

6. 关于Handler有一个需求,一个消息要立刻执行,要怎么做?Handler同步屏障异步消息的概念的理解

7.APP启动流程中,为什么是用socket和Zygote通信的

8.进程间怎么通信?Binder机制了解

9.性能调优方面的理解

10. 平时工作有处理过OOM的问题么?系统抛出OOM的原因有哪些

 

一个一个问题来总结一下:答案由蚂蚁金服首席架构师提供,官方答案会由3个人审核,审核之后才会公布,现在是中间版本答案

1、MVVM和MVP的一些区别,讲讲你理解的MVVM

这里其实主要说一下自己的见解,也没什么标准答案吧
答:MVVM主要是基于数据的双向绑定及观察者模式来实现的,MVP主要是通过共同实现一个View接口来实现的,MVP模式下处理不妥当的话,有可能造成内存的泄漏,因为都持有了View的一个引用。MVVM比MVP来讲更加的解耦,同时写法上也感觉更加的简便。感觉要是简单的项目,就用MVC来做来,复杂点的还是MVVM的优势较大,这个是我个人的一个感受。对于这个问题来讲,其实没有好坏之分,只有合适与不合适的说法,就是存在即有意义。

2、Kotlin的运算符可以重载么?协程和线程的区别?

答:可以的,Java中不支持运算符重载,但是Kotlin中支持运算符重载,运算符重载是对已有的运算符赋予新的含义,使一个运算符作用于不同类型的数据会有对应这个类型的行为。使用operator关键字来修饰的,主要也是对比如plus、times等等一些函数的重载。

  • 协程其实就是一个线程框架吧,网络上有说线程是阻塞式的,协程是非阻塞式的,我感觉其实不大对,所有代码都是阻塞式的,单线程下阻塞式,多线程下切换了一个线程,原线程就非阻塞式了,协程其实只是内部悄悄的帮你做了一个切线程的一个操作而已,所以可以说协程是一个阻塞式写法的非阻塞式。我记得官方文档有举了一个例子说开十万个协程和开十万个线程的对比来说明协程是一种轻量级的线程,我感觉这个说法是官方的一个误导性的说法,代码里好像是直接new了十万个Thread,来对比的,实际上协程的对比应该是和Executor线程池来对比,比如使用Executors.newSingleThreadScheduledExecutor的话,其实效率就没有很大的差别了。
  • 协程方便的地方就是在同一个代码块中进行线程切换,Kotlin的协程可以用同步的方式写出异步的代码,可以消除Java带来的回调式的一些写法,比如有两个请求,需要并发执行,然后将两个结果进行合并后更新到页面上,用Java来实现可能就不好操作了,因为你不知道哪一个接口先请求完成,所以就可能会选择串行的方式去做了,这样性能上可能就多损耗了一倍了,而Kotlin可以使用挂起函数来做,分别执行两个请求,然后进行合并,没有了回调也提高了一些性能。协程会使用Dispatchers调度器在挂起函数执行完成后自动切回到原先执行的线程,也就是挂起和恢复。实际上挂起的操作并不是suspend关键字的作用,真正的挂起操作是Dispatchers来做的。suspend关键字的作用只是一个提醒的作用,告诉调用者说这个函数是一个耗时方法,要在协程里调用。

https://blog.csdn.net/IO_Field/article/details/52817471

3.ViewPager和ViewPager2的区别,如何实现懒加载?

答:ViewPager默认会帮我们预加载前后两个页面的数据,并且这2个view是不可见的。

由于ViewPager对offscreenPageLimit做了限制,默认设置为1,因此页面的预加载不可避免。这也容易造成资源浪费。一般使用ViewPager与frament配合使用,利用fragment的setUserVisibleHint方法,来实现控制数据懒加载,而布局只能提前进入(预布局)。

  • ViewPager2的预加载与离屏加载在view层面有着本质的区别,离屏加载的view已经添加到parent上,而预加载只是准备了布局,并没有加载到parent上。ViewPager2默认是开启预加载关闭离屏加载的,可能会预加载一条数据,而离屏加载即设置offscreenPageLimit为0。ViewPager2设置offscreenPageLimit为1时,在第1页会加载2条数据,每滑动一页,都会加载下一页数据,直到第五页,会移除第一页数据。
    1.目前ViewPager2对Fragment支持只能用FragmentStateAdapter,FragmentStateAdapter在遇到预加载时,只会创建Fragment对象,不会把Fragment真正的加入到布局中,所以自带懒加载效果;
    2.FragmentStateAdapter不会一直保留Fragment实例,回收的ItemView也会移除Fragment,所以得做好Fragment重建后恢复数据的准备;
    3.FragmentStateAdapter在遇到offscreenPageLimit>0时,处理离屏Fragment和可见Fragment没有什么区别,所以无法通过setUserVisibleHint判断显示与否。

4、在onCreate方法中能获取到view的宽高吗?怎么才能获取view的宽高

答:不能在onCreate中获取View的宽高,获取到的值都为0。实际上,要真正获取到View的宽高,必须是等View的测量布局绘制完成之后才可以获取到真实的View的宽高。有三种方法可以去获取View的宽高

  • 1、通过view.post(new Runnable(){});方法去获取view的宽高。 view
  • 2、为ViewTreeObserver注册OnGlobalLayoutListener接口,OnGlobalLayoutListener的作用是当View树的状态发生改变或者View树中某view的可见性发生改变时,OnGlobalLayoutListener的onGlobalLayout方法将会被回调。
  • 3、在Activity的onWindowFocusChanged方法中获取,但是注意这个方法意为焦点发生变化时,即Activity的焦点发生变化就会回调这个方法,有可能调用多次。
     

5、onMeasure、onLayout、onDraw方法的先后顺序,有没有哪些方法可以触发执行,invalidate、layout、postinvalidate方法,还有没有其他方法经常需要重写?

答:他们的先后顺序是onMeasure、onLayout、onDraw,也就是先测量,才知道应该布局在哪里,之后才会进行绘制的操作。postinvalidate和invalidate的主要区别就是postinvalidate方法实现了Handler消息机制,可以让开发者在非UI线程也能调用刷新View的方法,最终还是调用到了invalidate方法。invalidate方法最终会回调到onDraw方法,而要回调onMeasure方法和onLayout方法的话可以使用requestLayout。也就是说,如果View只是需要重新绘制而没有改变位置的话,可以使用invalidate(非UI线程可以使用postinvalidate方法),如果View的位置发生了变化的话,可以使用RequestLayout方法。自定义View/ViewGroup的过程中,还有onSizeChanged()、onFinishInflate()这两个方法也是经常重写的方法吧,onFinishInflate方法只有在布局文件中加载View实例的时候会回调这个方法,如果使用new的方式不会回调这个方法,这个方法会在onMeasure方法之前调用。onSizeChanged方法一般是在视图大小发生改变的时候回调,之后回调onlayout方法进行重新布局。

6.关于Handler有一个需求,消息队列里还有很多没有执行的消息,有一个消息要立刻执行,要怎么做?

答:这个问题当时真不知道怎么处理,其实是第13个问题的答案,Handler发送消息其实是同步执行的,发送的消息都在消息队列中进行排队的。要做到立刻执行,可以通过异步消息的方式,这里就需要了解同步屏障和异步消息机制了。直接到第13问吧

答:同步屏障,让异步消息不用排队等候处理。可以理解为同步屏障是一堵墙,把同步消息队列拦住,先处理异步消息,等异步消息处理完了,这堵墙就会取消,然后继续处理同步消息。

  • 屏障消息和普通消息的区别在于屏障没有tartget,普通消息有target是因为它需要将消息分发给对应的target,而屏障不需要被分发,它就是用来挡住普通消息来保证异步消息优先处理的。
  • 屏障消息和普通消息一样可以根据时间来插入到消息队列中的适当位置,并且只会挡住它后面的同步消息的分发。
  • postSyncBarrier返回一个int类型的数值,通过这个数值可以撤销屏障。
  • postSyncBarrier方法是私有的,如果我们想调用它就得使用反射。
  • 插入普通消息会唤醒消息队列,但是插入屏障不会。
    在ViewRootImpl.scheduleTraversals()UI刷新的源码中中见过同步屏障异步消息的用法。

   public void postSyncBarrier() {
       Method method = MessageQueue.class.getDeclaredMethod("postSyncBarrier");
       token = (int) method.invoke(Looper.getMainLooper().getQueue());
   }

   public void removeSyncBarrier() {
       Method method = MessageQueue.class.getDeclaredMethod("removeSyncBarrier", int.class);
       method.invoke(Looper.getMainLooper().getQueue(), token);
   }

发送异步消息比较简单,调用Message的setAsynchronous(boolean flag)方法即可,甚至可以直接创建一个异步Handler。

7、APP启动流程中,为什么是用socket和Zygote通信的?

答:这个我是真的不了解,感兴趣去网上看看吧,都已经吵疯了,但我的感觉就是没有一个解释清楚的,要是有人能解释清楚的,还请在后面的评论中指出,学习一下,在这里先谢谢了~网上找的一篇文章,作为参考

8.进程间怎么通信?

答:由于进程间内存数据不能共享,Android中的进程间通信(IPC)主要有几种方式:共享文件、广播、内容提供者、Messenger、AIDL、socket等方式。Messenger是基于AIDL,AIDL是基于Binder机制实现的。Binder基于内存映射原理(mmap)实现,实现用户空间到内核空间的一次数据拷贝和内存映射。
AIDL的方式实现进程间通信步骤:1、创建一个aidl文件 2、build后生成接口 3、创建service实现接口及aidl中的方法(其实就是binder对象) 4、在onBind中返回binder对象 5、在使用时,使用bindService中传入ServiceConnection接口对象。在onServiceConnected方法中即可拿到service中的binder对象,调用aidl的方法。详细了解可以看看Android中进程间通信2.ViewPager和ViewPager2的区别,如何实现懒加载?

9、你做过哪些性能调优方面的优化,或者你没做过,了解过的也可以讲讲。

答:内存优化方面主要是有几个方面的吧,APP端给用户最为直观的感受就是APP启动快慢、使用时页面流畅度、下载的时候安装包的体积、使用过程中的稳定性(奔溃/ANR)、然后现在用户比较关心的就是耗电量(这个就和个人的一些代码习惯上有一些关系了,包括对内存、算法等等)
我在项目中做过的有:

  • APP启动优化:在application中的onCreate()会经常做一些SDK的初始化操作,就会对一些非必要及时初始化的SDK做一些异步初始化的操作(阿里有一个alpha框架),尽量不做或者异步去做一些计算来加快启动速度,同时启动页布局尽量简单。同时,我们可以将APP的主题背景设置为透明,这样虽然会有一点卡顿的现象,但是至少不会白屏。
  • 页面流程度上的优化:主要就是减少层级的嵌套,手机开发者模式中有一个可以看过渡绘制的,可以用来分析哪些地方过渡绘制。使用include、merge来重用布局,减少一个层级的嵌套,利用ViewStub来防止提前加载某些不需要及时展示的View等。Android也推出了一个新的布局叫约束布局(ConstraintLayout),用来减少布局的层级嵌套。还有就是因为Android页面刷新机制是16ms刷新一次,所以不要在UI线程去做一些计算,超过16ms的就会造成一些卡顿现象。
  • APK的瘦身优化:用户在下载的时候就会关注这个APK的大小,在用户体验上就需要对APK大小来进行一些优化了。这个主要就是针对一些图片压缩、SVG、webp等占用资源较小的图片。尽量删除一些无用资源以及一些不需要的so包,还有就是混淆也可以减少一部分的APK大小。
  • 稳定性的优化主要在监控及平时的代码习惯吧,可以用Thread.UncaughtExceptionHandler来捕获全局异常,然后上传异常信息到自己的服务器,也可以使用第三方平台来统计这些错误信息,当然第三方平台可能增加APK文件的大小。然后稳定性主要还有一方面在于ANR的处理吧,也有一些收集ANR的手段,我主要做的就是在平时开发过程中尽量避免,如果出现也可以通过去查看data/anr目录下的trace.txt文件,从文件中也可以分析出哪些地方出现的ANR异常。
  • 电量网络优化最主要就是减少对计算以及网络请求时做一些不必要请求的缓存之类的,当然很多方面的优化都可以减少电量的使用,渲染、内存啊等等,那些优化了,其实也是对电量优化方面做了一些贡献。特别耗电的APP,用户也不大喜欢用,毕竟现在的人最怕的就是手机没电了。
  • 还有用户可能不那么直观感受到的就是内存方面的优化,这个主要就是在内存泄漏方面以及图片的使用上做一些优化吧,内存泄漏可以利用一些工具来分析,AndroidStudio上就有一个工具叫profiler,可以看电量、网络、内存等等一些信息。然后图片的使用是Android中内存占用最大的一块吧,非必要的一些图片文件尽量放到xxxhdp目录下,因为同一张图片不同文件夹目录下加载到内存中占用内存大小是不一样的,越大占用内存越小。
    优化上的东西我了解的大概就是这些了吧,之前也分析过一些,可以看上篇文章,这里就再说说。

10、平时工作有处理过OOM的问题么?系统抛出OOM的原因有哪些?

答:OOM就是内存溢出,现在加载图片也都用Glide等图片加载库了,就比较少出现加载图片的OOM。OOM出现的原因归结到底其实就是因为程序进程需要申请一块内存,但是系统无法提供需要的内存大小,就会抛出OOM异常。内存泄漏是OOM的一个很大原因,还有就是图片,资源对象未关闭、注册的服务未及时反注册、图片太大等等造成OOM异常

关于作者:

2013年       快播公司       当时播放器老大,你懂的

2014年      华强集团       深圳北最大的电子公司

2015年      TCL公司        深圳传统电子公司

2016年       顺丰科技        深圳快递老大

2017年      招商银行        深圳本地银行老大

2018年      字节跳动        深圳后海,抖音头条

2019年      VIVO               深圳手机厂上梅林

2020年      腾讯音乐        深圳滨海大厦

2021年      蚂蚁金服        深圳分公司

从月薪2000到年薪100万。从专科生到深圳一线大厂。关注我就能达到大师级水平,这话我终于敢说了, 年薪100万不是梦!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值