4.牛批了 Android 2021中高级面试题 一线大厂和二线大厂面试真题精选 (Shopee 附答案)第四套 27k+

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

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

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

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

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

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

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

第四套Shopee    价值27k+,   难易程度:中等      看完你能进这些公司: Shopee,京东, 深信服,TCL,平安,荣耀,  美的,一加,随手记,中兴,虎牙 强调:一定要搞的非常清晰,细节一个都不能放过,要非常深入,仅仅10题而已 1.LifeCycle的原理是怎样的? 2.协程介绍一下,讲一个协程的scope与context,协程的+号代表什么 3.PathClassLoader与DexClassLoader有什么区别 4.怎么获取view的宽高,如何确定值是准确的,说了view.post()补充viewTreeObserverOnGlobalLayoutListener 5.  平常有用到什么锁,synchronized底层原理是什么,synchronized是公平锁还是非公平锁,ReteranLock是公平锁吗?是怎么实现的 6.线程池了解多少?拒绝策略有几种,为什么有newSingleThread 7.RecyclerView 缓存结构,RecyclerView预取,RecyclerView局部刷新 8.跨进程通信了解多少?管道了解吗? 9.你们项目的稳定性如何?有做过什么稳定性优化的工作? 10.二叉树的每一层最左边节点 1. LifeCycle的原理是怎样的? 答:Lifecycle: 封装的生命周期对象,保存了当前Activity,Fragment当前生命周期状态。同时也是一个事件源,可以被其他已注册的观察者监听。 LifecycleOwner: 生命周期提供者,或者说生命周期本身,提供Lifecycle对象。它的实现为Fragment和Activity。 LifecycleObserver: 生命周期观察者,可以将它注册到Lifecycle监听生命周期时间。 总的来说:Lifecycle组件通过在Activity/Fragmen中注入空的Fragment(ReportFragment),实现了对生命周期的感知。使用反射把使用了@OnLifecycleEvent注解的方法信息保存下来,基于观察者模式, 当页面生命周期变化的时候,通知相应的 Observers 即观察者。 2.协程介绍一下,讲一个协程的scope与context,协程的+号代表什么 答:协程:是线程的封装,切换线程API scope: CoroutineScope是启动协程的作用域,所有协程都需要在作用域中启动,并且作用域内部创建子协程则会自动传播给子协程;CoroutineScope内部含有CoroutineContext context: CoroutineContext则是在协程作用域中执行的线程切换。   协程上下文,是一些元素的集合,主要包括 Job 和 CoroutineDispatcher 元素,可以代表一个协程的场景。 这些数据与协程密切相关。它类似于map集合,可以通过key来获取不同类型的数据。同时CoroutineContext的灵活性很强,如果其需要改变只需使用当前的CoroutineContext来创建一个新的CoroutineContext即可。 每一个 CoroutineContext 都有它唯一的一个 Key 其中的类型是 Element ,我们可以通过对应的 Key 来获取对应的具体对象 3.PathClassLoader与DexClassLoader有什么区别 答: PathClassLoader 和 DexClassLoader 类加载器都是继承自 BaseDexClassLoade  DexClassLoader 和 PathClassLoader 构造函数 DexClassLoader 和 PathClassLoader 的差异在于构造 ClassLoader 对象时,是否给父类 ( BaseDexClassLoader ) 传递 optimizedDirectory 参数  (即是否指定优化后的 .odex 文件的存储路径)。 4.怎么优化xml inflate的时间,涉及IO与反射。了解compose吗? 答: 异步Inflate实战

源码,请:

void rInflate(XmlPullParser parser, View parent, Context context,
        AttributeSet attrs, boolean finishInflate) throws XmlPullParserException, IOException {
    // 获取深度     final int depth = parser.getDepth();
    int type;
            parseViewTag(parser, parent, attrs);
        } else if (TAG_INCLUDE.equals(name)) {
            // 解析include             if (parser.getDepth() == 0) {
                throw new InflateException("<include /> cannot be the root element");
            }
            parseInclude(parser, context, parent, attrs);
        } else if (TAG_MERGE.equals(name)) {
            // 子View不能有merge标签,merge只能用在根布局             throw new InflateException("<merge /> must be the root element");
        } else {
            //通过createViewFromTag构建这个view             final View view = createViewFromTag(parent, name, context, attrs);
            // 利用parent作为ViewGroup,构建出LayoutParams,并赋值予子View             final ViewGroup viewGroup = (ViewGroup) parent;
            final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
            rInflateChildren(parser, view, attrs, true);
            // addView到ViewGroup             viewGroup.addView(view, params);
        }
    }
    // finishInflate是方法传参进来的     if (finishInflate) {
        parent.onFinishInflate();
    }
}
来源: https://zhuanlan.zhihu.com/p/51279654 LayoutInflater.inflate()方法是个耗时操作, 应尽量避免调用.

很明显,整个过程中最耗时(ANR)的地方有两处:

    解析XML 反射获取实例

而Google做的优化是:

    预编译 缓存
