2024新鲜出炉的Android大厂面试题锦集(BAT TMD JD 小米),Github标星5K 建议收藏!


2.android view绘制机制和加载过程,请详细说下整个流程


  • 1.ViewRootImpl会调用performTraversals(),其内部会调用performMeasure()、performLayout、performDraw()。

  • 2.performMeasure()会调用最外层的ViewGroup的measure()–>onMeasure(),ViewGroup的onMeasure()是抽象方法,但其提供了measureChildren(),这之中会遍历子View然后循环调用measureChild()这之中会用getChildMeasureSpec()+父View的MeasureSpec+子View的LayoutParam一起获取本View的MeasureSpec,然后调用子View的measure()到View的onMeasure()–>setMeasureDimension(getDefaultSize(),getDefaultSize()),getDefaultSize()默认返回measureSpec的测量数值,所以继承View进行自定义的wrap_content需要重写。

  • 3.performLayout()会调用最外层的ViewGroup的layout(l,t,r,b),本View在其中使用setFrame()设置本View的四个顶点位置。在onLayout(抽象方法)中确定子View的位置,如LinearLayout会遍历子View,循环调用setChildFrame()–>子View.layout()。

  • 4.performDraw()会调用最外层ViewGroup的draw():其中会先后调用background.draw()(绘制背景)、onDraw()(绘制自己)、dispatchDraw()(绘制子View)、onDrawScrollBars()(绘制装饰)。

  • 5.MeasureSpec由2位SpecMode(UNSPECIFIED、EXACTLY(对应精确值和match_parent)、AT_MOST(对应warp_content))和30位SpecSize组成一个int,DecorView的MeasureSpec由窗口大小和其LayoutParams决定,其他View由父View的MeasureSpec和本View的LayoutParams决定。ViewGroup中有getChildMeasureSpec()来获取子View的MeasureSpec。

  • 6.三种方式获取measure()后的宽高:

  • 1.Activity#onWindowFocusChange()中调用获取

  • 2.view.post(Runnable)将获取的代码投递到消息队列的尾部。

  • 3.ViewTreeObservable.

3.图片的三级缓存中,图片加载到内存中,如果内存快爆了,会发生什么?怎么处理?


首先我们要清楚图片的三级缓存是如何的

如果内存足够时不回收。内存不够时就回收软引用对象

4.Activity的启动模式


  • 1.standard:默认标准模式,每启动一个都会创建一个实例,

  • 2.singleTop:栈顶复用,如果在栈顶就调用onNewIntent复用,从onResume()开始

  • 3.singleTask:栈内复用,本栈内只要用该类型Activity就会将其顶部的activity出栈

  • 4.singleInstance:单例模式,除了3中特性,系统会单独给该Activity创建一个栈,

5.A、B、C、D分别是四种Activity的启动模式,那么A->B->C->D->A->B->C->D分别启动,最后的activity栈是怎么样的


  • 1.这个题目需要深入了解activity的启动模式

  • 2.最后的答案是:两个栈,前台栈是只有D,后台栈从底至上是A、B、C

6.Activity缓存方法


  • 1.配置改变导致Activity被杀死,横屏变竖屏:在onStop之前会调用onSaveInstanceState()保存数据在重建Activity之后,会在onStart()之后调用onRestoreInstanceState(),并把保存下来的Bundle传给onCreate()和它会默认重建Activity当前的视图,我们可以在onCreate()中,回复自己的数据。

  • 2.内存不足杀掉Activity,优先级分别是:前台可见,可见非前台,后台。

