安卓题目

知识点

网络基础

1. TCP三次握手

2. TCP,UDP区别

3. Http与Https

4. 多线程断点续传如何实现

通过请求头 Range bytes=100-500告诉服务器要哪段数据

服务器状态码206(HTTP_PARTRIAL)表示支持断点下载

通过RandomAccessFile seek到开始写入的位置,写入文件。

Java基础

1.并发编程

  • synchronized关键字(类锁,对象锁的区别;synchronized底层实现)

    深入理解Java并发之synchronized实现原理

    synchronized代码块:monitorenter,monitorexit指令

    synchronized方法:ACC_SYNCHRONIZED标志

  • 内存模型和volatile

    全面理解Java内存模型(JMM)及volatile关键字

    深入理解 Java 内存模型(四)——volatile

    工作内存,主内存。内存屏障-storestore,storeload,loadload,loadstore,防止指令重排序。通知工作内存数据失效,从主内存取,保证了可见性。

  • 并发相关的数据结构和系统类(Atomic*,BlockingQueue)

    Java并发编程-无锁CAS与Unsafe类及其并发包Atomic

    深入剖析基于并发AQS的(独占锁)重入锁(ReetrantLock)及其Condition实现原理

    深入剖析java并发之阻塞队列LinkedBlockingQueue与ArrayBlockingQueue

  • 线程,线程池

    ThreadLocal原理?

    ThreadLocal对象本身会被当作key,每一个Thread对象内部都有一个TheadLocalMap

    ThreadLocalMap内部通过Entry数组存数据。当我们通过threadLocal set一个value时候,其实set方法内部做的是找到当前线程t,取出t的ThreadLocalMap,调用threaLocalMap.set(threadLocal,value),threadLoca自身带有一个hashCode,与线程threadlocalMap内部数组长度-1按位与(&)产生数组下标,把value存到该下标位置。所以每个线程都是通过自己内部的ThreadLocalMap存数据的,数据当然会互不干扰。

    sleep,wait区别?哪个会释放锁?

    线程池有哪几种?如何创建?

    FixedThreadPool,SingleThreaPool,CachedThreadPool,ScheduledThreadPool

    线程池如何复用线程的?

    其实是一个生产消费者模型,Worker内部有一个Thread,start之后就一直while循环从任务队列中取任务;

    如果没有达到核心线程数,直接new一个Worker,执行任务。

    AsyncTask源码,可以在子线程实例化AsyncTask吗?可以在子线程调用execute吗?

    答:都可以。在子线程调用execute要注意,onPreExecute方法中,不能操作ui,因为execute会间接回调该方法。

    HandlerThread,IntentService原理?使用场景?

    HandlerThread继承自Thread,其run方法中,调用Looper.prepare,Looper.loop开启了消息循环。

    IntentService的onCreate方法中new除了一个HandlerThread,使用该HandlerThread内部的looper初始化了ServiceHandler,每次调用startService的时候,IntentService的onStartCommand就会被调用,onStartCommand调用onStart,onStart中把intent数据封装成message,通过ServiceHandler发送到消息循环中,ServiceHandler的handleMessage接收到数据就会回调onHandleIntent(),我们使用IntentService就是重载onHandleIntent,onHandleIntent执行完就会调用stopSelf结束自己。由此可见,IntentService适合在后台顺序执行一系列任务(比如静默的上传一些日志文件),顺序执行是因为这些任务都会被投递到messagequeue进行消息循环。

2.GC相关

内存划分:

标记垃圾对象:引用计数,GCRoot可达性分析(哪些变量或常量可作为GCRoot?)

GCRoot:
Java虚拟机栈引用的变量
方法区中静态属性引用的对象
方法区中常量引用的对象
Native方法中引用的对象

回收垃圾对象:
标记清除,
标记整理,
复制算法,
分代回收(对jvm内存区域分代,对不同的代使用不同的回收算法)

3.类加载机制

Java 中的类加载器:

  • BootstrapClassloaderjre/lib
  • ExtensionClassloaderjre/lib/ext
  • AppClassloaderclasspath