https://www.bilibili.com/video/av884853350/ 5.  平常有用到什么锁,synchronized底层原理是什么,synchronized是公平锁还是非公平锁,ReteranLock是公平锁吗?是怎么实现的 答:synchronized和ReenLock synchronized底层原理:底层,通过jvm实现,字节码指令,monitor指令。在synchronized修饰的代码块前面和后面添加了2个monitor指令 synchronized:非公平锁 ReteranLock:非公平锁,也可以实现公平锁 ReteranLock原理:AQS,通过CAS+volterel实现 6.线程池了解多少?拒绝策略有几种,为什么有newSingleThread 答:5种线程。线程池的原理

  线程池提供了四种拒绝策略:

    AbortPolicy:直接抛出异常,默认策略; CallerRunsPolicy:用调用者所在的线程来执行任务; DiscardOldestPolicy:丢弃阻塞队列中靠最前的任务,并执行当前任务; DiscardPolicy:直接丢弃任务;
newSingleThread:可以比较好的复用和管理 7.RecyclerView 缓存结构,RecyclerView预取,RecyclerView局部刷新 Scrap:对应ListView 的Active View,就是屏幕内的缓存数据,就是相当于换了个名字,可以直接拿来复用 Cache : 刚刚移出屏幕的缓存数据 ViewCacheExtension:是google留给开发者自己来自定义缓存的 RecycledViewPool:回收池,最重要 答:四级缓存,有一个自定义的不用 局部刷新:notifyPositon或者nofiyview实现,可以执行动画 8.跨进程通信了解多少?管道了解吗? 答:四大组件可以跨进程 主要是binder机制。Android都是,平时用AIDL 管道:2次拷贝???????缓冲区有大小限制。管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。在创建时分配一个page大小的内存,缓存区大小比较有限。 9.你们项目的稳定性如何?有做过什么稳定性优化的工作? 答: 我们主要优化了三项: Crash专项优化 性能稳定性优化 业务稳定性优化 性能:全面的性能优化:启动速度、内存优化、绘制优化 线下发现问题、优化为主 线上监控为主 Crash专项优化

我们针对启动速度,内存、布局加载、卡顿、瘦身、流量、电量等多个方面做了多维的优化。

我们的优化主要分为了两个层次,即线上和线下,针对于线下呢,我们侧重于发现问题,直接解决,将问题尽可能在上线之前解决为目的。而真正到了线上呢,我们最主要的目的就是为了监控,对于各个性能纬度的监控呢,可以让我们尽可能早地获取到异常情况的报警。

同时呢,对于线上最严重的性能问题性问题:Crash,我们做了专项的优化,不仅优化了Crash的具体指标,而且也尽可能地获取了Crash发生时的详细信息,结合后端的聚合、报警等功能,便于我们快速地定位问题。

10.二叉树的每一层最左边节点

这题有2个做法,一是宽度优先搜索,用每层的第一个节点来更新答案。二是深度优先搜索,当遇到一个节点的深度大于目前维护的最大深度时用这个节点来更新答案。

    使用宽度优先搜索bfs,用每层的第一个节点更新Ans。时间复杂度O(n)。 使用深度优先搜索dfs,当我们第一次访问一个深度为depth的节点x(之前只访问过深度小于depth的节点)时,x一定是depth深度的最左节点,用这个节点更新Ans。即我们维护一个最大深度,当遍历到一个点的深度大于最大深度时,用这个节点来更新答案,并更新最大深度即可。时间复杂度O(n)。
public static void levelReadLeft(BinaryNode node) { static void levelReadLeft(BinaryNode node) {
    if (node == null) {if (node == null) {
        return;    return;
    }}
    int depth = calcDepth(node);int depth = calcDepth(node);
    
    for (int i = 1; i <= depth; i++) {for (int i = 1; i <= depth; i++) {
        String string = readLevelLeft(node,i);    String string = readLevelLeft(node,i);
        System.out.println(string);    System.out.println(string);
    }}
}
 
         
         
         
private static String readLevelLeft(BinaryNode node, int i) { static String readLevelLeft(BinaryNode node, int i) {
    String reString = "";String reString = "";
    if (node == null||i<1) {if (node == null||i<1) {
        return reString;    return reString;
    }}
    if (i == 1) {if (i == 1) {
        return reString + (node.element+"  ");    return reString + (node.element+"  ");
    }}
    
    reString += readLevelLeft(node.left, i-1);reString += readLevelLeft(node.left, i-1);
    if (reString.equals ("")) {if (reString.equals ("")) {
        reString += readLevelLeft(node.right, i-1);    reString += readLevelLeft(node.right, i-1);
    }}
    return reString;return reString;
private static int calcDepth(BinaryNode node) { static int calcDepth(BinaryNode node) {
    if (node ==null) {if (node ==null) {
        return 0;    return 0;
    }}
    int ld = calcDepth(node.left);int ld = calcDepth(node.left);
    int rd = calcDepth(node.right);int rd = calcDepth(node.right);
    if (ld>rd) {if (ld>rd) {
        return ld+1;    return ld+1;
    }else{}else{
        return rd+1;    return rd+1;
    }}

关于作者:

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

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

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

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

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

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

2019年      VIVO               深圳手机厂上梅林

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

2021年      蚂蚁金服        深圳分公司

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

来源url
栏目