7.Service的生命周期,两种启动方法,有什么区别


  • 1.context.startService() ->onCreate()- >onStart()->Service running–>(如果调用context.stopService() )->onDestroy() ->Service shut down

  • 1.如果Service还没有运行,则调用onCreate()然后调用onStart();

  • 2.如果Service已经运行,则只调用onStart(),所以一个Service的onStart方法可能会重复调用多次。

  • 3.调用stopService的时候直接onDestroy,

  • 4.如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行。该Service的调用者再启动起来后可以通过stopService关闭Service。

  • 2.context.bindService()->onCreate()->onBind()->Service running–>onUnbind() -> onDestroy() ->Service stop

  • 1.onBind将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service运行的状态或其他操作。

  • 2.这个时候会把调用者和Service绑定在一起,Context退出了,Service就会调用onUnbind->onDestroy相应退出。

  • 3.所以调用bindService的生命周期为:onCreate --> onBind(只一次,不可多次绑定) --> onUnbind --> onDestory。

8.怎么保证service不被杀死


  • 1.提升service优先级

  • 2.提升service进程优先级

  • 3.onDestroy方法里重启service

9.静态的Broadcast 和动态的有什么区别


  • 1.动态的比静态的安全

  • 2.静态在app启动的时候就初始化了 动态使用代码初始化

  • 3.静态需要配置 动态不需要

  • 4.生存期,静态广播的生存期可以比动态广播的长很多

  • 5.优先级动态广播的优先级比静态广播高

10.Intent可以传递哪些数据类型


  • 1.Serializable

  • 2.charsequence: 主要用来传递String,char等

  • 3.parcelable

  • 4.Bundle

11.Json有什么优劣势、解析的原理


  • 1.JSON的速度要远远快于XML

  • 2.JSON相对于XML来讲,数据的体积小

  • 3.JSON对数据的描述性比XML较差

  • 4.解析的基本原理是:词法分析

12.一个语言的编译过程


  • 1.词法分析:将一串文本按规则分割成最小的结构,关键字、标识符、运算符、界符和常量等。一般实现方法是自动机和正则表达式

  • 2.语法分析:将一系列单词组合成语法树。一般实现方法有自顶向下和自底向上

  • 3.语义分析:对结构上正确的源程序进行上下文有关性质的审查

  • 4.目标代码生成

  • 5.代码优化:优化生成的目标代码,

13.动画有哪几类,各有什么特点


  • 1.动画的基本原理:其实就是利用插值器和估值器,来计算出各个时刻View的属性,然后通过改变View的属性来,实现View的动画效果。

  • 2.View动画:只是影像变化,view的实际位置还在原来的地方。

  • 3.帧动画是在xml中定义好一系列图片之后,使用AnimationDrawable来播放的动画。

  • 4.View的属性动画:

  • 1.插值器:作用是根据时间的流逝的百分比来计算属性改变的百分比

  • 2.估值器:在1的基础上由这个东西来计算出属性到底变化了多少数值的类

14.Handler、Looper消息队列模型,各部分的作用


  • 1.MessageQueue:读取会自动删除消息,单链表维护,在插入和删除上有优势。在其next()中会无限循环,不断判断是否有消息,有就返回这条消息并移除。

  • 2.Looper:Looper创建的时候会创建一个MessageQueue,调用loop()方法的时候消息循环开始,loop()也是一个死循环,会不断调用messageQueue的next(),当有消息就处理,否则阻塞在messageQueue的next()中。当Looper的quit()被调用的时候会调用messageQueue的quit(),此时next()会返回null,然后loop()方法也跟着退出。

  • 3.Handler:在主线程构造一个Handler,然后在其他线程调用sendMessage(),此时主线程的MessageQueue中会插入一条message,然后被Looper使用。

  • 4.系统的主线程在ActivityThread的main()为入口开启主线程,其中定义了内部类Activity.H定义了一系列消息类型,包含四大组件的启动停止。

  • 5.MessageQueue和Looper是一对一关系,Handler和Looper是多对一

15.怎样退出终止App


  • 1.自己设置一个Activity的栈,然后一个个finish()