Android中的类加载器:

  • ClassLoader

  • BootClassLoader,BaseDexClassLoader,SecureClassLoader

  • PathClassLoader,DexClassLoader,InMemoryClassLoader

  • 双亲委派模型
    basedexclassloader.findclass->dexpathlist.findclass->循环dexpathlist内部的element数组,调用element .findclass->dexfile.loadClassBinaryName

  • 热修复应用

  • 插件化应用

    4.常用的数据结构

  • ArrayList,HashMap,ConcurrentHashMap,HashTable

  • LrucacheLinkedHashMap

  • SparseArrayHashMap对比

  • ArrayMap

    5.常用技术

  • 反射

  • 动态代理

  • 注解

    Android知识点

    1.Activity相关问题

  • Activity生命周期
    onSaveInstanceState,onRestoreInstanceState是否用过?(保存Activity状态)
    启动一个透明主题的Activity,当前Activity生命周期的变化?弹出一个dialog呢?

  • Activity启动模式
    用过哪些启动模式?(比如MainActivity使用singleTask)

  • IntentFilter匹配规则
    对于一个Activity有多个intent-filter,一个匹配成功就行。一个intent-filterdatacategoryaction多个条件,所有条件都匹配才算成功。
    action匹配规则:intent中要存在action且只要一个action值匹配上就行(字母区分大小写)
    category匹配规则:intent中可以没有category,但只要有,必须和intent-filter中指定的某个category相匹配。
    data匹配规则:intent中必须有data

    为什么模块化/组件化的架构中schema跳转?

  • Activity启动过程
    startActivityForResult->instrumetion.execStartActivity->ActivityManagerNative->AMS->ActivitySuperVisor->ActivityStack->ApplicationThread->ActivityThread->H->handleLaunchActivity

2.Android的IPC机制

  • Android有哪些跨进程通信的方法,用过哪种
    AIDL,ContentProvider,Socket,BroadcastReceiver
  • Binder机制
    Binder学习指南
    Android Binder设计与实现 - 设计篇

    3.View事件分发相关问题

  • 简述View的事件传递机制
  • 如何解决滑动冲突
    具体来说,viewpager如何解决滑动冲突?

    4.View绘制流程

  • onMeasure
    measurespec
    getWidth,getMeasuredWidth 有什么区别?
    getMeasuredWidthonMeasure之后就能取得值
    getWidth要在onLayout之后才有值,因为mWidth=mRight-mLfet,而mRightmLeft要在onLayout时才确定。
    一般情况下getMeasuredWidthgetWidth取得的值一样,除非在onLayout中强行改变了mRightmLeft
  • onLayout
  • onDraw
  • invalidate,postinvalidate,requestlayout区别
    invalidatepostinvalidate都只会引起view重新绘制,前者在主线程中调用,后者可在子线程调用
    requestlayout会引起view树重新measurelayoutdraw
  • 分辨率适配,原理?
  • recyclerviewlistview对比?缓存实现有什么不同
  • LinearLayout,RelativeLayout
    当使用weight时,linearlayoutmeasure两次,第二次是给使用了weightview分配剩余空间。
    relativelayout本身就需要measure两次,因为其子view布局在横向和纵向上都会相互依赖。
    但是relativelayout可以有效减少布局层级。

    5.动画

    animationanimator什么区别?原理?

属性动画画一个抛物线?

6.消息机制

bitmap格式?各占多少字节?

Android性能优化:Bitmap详解&你的Bitmap占多大内存

大图加载如何不oom?

regionDecoder

Android各个版本新特性

  • art,dvm的区别

dvm:

运行期解释dex文件

堆内存划分为Zygote Space,Allocation Space

2.2之后引入JIT对热点代码预编译

Art:

安装时通过AOT把字节码编译成了本地机器码,运行速度更快。安装速度变慢,同时需要更多的空间存储机器码。

7.0之后引入JIT作为AOT的补充,节省了安装时间也节省了空间

Art减少了GC停顿的次数

Art堆内存划分:Zygote Space,Allocation Space,Image Space,Large Object Space。

  • 5.0Material Design,自定义behavior?
  • 6.0运行时权限,权限适配?
  • 9.0hide api限制

开源框架源码

  • ButterKnife
  • EventBus
  • OkHttp

RealCall,Dispatcher,InterceptorChain,StreamAllocation

RetryAndFllowUpInterceptor 失败重试

CacheInterceptor 缓存策略

BridgeInterceptor 添加请求头信息

ConnectionInterceptor 构造httpcodec和获取realconnection

CallServerInterceptor 使用httpcodec和realconnection发送请求

  • Retrofit

create->loadServiceMethod->ServiceMethod.Builder

ServiceMethod的build方法调用createCallAdapter创建了CallAdapter

CallAdapter在这里默认返回的是ExecutorCallAdapterFactory.get所返回的。