16.Android IPC:Binder原理


  • 1.在Activity和Service进行通讯的时候,用到了Binder。

  • 1.当属于同个进程我们可以继承Binder然后在Activity中对Service进行操作

  • 2.当不属于同个进程,那么要用到AIDL让系统给我们创建一个Binder,然后在Activity中对远端的Service进行操作。

  • 2.系统给我们生成的Binder:

  • 1.Stub类中有:接口方法的id,有该Binder的标识,有asInterface(IBinder)(让我们在Activity中获取实现了Binder的接口,接口的实现在Service里,同进程时候返回Stub否则返回Proxy),有onTransact()这个方法是在不同进程的时候让Proxy在Activity进行远端调用实现Activity操作Service

  • 2.Proxy类是代理,在Activity端,其中有:IBinder mRemote(这就是远端的Binder),两个接口的实现方法不过是代理最终还是要在远端的onTransact()中进行实际操作。

  • 3.哪一端的Binder是副本,该端就可以被另一端进行操作,因为Binder本体在定义的时候可以操作本端的东西。所以可以在Activity端传入本端的Binder,让Service端对其进行操作称为Listener,可以用RemoteCallbackList这个容器来装Listener,防止Listener因为经历过序列化而产生的问题。

  • 4.当Activity端向远端进行调用的时候,当前线程会挂起,当方法处理完毕才会唤醒。

  • 5.如果一个AIDL就用一个Service太奢侈,所以可以使用Binder池的方式,建立一个AIDL其中的方法是返回IBinder,然后根据方法中传入的参数返回具体的AIDL。

  • 6.IPC的方式有:Bundle(在Intent启动的时候传入,不过是一次性的),文件共享(对于SharedPreference是特例,因为其在内存中会有缓存),使用Messenger(其底层用的也是AIDL,同理要操作哪端,就在哪端定义Messenger),AIDL,ContentProvider(在本进程中继承实现一个ContentProvider,在增删改查方法中调用本进程的SQLite,在其他进程中查询),Socket

17.描述一次跨进程通讯


  • 1.client、proxy、serviceManager、BinderDriver、impl、service

  • 2.client发起一个请求service信息的Binder请求到BinderDriver中,serviceManager发现BinderDiriver中有自己的请求 然后将clinet请求的service的数据返回给client这样完成了一次Binder通讯

  • 3.clinet获取的service信息就是该service的proxy,此时调用proxy的方法,proxy将请求发送到BinderDriver中,此时service的 Binder线程池循环发现有自己的请求,然后用impl就处理这个请求最后返回,这样完成了第二次Binder通讯

4.中间client可挂起,也可以不挂起,有一个关键字oneway可以解决这个

18.android重要术语解释


  • 1.ActivityManagerServices,简称AMS,服务端对象,负责系统中所有Activity的生命周期

  • 2.ActivityThread,App的真正入口。当开启App之后,会调用main()开始运行,开启消息循环队列,这就是传说中的UI线程或者叫主线程。与ActivityManagerServices配合,一起完成Activity的管理工作

  • 3.ApplicationThread,用来实现ActivityManagerService与ActivityThread之间的交互。在ActivityManagerService需要管理相关Application中的Activity的生命周期时,通过ApplicationThread的代理对象与ActivityThread通讯。

  • 4.ApplicationThreadProxy,是ApplicationThread在服务器端的代理,负责和客户端的ApplicationThread通讯。AMS就是通过该代理与ActivityThread进行通信的。

  • 5.Instrumentation,每一个应用程序只有一个Instrumentation对象,每个Activity内都有一个对该对象的引用。Instrumentation可以理解为应用进程的管家,ActivityThread要创建或暂停某个Activity时,都需要通过Instrumentation来进行具体的操作。

  • 6.ActivityStack,Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程。

  • 7.ActivityRecord,ActivityStack的管理对象,每个Activity在AMS对应一个ActivityRecord,来记录Activity的状态以及其他的管理信息。其实就是服务器端的Activity对象的映像。

  • 8.TaskRecord,AMS抽象出来的一个“任务”的概念,是记录ActivityRecord的栈,一个“Task”包含若干个ActivityRecord。AMS用TaskRecord确保Activity启动和退出的顺序。如果你清楚Activity的4种launchMode,那么对这个概念应该不陌生。