ExecutorCallbackCall

Paltform为Android平台提供了切换回主线程的Executor

img

  • Glide

一次图片加载流程:

img

缓存机制:

Glide有三级缓存,Lrucache,WeakRefrence(会通过IdleHandler清理),DiskLrucache。

Android常用架构,设计模式

  • MVC,MVP,MVVM
  • 源码中的设计模式

Dialog的builder模式

WindowManagerImpl和WindowManagerGlobal之间的桥接模式

Retrofit动态代理(动态代理的底层原理?),对方法参数的处理是策略模式。

OkHttp中的责任链模式

性能优化

1.启动速度优化

  • 启动速度测量
  • 耗时方法分析
  • 体验优化,异步化,task化

2.内存优化

3.卡顿优化

  • CPU Profiler(Trace View),Systrace,StrictMode

以上方案无法带到线上

  • 自动化卡顿检测AndroidPerformanceMonitor
  • ANR

原因:

Keydispatchtimeout 5s

Broadcasttimeout 前台10s 后台60s

Service 前台20s 后台200s

4.网络优化

指标:流量,接口访问速度,请求成功率

手段:HttpDNS,gzip,图片压缩,请求合并

5.电量优化

6.包体积优化

项目细节

1.可能被问到的模块,功能点

  • 轮播图原理?会引起内存问题吗?
  • 扫码使用的zxing原理?如何优化提高速度识别率?
  • 模块化?ARouter原理?

2.亮点难点

  1. AOP实现统一登陆状态判断

  2. 自定义gradle插件,在构建过程中修改字节码,实现了耗时盲区监控,自动替换引导页

  3. 模块化

常见算法题

计算viewgroup层级

手写生产者消费者模型?不用BlockingQueue如何实现?

用两个栈实现一个队列?

快排,堆排序,冒泡排序?

动态规划钱币问题,走台阶问题?

Framework知识点

一、系统服务相关

1.谈谈zygote作用

作用:zygote作用有孵化应用进程、启动SystemServer。

启动流程:init进程通过读取init.rc配置文件,启动zygote。zygote启动过程主要分为native部分和Java部分。native部分完成了Android虚拟机的创建、JNI函数(TODO:比如哪些JNI函数呢)的注册、通过JNI调用ZygoteInit.java的main函数进入Java世界。Java部分完成了预加载资源、启动Systemserever、开始loop循环处理socket消息。

工作原理:runOnce函数处理socket消息,根据参数孵化子进程。

2.说说Android系统的启动流程

img

3.你知道怎么添加一个系统服务吗

添加系统服务的时机:可在SystemServer中启动系统服务的地方添加,跑在SystemServer进程。也可以在init.rc文件中配置,跑在独立的进程。

服务端需要做什么:启用binder机制(如果是跑在SystemServer进程的服务则不需要,因为SystemServer已经启用了),把自己注册到ServiceManager。如果是配置在init.rc文件中的服务,需要提供一个main入口函数。

客户端需要做什么:为系统服务实现一个ServiceFetcher,添加到缓存中,这样可以保证和其他系统服务一致的调用方式。

4.系统服务和bind的应用服务有什么区别

启动方式区别:系统服务在SystemServer中启动或在init.rc文件中配置,由init进程拉起。应用开发中的Service,由开发者调用bindService启动。

注册方式区别:系统服务由ServiceManager的addService方法注册

使用方式区别:系统服务通过context.getSystemService获取到binder来使用,应用服务通过ServiceConnection中的onBind回调拿到binder对象来使用。

5.ServiceManager启动和工作原理是怎样的

启动:init进程读取init.rc文件,拉起ServiceManager进程,执行入口main函数。main函数会启用binder机制,通过BINDER_SET_CONTEXT_MGR命令将自己注册为上下文管理者。通过BC_ENTER_LOOP指令将当前线程注册为binder线程,开启binder loop循环,处理binder中的消息,这样就可以和其他进程通信了。

工作原理:

1.如何获取ServiceManager的binder?

通过默认的0号引用

2.如何通过smgr添加服务

调用addService

3.如何通过smgr获取服务

调用getService

二、应用进程相关

1.你知道应用进程是怎么启动的吗

当系统尝试打开一个activity或者service时,会先检查其所在的进程是否已经存在(app!=null && app.thread!=null)。由AMS通过socket通信将ActivityThread的类名发送给zygote进程,zygote进程孵化出子进程,执行ActivityThread的main函数。main函数中通过thread.attach(false)通知AMS进程启动完成。