19.理解Window和WindowManager


  • 1.Window用于显示View和接收各种事件,Window有三种类型:应用Window(每个Activity对应一个Window)、子Window(不能单独存在,附属于特定Window)、系统window(Toast和状态栏)

  • 2.Window分层级,应用Window在1-99、子Window在1000-1999、系统Window在2000-2999.WindowManager提供了增删改View三个功能。

  • 3.Window是个抽象概念:每一个Window对应着一个View和ViewRootImpl,Window通过ViewRootImpl来和View建立联系,View是Window存在的实体,只能通过WindowManager来访问Window。

  • 4.WindowManager的实现是WindowManagerImpl其再委托给WindowManagerGlobal来对Window进行操作,其中有四个List分别储存对应的View、ViewRootImpl、WindowManger.LayoutParams和正在被删除的View

  • 5.Window的实体是存在于远端的WindowMangerService中,所以增删改Window在本端是修改上面的几个List然后通过ViewRootImpl重绘View,通过WindowSession(每个应用一个)在远端修改Window。

  • 6.Activity创建Window:Activity会在attach()中创建Window并设置其回调(onAttachedToWindow()、dispatchTouchEvent()),Activity的Window是由Policy类创建PhoneWindow实现的。然后通过Activity#setContentView()调用PhoneWindow的setContentView。

20.Bitmap的处理


  • 1.当使用ImageView的时候,可能图片的像素大于ImageView,此时就可以通过BitmapFactory.Option来对图片进行压缩,inSampleSize表示缩小2^(inSampleSize-1)倍。

  • 2.BitMap的缓存:

  • 1.使用LruCache进行内存缓存。

  • 2.使用DiskLruCache进行硬盘缓存。

  • 3.实现一个ImageLoader的流程:同步异步加载、图片压缩、内存硬盘缓存、网络拉取

  • 1.同步加载只创建一个线程然后按照顺序进行图片加载

  • 2.异步加载使用线程池,让存在的加载任务都处于不同线程

  • 3.为了不开启过多的异步任务,只在列表静止的时候开启图片加载

21.如何实现一个网络框架(参考Volley)


  • 1.缓存队列,以url为key缓存内容可以参考Bitmap的处理方式,这里单独开启一个线程。

  • 2.网络请求队列,使用线程池进行请求。

  • 3.提供各种不同类型的返回值的解析如String,Json,图片等等。

22.ClassLoader的基础知识


  • 1.双亲委托:一个ClassLoader类负责加载这个类所涉及的所有类,在加载的时候会判断该类是否已经被加载过,然后会递归去他父ClassLoader中找。

  • 2.可以动态加载Jar通过URLClassLoader

  • 3.ClassLoader 隔离问题 JVM识别一个类是由:ClassLoader id+PackageName+ClassName。

  • 4.加载不同Jar包中的公共类:

  • 1.让父ClassLoader加载公共的Jar,子ClassLoader加载包含公共Jar的Jar,此时子ClassLoader在加载公共Jar的时候会先去父ClassLoader中找。(只适用Java)

  • 2.重写加载包含公共Jar的Jar的ClassLoader,在loadClass中找到已经加载过公共Jar的ClassLoader,也就是把父ClassLoader替换掉。(只适用Java)

  • 3.在生成包含公共Jar的Jar时候把公共Jar去掉。

23.插件化框架描述:dynamicLoadApk为例子


  • 1.可以通过DexClassLoader来对apk中的dex包进行加载访问

  • 2.如何加载资源是个很大的问题,因为宿主程序中并没有apk中的资源,所以调用R资源会报错,所以这里使用了Activity中的实现ContextImpl的getAssets()和getResources()再加上反射来实现。

  • 3.由于系统启动Activity有很多初始化动作要做,而我们手动反射很难完成,所以可以采用接口机制,将Activity的大部分生命周期提取成接口,然后通过代理Activity去调用插件Activity的生命周期。同时如果像增加一个新生命周期方法的时候,只需要在接口中和代理中声明一下就行。

  • 4.缺点:

  • 1.慎用this,因为在apk中使用this并不代表宿主中的activity,当然如果this只是表示自己的接口还是可以的。除此之外可以使用that代替this。

  • 2.不支持Service和静态注册的Broadcast

  • 3.不支持LaunchMode和Apk中Activity的隐式调用。

24.热修复:Andfix为例子


  • 1.大致原理:apkpatch将两个apk做一次对比,然后找出不同的部分。可以看到生成的apatch了文件,后缀改成zip再解压开,里面有一个dex文件。通过jadx查看一下源码,里面就是被修复的代码所在的类文件,这些更改过的类都加上了一个_CF的后缀,并且变动的方法都被加上了一个叫@MethodReplace的annotation,通过clazz和method指定了需要替换的方法。然后客户端sdk得到补丁文件后就会根据annotation来寻找需要替换的方法。最后由JNI层完成方法的替换。

  • 2.无法添加新类和新的字段、补丁文件很容易被反编译、加固平台可能会使热补丁功能失效

《设计思想解读开源框架》

第一章、 热修复设计

  • 第一节、 AOT/JIT & dexopt 与 dex2oat

  • 第二节、 热修复设计之 CLASS_ISPREVERIFIED 问题

  • 第三节、热修复设计之热修复原理

  • 第四节、Tinker 的集成与使用(自动补丁包生成)

    第二章、 插件化框架设计

  • 第一节、 Class 文件与 Dex 文件的结构解读

  • 第二节、 Android 资源加载机制详解

  • 第三节、 四大组件调用原理

  • 第四节、 so 文件加载机制

  • 第五节、 Android 系统服务实现原理

    第三章、 组件化框架设计

  • 第一节、阿里巴巴开源路由框——ARouter 原理分析

  • 第二节、APT 编译时期自动生成代码&动态类加载

  • 第三节、 Java SPI 机制

  • 第四节、 AOP&IOC

  • 第五节、 手写组件化架构

    第四章、图片加载框架

  • 第一节、图片加载框架选型

  • 第二节、Glide 原理分析

  • 第三节、手写图片加载框架实战

    第五章、网络访问框架设计

  • 第一节、网络通信必备基础

  • 第二节、OkHttp 源码解读

  • 第三节、Retrofit 源码解析

    第六章、 RXJava 响应式编程框架设计

  • 第一节、链式调用

  • 第二节、 扩展的观察者模式

  • 第三节、事件变换设计

  • 第四节、Scheduler 线程控制

    第七章、 IOC 架构设计

  • 第一节、 依赖注入与控制反转

  • 第二节、ButterKnife 原理上篇、中篇、下篇

  • 第三节、Dagger 架构设计核心解密

    第八章、 Android 架构组件 Jetpack

  • 第一节、 LiveData 原理

  • 第二节、 Navigation 如何解决 tabLayout 问题

  • 第三节、 ViewModel 如何感知 View 生命周期及内核原理

  • 第四节、 Room 架构方式方法

  • 第五节、 dataBinding 为什么能够支持 MVVM

  • 第六节、 WorkManager 内核揭秘

  • 第七节、 Lifecycles 生命周期


    本文包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

ewModel 如何感知 View 生命周期及内核原理**

  • 第四节、 Room 架构方式方法

  • 第五节、 dataBinding 为什么能够支持 MVVM

  • 第六节、 WorkManager 内核揭秘

  • 第七节、 Lifecycles 生命周期

    [外链图片转存中…(img-XLOWZKDv-1714243535713)]
    本文包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…
    [外链图片转存中…(img-1c2a2JcB-1714243535714)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值