2.应用是怎么启用binder机制的

zygote在fork出应用进程后,调用handleChildProc->zygoteint.zygoteinit(),最终调用AppRuntime中的onZygoteInit这个native方法,onZygoteInit中会通过调用ProcessState.startThreadPool()开启binder线程池,其中打开binder驱动,映射内存等操作都是在获取ProcessState实例时做的,startThreadPool最终是调用IPCThreadState.joinThreadPool()开始了一个do。。while循环,不断从处理binder中的消息。到此,应用的binder机制就启动了。

3.谈谈你对Application的理解

作用:1.常在其onCreate生命周期中做一些sdk初始化工作

2.常用来保存一些应用运行期间所需的数据

3.提供应用上下文

继承关系:Application->ContextWrapper->Context

生命周期:在应用进程启动后,执行ActivityThread的main函数,其中会调用thread.attach(appThread)向AMS报告应用进程启动完成,并把appThread(ApplicationThread)的binder对象传了过去,这样AMS和应用进程就可以进行双向的binder调用了。AMS端收到appThread后,调用其bindApplication,应用端收到跨进程调用后,发送BIND_APPLICAION消息,应用主线程收到消息,调用handleBindApplication,反射创建appliaction,调用其onCreate。所以这里调用顺序是:application构造函数->attachBaseContext->onCreate。

4.谈谈你对Context的理解

作用:应用上下文,用来获取一些应用信息,系统服务。

应用中有几种Context?其继承关系?

Activity-ContextThemeWrapper-ContextWrapper-Context

Service-ContextWrapper

Application-ContextWrapper

所以应用中context的个数=application个数+activity个数+service个数

Context是一个抽象类,其实现是ContextImpl,context的创建是在创建每个application,activity或者service之前,通过new ContextImpl()创建的,并且各组件调用attach保存context,实际是attach是调用了attachBaseContext给ContextWrapper的成员mBase赋了值,ContextWrapper继承了Context,其实现的抽象方法都是间接调用了mBase相应的方法,是一种静态代理。如果我们通过反射换掉ContextWrapper的mBase,就可以对context的一些方法进行hook或者改造。

三、Activity组件相关面试题

1.说说Activity的启动流程

2.说说Activity的显示原理

通常我们通过setContentView设置Activity的布局文件,这其实是调用了window.setContentView。Activity的window是在attach方法中初始化的,Window是一个接口,PhoneWindow是其实现。所以在Activity中调用setContentView实际上调用了phonewindow的setContentView,在PhoneWindow该方法中,会先installDecor,即初始化DecorView,DecorView就是一个FrameLayout,是activity界面布局的根view。installDecor方法中会根据不同的feture选择不同的系统布局,加载到decorview中。这些系统布局中都有一个id为ID_ANDROID_CONTENT(即contentParent)的viewgroup,我们通过setContentView设置的布局,会被加载到contentParent中。至此,setContentView算是完成了activity布局的加载,view的创建。

而activity布局中这些view的测量,绘制,布局,是在ActivityThread中handleResumeActivity中触发的。

3.应用的UI线程是怎么启动的

四、其他应用组件相关面试题

1.

五、UI体系相关面试题

1.说说屏幕的刷新机制

2.surface跨进程传递原理

六、进程间通信相关面试题

1.Android Framework用到了哪些跨进程通信方式

    • 管道

​ 特点:半双工,传输的数据量小

​ 用处:Android消息机制中,Looper的死循环就通过epoll_wait阻塞在管道的读端,监听写事件,一旦有数据写入,就唤醒当前线程。

    • socket

​ 特点:全双工

​ 用处:AMS和zygote通信是采用的socket方式,比如启动应用进程是,AMS通过socket把ActivityThread类名发送到了zygote进程,zygote进程在runOnce方法解析参数,执行ActivityThread的main方法

    • 共享内存
    • binder

2.谈谈你对binder的理解

作用:Android特有的跨进程通信方式

特点:相比于其他方式,它安全,高效,使用方便。安全体现在其调用者的身份标记只能由binder机制在内核态中添加。高效在于其使用了内存映射,只需要一次数据拷贝。方便在于我们可以像调用普通的java方法一样使用binder机制,模糊了进程边界。

binder通信架构图:

img

3.Binder机制中,一次完整的IPC通信流程是什么样的

4.Binder对象跨进程传递的原理是怎样的

5.说一说binder的one way机制

Binder