《Android面试宝典》学习笔记
适用于初中级Android面试
一、面试准备
1、简历制作
-
个人资料
-
求职意向
-
专业技能
- 详细描述掌握的专业技能Java/Kotlin/Android
- 辅助开发技能的描述Git/AS/第三方源码/设计模式/架构
- 工作经历
- 项目经验描述/职责/技术要点
-
自我评价
自学能力强、踏实勤奋、爱钻研,热爱研发工作,责任心强;做事认真,工作积极;求知好学,分析问题解决问题能力突出,敢于接受挑战,有毅力耐力;团队合作,善于沟通和协调。
2、 面试问题
- 离职原因
- 加班态度
- 跳槽看法
- 薪资意见
- 印象深刻的技术问题
- 反问面试
- 晋升机制,期权股份,业务发展,产品/研发等项目运作模式。
- 自身价值
- 技术多样性
- 创新能力
- 团队战斗力
- 技术面试要点
- 自信
- 主动引导
- 简明扼要,突出重点
- 适度扩展
- 注重礼节
二、Java基础
1、面向对象的热点问题
-
面向对象和面向过程
-
AOP、OOP
-
面向对象的特征
-
封装
将对象的
属性和行为封装成类,对外隐藏实现细节 -
继承
-
多态
表现出多种形态,具有多样的实现方式
-

这里的名词都是C++语言中的概念;
虚函数,就是Java中的抽象函数的意思;
纯虚类,就是Java中的抽象类;
实现继承就是继承没有抽象函数的基类;
可视继承就是继承抽象类
-
抽象和封装的区别
抽象事将食物的共有、本质性的特征抽取描述;
封装则是将抽象得到的数据和行为相结合构成一个描述类;
-
接口和抽象类的区别
- 语法层面
抽象类 接口 可以有非抽象函数和变量 只能有public的抽象函数(Kotlin可以有函数默认实现) 成员变量可以多样化 只能有public static final的成员变量 可以有静态代码块和静态方法 不能有静态代码块和静态方法 类只能继承一个抽象类 类可以实现多个接口 -
设计层面
抽象类 接口 对问题领域分析设计得到的抽象概念,是对类的抽象,整体的。 接口是对行为的抽象,局部的。 继承 is的关系 实现是has的关系
2、集合框架的热点问题
-
ArrayList和Vector的区别
ArrayList Vector 基于Object[]实现,具有数组特性,可以自扩容 基于Object[]也具有数组特性,可自扩容 有索引查询效率高 有索引查询效率高 线程不安全 线程安全synchronized修饰 自扩容默认50% 自扩容100% 若扩容后还不足,则minCapaxity设为size大小 capacityIncrement的赋值与否来确定扩容的方式 -
HashMap的特点
- 实现Map接口的Key-Value形式
- 可以Null值,Key是否可NUll?多少个?
- 无序、非同步安全的
- 底层存储了Entry对象
-
HashMap的工作原理
通过Hash算法计算Key的hash值来存储对象(entry);
调用put时,调用hashCode计算hash值,得到对应table中的位置,若对应Key的table上存在元素,HashMap通过链表将产生碰撞的元素组织起来。冲突元素超过限制(默认是8),换用红黑树替换链表,从而提高效率。

3、I/O流的热点问题
-
I/O流常见子类及特点
- 结点流FileInputStream&FileOutputStream,作用于外部存储(非内存);需文件存在、可读/写;
- PipedInputSteam&PipedOutputSteam,用于线程操作,自带缓冲区;
- Buffered I/O Stream,将原始流数据缓存积累成大数据块再批量操作,注意flush的调用方才生效;
- Data I/O Stream ,常作用于网络数据传输,用作数据过滤流;
- InputStreamReader/OutputStreamWriter,会将数据自动转码为Unicode字符。
-
I/O流结构
- 字节流,对应于Java中就是xxxStream
- ByteArray
- File
- Filter
- Buffered
- Data
- Piped
- Sequence
- Object
- 字符流,对应于Java中就是xxxReader/Writer
- Buffered
- LineNumberReader
- CharArray
- Input/Output
- FileReader/Writer
- Piped
- Buffered
- 字节流,对应于Java中就是xxxStream
-
NIO的作用
传统I/O操作时阻塞的;
NIO是非阻塞的,提高程序性能,CPU利用率;
IO NIO 面向流 面向缓冲区 没有缓存区 有缓冲区 不能前后移动读取流数据的区段 可读取缓冲区的数据区段 阻塞 非阻塞 无选择器 有选择器,可用于监控多通道的数据 -
磁盘I/O的工作机制
File创建于磁盘,Java有File对象,并有与之关联的FileDescriptor
4、多线程问题Multithreading
-
多线程的实现方式
基于硬件及操作系统支持的前提下,Java实现多线程的方式
- 继承Thread类
- 实现Runnable接口,接口形式,便于要执行线程任务的类不能既继承Thread有继承其他类的多继承问题
- 使用ExecutorService、Callable、Future实现有返回结果的多线程,主要是Executor框架中,得到Future对象可以get任务结果
-
线程的运行状态
- 新建状态,被JVM分配堆内存
- 就绪状态,调用start之后,处于等待CPU使用权
- 运行状态
- 阻塞状态,不分配CPU,直到线程重新就绪
- 对象池状态,即线程执行了某对象的wait函数,则会被放到该对象的等待池中
- 对象锁状态,即线程执行去获取某对象的同步锁,而不得的时候,就会被放到该对象的锁池中
- 其他状态,如线程执行sleep,或者调用其他线程的join,或者进行I/O请求的时候,造成的阻塞
-
终止线程的方法
- 使用退出标志,即run函数执行完毕,正常退出
- Thread.interrupt中断线程
- Thread.stop强行终止,不建议使用,suspend、resume等都会引起不可预料的结果
-
Sleep和Yield
sleep yield 是当前线程休眠 暂停正在执行的线程对象,并去执行其他线程。即,交出cpu执行权 sleep(0)相当于yield sleep让自身不占用执行,其他任意优先级的线程都有机会抢到执行权 yield释放cpu交给同优先级,或者高优先级的线程来使用 sleep(xxx)之后,线程处于阻塞状态 yield之后,线程处于就绪状态 sleep会抛出InterruptedException yield无异常抛出 sleep更易于移植 -
Sleep和wait
- sleep属于Thread的方法,sleep指定时间后,会自动从监控状态恢复,不会释放对象锁;
- wait是Object的方法,调用wait会使本线程放弃对象锁,进入等待此对象的等待锁定池,且只有该对象notify/notifyAll后,本线程才会进入对象锁定池,准备获得对象锁来进入运行状态;
-
synchronized和lock的异同
- 均可用于线程安全问题
- Lock可实现所有synchronized的功能
- synchronized持有锁资源,可以自动释放锁
- Lock需要手动释放,载finally中。
- Lock可以用tryLock方式非阻塞的获取锁
- 性能消耗的差异
- 竞争不激烈时,synchronized使用轻量锁或偏向锁,均可有效减少轮询或阻塞的发生;
- Lock将未获得锁的线程放入等待队列,阻塞,带来切换的消耗;
- 高竞争时,synchronized使用重量级锁,此时相对处理速度慢,效率低于lock。
- 数据结构设计或框架设计上,多用lock
5、Java数据结构热门问题
-
Java内存模型
- 堆栈的理解
基本类型的变量和对象的引用变量,存放在栈内存;
堆内存存放对象实例和数组,JVM垃圾回收机制GC
- Java堆栈代码示例
public class Stack{ int[] data; int maxSize; int top; public Stack(int maxSize){ this.maxSize = maxSize; data = new int[maxSize]; top = -1; } //push public boolean push(int data){ if(top+1==maxSize){ System.out.println("栈已满!"); return false; } this.data[++top] = data; return true; } //pop public int pop() throws Exception{ if(top==-1){ throw new Exception("栈已空!"); } return this.data[top--]; } //test public static void main(String[] args) throw Exception{ Stack stack = new Stack(1000); stack.push(1); stack.push(3); while(stack.top>=0){ System.out.println("stack pop 后 "+stack.pop()); } } } -
简述对树的理解
- 非线性结构,有节点和分支,具有层次关系的数据描述
-
如何遍历二叉树
- 先序、中序、后序三种,均可递归和非递归
6、设计模式的热点问题
-
单例模式的理解
- 只有一个实例对象
- 必须是自己创建自己的唯一实例
- 必须给其他类提供该唯一实例对象的获取方式
为了避免状态不一致,常见的有日志对象、线程池、缓存、对话框、打印对象、驱动对象等
常见的5种单例模式写法
//饿汉式,非线程安全 class Singleton{ private static Singleton instance = new Singleton();//内部创建对象实例 private Singleton(){}//私有构造函数 //对外提供获取单例对象的函数 public static Singleton getInstance(){ return instance; } } //懒汉式,线程安全的 class Singleton{ private static Singleton instance = null; private Singleton(){} public static synchronized getInstance(){ if(instance==null){ instance = new Singleton(); } return instance; } } //枚举方式,Jvm创建模式也是静态的,所以线程安全的 enum Singleton{ INSTANCE } //静态内部类 线程安全的 class Singleton{ //静态内部类持有外部对象 private static class SingletonHolder{ private static final Singleton INSTANCE = new Singleton(); } private Singleton(){} //注意这里函数get是final的 public static final Singleton getInstance(){ return SingletonHolder.INSTANCE; } } //静态代码块,线程安全 class Singleton{ static{ Singleton instance = new Singleton(); } } -
工厂模式的理解
屏蔽创建对象的过程,提高灵活性,作为创建对象的过渡接口;
- 简单工厂模式,不利于系列创建
- 工厂方法模式,多形性工厂
- 抽象工厂模式,产生产品组,不利于新产品
三、Android菜鸟
1、系统架构相关问题
-
Android系统架构
- 四层架构,应用层、框架层、核心类库和Linux内核
2、Android版本变更特性
- 5.0特性
- materialDesign
- 多设备支持
- 全新通知中心
- 64位ART虚拟机
- 电池续航改进JobScheduleAPI
- Recent 最近使用
- 系统数据加密
- 独立数据保存、搜索改进、新Api支持、蓝牙4.1、USB Audio及多人分享等
- 6.0特性
- 运行时权限管理
- 网页体验提升
- App LInks应用关联
- Android Pay
- Fingerpirnt Support指纹支持
- Power&Change 电量管理
- 7.0特性
- 8.0特性
- 9.0特性
- 10.0特性
- 11.0特性
- 12特性
3、四大组件
-
Activity的生命周期
- 五种状态,启动、运行(可见、有交点、可交互)、暂停(无交互)、停止(完全不可见)、销毁
- 启动和销毁状态属于过渡态,不会停留此状态下
- 回调函数onCreate–>onStart->onResume->onPause->onStop->onDestroy,另有onRestart
-
横竖屏切换
- 不配置android:configChanges时候
- 切横屏:onSaveInstanceState->onPause->onStop->onDestroy->onCreate->onStart->onRestoreInstanceState->onResume
- 切竖屏:onSaveInstanceState->onPause->onStop->onDestroy->onCreate->onStart->onRestoreInstanceState->onResume
- 设置android:configChanges="orientation"时候,切横竖屏都只会走一次生命周期
- 设置android:configChanges="orientation|keyboardHidden"时,切横竖屏不会走生命周期回调,只会执行onConfigurationChanged函数
- 不配置android:configChanges时候
-
Activity的启动方式
- 显式intent调用,需要有class的直接引用或者className
- 隐式启动,通过带有action的intent调用
- 理解manifest中标签的含义
-
Activity启动模式
- standard标准模式,例如闹钟应用
- singleTop栈顶复用模式,例如浏览器tab
- singleTask栈内唯一模式,例如浏览器主界面
- singleInstance独立栈模式,例如来电界面
-
Activity之间传递数据
-
Intent传参,基础数据类型、数组、bundle、serializable、parcelable
-
Intent最大参数1024KB数据,也就是Binder的数据大小
-
-
Intent和PendingIntent区别
intent pendingIntent 即时性 延时 程序结束则Intent终止 仍然有效 需要context调用 自带context 运行在原task中 新task 一般用于四大组建Activity、service、broadcaseReceiver之间传参 一般用于消息通知 -
如何安全退出多个Activity
- 抛异常
- 记录已经打开的Activity并逐个关闭
- 特定广播关闭其他activity
- startActivityForResult递归关闭
-
应对Activity被系统回收
内存不足、切换配置、节省电量等时候可能会被回收。注意onSaveInstanceState保存状态
-
Service启动方式
- 运行于主线程(如果在子线程中调用呢?)
- startService,启动后执行到自身结束,不受调用者关联影响。
- bindService,通过跨进城IPC机制通讯,调用者和service关联,并能够交互通信。调用unbind销毁service
综合而言,bindService启动服务并能调用服务内部的方法。
-
常用的混合调用方式
start->bind->unbind->stop
-
service生命周期
- startServce:onCreate->onStartCommand->onDestory,被调用stopService或者自身stopSelf
- bindService: onCreate->onBind->onUnBind->onDestroy,被调用unBindService
-
广播相关
- 无序广播,sendBroadcast
- 有序广播,sendOrderedBroadcast,可用abortBroadcast拦截广播
- 另还有必达的广播、粘性广播、本地广播等,后序补充??
android:property属性配置优先级
- 静态注册、动态注册regiseterReceiver,注:高版本以后,广播策略有变化限制
-
EventBus事件总线
-
三部分Event、Subscriber、Publisher
-

-
优点,代码简洁优雅、使用方便、开销小、有助于代码接耦
-
-
ContentProvider的理解
用于不同应用程序间的数据共享,如通讯录、系统相册等。
不论数据源的形式如何,ContentProvider都按照表的形式对外提供,CURD也就是增删改查操作,query、insert、update、delete
- getContentResolver来获得ContentResolver操作ContentProvider提供的数据
- ContentProvider提供数据共享,并规定URI给外部
- ContentResolver使用URI来CRUD操作数据
- ContentObserver用于监听ContentProvider的数据变化
4、Fragment相关问题
在3.0开始出现,必须依赖于Activity,可以动态加载和静态加载;
动态加载用到事务,事务具有原子性、不可拆分的操作。
开启事务->添加fragment->提交事务
-
Fragment向下兼容使用support包
-
生命周期onAttach->onCreate->onCreateView->onActivityCreated->onStart->onResume->onPause->onStop->onDestroyView->onDestroy->onDetach
-
Fragment和Activity的交互
- Activity可以有Fragment的对象引用,或者fragmentManager中findFragmentByTag/ById
- Fragment中可以有getActivity获取Activity的引用
- 切换fragment,使用fragmentManager中的FragmentTranscation调用replace而后commit
FragmentManager fm = getFragmentManager(); FragmentTranscation ft = fm.beginTranscation(); //示例fragment XXXFragment fg = new XXXFragment(); ft.replace(R.id.content,fg); ft.commit();
5、控件相关问题
-
RecyclerView
在5.0出现的控件,用以替换listView、GridView等,有Adapter、ViewHolder、LayoutManager、ItemDecoration、ItemAnimator等几部分分工协作
-
WebView控件
- loadUrl加载网页资源,也可以是本地的Html资源
- loadDataWithBaseURL,加载字符资源
- getSettings里面配置必要的webView设置
- 若处理返回事件,需要override对应backPress函数和keyDown事件,并在WebView的shouldOverrideUrlLoading中处理
- WebView桥接Java和JS交互,使用@JavascriptInterface注解
- Java调用Js,使用loadUrl可以调用Javascript语句
- JS调用Java,需要Java中有@JavascriptInterface的注解的函数,然后webView.addJavascriptInterface 添加进来,并提供js调用的别名;而后js中就可以调用
6、数据处理的相关问题
-
XML解析
-
Dom解析
基于文档驱动的解析,构建Dom树,在内存中持久,可修改数据和结构
优点:直观、简单,适用于小文件
缺点:加载整个XML文件,资源消耗大,不适合大文件
-
SAX解析
Simple API for XML,基于事件的解析器,扫描文件的标签;
优点:效率高、内存占用小
缺点:需要代码负责tag的处理逻辑,适用麻烦,单向导航,不便于反问文档的不同部分,不支持XPath
-
Pull解析
类似于SAX,基于事件,但是在开始时就完成了大多数处理,而非坚挺tag结束;
优点:小巧轻便、解析速度快、简单易用
-
-
Json数据
- 有数字、字符串、boolean、array、object、null等组成;
- Json只有对象
{}和数组[]两种结构 - 解析Json可用JsonObject/JsonArray,或者开源库Gson
- JsonReader使用流的形式读取json数据,类似于PUll解析,beginObject/beginArray,close;
-
SQLite相关
数据库的表对应关系,一对一、一对多、多对多;常见的数据库框架greenDao、Realm、Room;
-
SQLiteDatabase操作数据库
- openOrCreateDatabase
- insert
- delete
- query
- update
- execSQL
- close
-
SQLiteOpenHelper
- getWriteableDatabase
- getReadableDatabse
调用如上函数时候,数据库若无,则会被create创建
-
Cursor
- getCount、isFirst、isLast、moveToFirst/last/next/previous、getColumnindexOrthrow、getInt/getString
-
6、数据加密相关
-
base64编码
-
AES加密,强安全性、高性能、高效率、易用灵活
- 轮变化、圈数、密钥扩展
- 迭代的、对称密钥分组的密码
- 加密数据块长度128bit,密钥长度可以是128bit,192bit、256bit
- 数据块及密钥长度不足时自动补足
-
DES加密,密钥长度小于56位,所以被AES代替了
-
RSA加密
公钥加密算法、非对称加密;
两个大素数的乘积,作为公钥;自身作为私钥;
效率略低,安全性高;
-
MD5算法
数字摘要 Message-Digest Algorithm 5,用于确保数据信息的完整、一致性
- 压缩性,MD5计算结果长度固定
- 易计算
- 抗修改,原始数据的改动会引起md5的变动
- 强碰撞性,较难有不同数据源的同一md5值
常用于密码摘要;
7、网络交互的相关问题
-
Http协议特点
- 简单快速
- 灵活
- 无状态
- 常见header和状态吗code
- Host、Charset、Connection、Form、timeOut
- 200、302 重定向、404、找不到url资源、500 服务器错误
- Http的请求和响应
//简单的示例 URL realUrl = new URL(requestUrl); HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection(); conn.setDoOutput(true); conn.setUseCaches(false); conn.setRequestMethod("POST"); conn.setRequestProperty("Connection","Keep-Alive"); ... //响应 if(conn.getResponseCode()!=200){ throw new RuntimeException("请求url失败"); } InputStream is = conn.getInputStream(); String result = readData(is,"GBK"); conn.disconnect(); -
POST请求的几种形式
- Form表单形式
- JSON数据形式
- 文件形式
//1、form post.setEntity(postEntity); //2、json post.addHeader("Connect-Type","applicatin/json"); post.setEntity(new StringEntity(jsonStr)); //3、file MultipartEntity entity = new MultipartEntity(); ContentBody cb = new FileBody(file); entity.addPart("img",cb); post.setEntity(entity); //服务端可以根据content-type判断数据请求类型 -
Socket通信
socket是对tcp/ip的封装api,StreamSocket和DatagramSocket(使用udp)
-
基于TCP的socket
ServerSocket serverSocket = new ServerSocket(); Socket socket = serverSocket.accept();//阻塞的 //客户端 SocketClient client = new SocketClient(); client.getOutputStream(); -
基于UDP的数据传输
byte data[] = new byte[1024]; DatagramSocket packet = new DatagramSocket(data,data.length); packet.receive();//也是阻塞的 packet.send();
Http和socket的区别在于,http是请求–响应式的,socket可以双向通讯;
-
-
Volley框架
适用于数据量小、通信频繁的网络操作;
- StringRequest、JsonObjectRequest、JsonArrayRequest、ImageRequest
//RequestQueue是请求队列,根据内部算法,可适时的并发的发出队列的请求,一个requestQueue即可 RequestQueue mQueue = Volley.newRequestQueue(context); StringRequest request = new StringRequest();//这里可以设置post,get的方式 mQueue.add(request); -
Volley异步加载图片
ImageLoader内部使用IamgeRequest,做了缓存以及过滤重复请求等。
- 创建RequestQueue、ImageCache、ImageLoader对象;
- 通过ImageLoader获取ImageListener
- 调用ImageLoader的get
-
Volley的NetworkImageView加载网络图片
netImageView.setImageUrl("");
四、Android大神
1、线程相关问题
-
线程间通信
Android是UI单线程机制,主线程避免ANR,所以存在需要子线程交互的问题。线程间通信可用Hanlder
-
线程池的理解
面向对象的编程中,创建/销毁 对象都是相对耗时消耗资源的。
尽可能减少对象的创建和销毁的频次,用到线程池。
概念,优点,使用方式;
多线程应用在启动之初,创建一个线程集合,存放一定量的线程空闲队列中;不消耗cpu,占用较少内存;
有请求的时候,分配任务给空闲线程;
预制线程不足用时,线程池可自由创建新的线程,来处理请求任务;
超出最大设定线程数的时候,抛出异常,拒绝任务;
任务清闲时候,会移除停用状态的线程;
- 线程池可提高性能、减少CPU的消耗,控制并发线程数,避免内存过度消耗;
-
如何创建线程池
ThreadPoolExecutor,提供管理任务执行、线程调度、线程池管理的功能;
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler){ }- corePoolSize 核心线程数
- maximumPoolSize 线程池维护线程最大数
- keepAliveTime 维护线程所允许的空闲时间
- unit 空闲时间的单位
- workQueue 缓冲队列
- threadFactory 新建线程用的工厂类
- handler 线程池拒绝任务时候的处理策略
2、多媒体相关
-
Android中动画
- 补间动画 Tween Animation
- 旋转、平移、缩放、透明度
- 不改变控件位置属性
- 帧动画 Frame Animation
- 加载一系列的图片资源,逐帧播放
- 属性动画 Property Animation
- 类似补间动画,但是修改控件属性
- 补间动画 Tween Animation
-
Interpolator动画差值器
加速、减速、重复、弹跳等不同的动画细节效果;
-
在res/anim下创建interpolator的差值器
<cycleInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:cycles="3"/><!-- 表示重复三次 --> -
在res/anim下创建动画xml
<translate xmlns:android="http://schemas.android.com/apk/res/android" android:fromXDelta="0" android:interpolator="@anim/cycle_3" android:toXDelta-"10" android:duration="500"/> -
在代码中控件使用动画资源
Animation shake = AnimationUtils.loadAnimation(this,R.anim.shake); et_phone.startAnimation(shake);
-
-
Android中常见的视频播放方式
-
自带播放器App
Uri uri = Uri.parse("xxxx/xxx.mp4"); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(uri,"video/mp4"); startActivity(intent); -
VideoView控件
videoView.setMediaController(new MediaController(context)); videoView.setVideoURI(uri); videoView.start(); videoView.requestFocus(); -
MediaPlayer&SurfaceView
SurfaceView属于绘图容器,可以直接从内存或者DMA等硬件接口取得图像,可以在主线程之外的线程向屏幕绘图。可与MediaPlayer结合使用。
- MediaPlayer加载视频文件
- 创建布局文件SurfaceView,设置SurfaceHolder的Callback;
- 调用mediaPlayer的setDisplay,输出图像到surfaceView
- mediaPlayer的start、stop、pause操作控制;
-
-
Vitamio视频框架/ExoPlayer框架
3、机制相关问题
-
Handler运行机制
事件驱动型程序设计模型,与其他线程协同工作,接收其他线程消息并更新主线程;
App点击事件的响应、Activity的启动、更新界面等,都是handler的应用;
handler可用于异步请求、定时操作;
-
Message
线程间的消息
-
MessageQueue
消息集合,用以存放Runnable和Message
-
Looper
不断循环消息队列,取出消息
-
Handler
接收消息回调
如需在自己线程创建handler,则必须调用Looper的perpare()和loop();

- 在UI线程创建handler
- 在子线程中调用handler的sendMessage,消息会被存放到UI线程的MessageQueue中去。因为handler是UI线程创建的;
- Looper会取出MessageQueue中的消息,分发给hanlder
- handler中的handlerMessage回调,处理消息;
-
-
事件驱动型程序设计模型
特点:
- 有消息队列,用以存放消息
- 有轮询器,用以处理消息队列,无消息时候就休眠
- 有消息实体,每个消息都与一个消息处理器handler绑定。handler生命周期很短。
避免传统时间模型的持久轮询,阻塞耗费cpu资源;
-
AsynaTask异步任务的理解
为耗时操作开启新线程,AsyncTask是抽象类;Params、Progress、Result三个范型参数;
- Params,启动任务的入参,如Url,执行数据等;
- Progress,后台执行任务的百分比;
- Result,执行任务的返回结果;
可用Void表示空参数类型;
- onPreExecute 准备执行,预初始化的必要操作
- doInBackground 核心的后台任务逻辑,返回参数传递到onPostExecute中。可食用publishProgress发布进度值,到onProgressUpdate中,可用于UI显示进度
- onProgressUpdate 进度的更新
- onPostExecute 完成任务后后台结果处理。
AsyncTask适用于小型、简单的异步处理。
注:AsyncTask后续版本已经废弃,看似比Handler简单轻量,实则更耗资源;
| 类名 | 优点 | 缺点 |
|---|---|---|
| AsyncTask | 简单、快捷、过程可控 | 多个异步操作并都去更新UI时,变得复杂 |
| Handler | 结构清晰、功能定义明确 | 单个后台异步处理时,显得代码繁多,结构相对复杂 |
-
Android的事件分发
Android的手势冲突,多用内部拦截或外部拦截处理;View的分发机制涉及dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent三个重要函数;
- dispatchTouchEvent,只要事件传递到当前View,就会调用。内部判断是否interceptTouchEvent,来确定时自身消费,还是分发给子View

-
图示中、super/true/false代表的是return返回值,super调用父类实现;
-
onInterceptTouchEvent在dispatchTouchEvent中调用,用以判断自身消费还是向下分发;
-
ouTouchEvent也是在dispatchTouchEvent中调用用于处理事件,返回值false则表示自身不消费也不拦截,true表示自身消费掉;
-
Android消息推送
消息推送的实现有pull方式、push方式;
-
pull表示client定期请求,频次低则消息不及时,频次高,则耗费网络与内存cpu等资源
-
push则是通过长链接实现服务器到client的消息推送;消耗电量、占用资源。
-
-
如何绘制View
简单说分为三步:measure、layout、draw
- onMeasure,测量View的宽高数据
- onLayout,ViewGroup中用于确定子view的位置关系
- onDraw绘制view自身的背景、边框、子view等
-
OAuth2的认证机制
Open Authorization,获取第三方服务授权的方式;
安全、开放、简易;
服务令牌,而不需要密码账号,来获取用户信息数据
- 用户访问3rd server,需要userInfo
- 3rd server请求用户User Server
- User Server验证3rd Server后,给它一个临时Token
- 3rd server拥有token后,向User Server请求授权
- 用户在User Server上确认授权,以及配置授权信息Info
-
AIDL的理解
Android进程间通信机制,进程间不能共享内存;Inter Progress Communication;
AIDL Android Interface Definition Language,类似Java 接口语法;
- 接口名与AIDL文件名必须相同
- client、server中AIDL的皆苦文件包名必须相同
- 接口和方法前,不能加权限修饰符和final、static等
- 默认支持基本数据类型int、long、boolean、String等及List、Map、Charsequence
- 对List、Map的元素必须是aidl支持的类型
- 自定义类型作为参数或返回值,则必须实现Parcelable接口
- 所有非Java基本数据类型的参数,必须加上in、out、inout标记,用以标记入参还是返参;Java原始类型默认的标记为in,不能是其他;
- 自定义类型和aidl即使在同一包下,生成的其他接口类在aidl中也需要import导入;
- 需要一个service类协同使用
-
说明AIDL的使用
A应用调用B应用的服务,得到计算结果;
- 在B中创建aidl文件
- B中实现aidl的接口,binder
- B中创建service,用以返回binder
- 把B中的aidl复制到A中
- A调用B中定义的service即可,隐式调用;
4、优化相关问题
-
如何优化Listview
- 复用convertView
- 定义存储控件引用类的viewHolder
- 数据粉分页加载、分批加载
- 图片处理
- WeakRefrence弱引用
- 图片压缩
- 及时释放资源
避免BaseAdapter中使用static全局变量,尤其避免其引用context,引起内存泄漏
避免ListView的Adapter中使用线程,其生命周期不可控,避免内存泄漏;
-
Android布局优化
- <include>复用布局片段
- <merge>标签减少层级填充
- 根结点是FrameLayout可并入到Activity自身根结点,此时background、padding无效
- 结合include使用
- ViewStub延迟加载
- 合理的布局方式Releative、LinearLayout、ConstraintLayout等
嵌套层级深引起堆栈溢出问题,推荐层级小于10,view个数小于80;
-
使用Hierarchy Viewer分析布局
-
Android中使用的引用
- 强引用,即使OOM也不回收
- 软引用,用以实现内存敏感的高速缓存,内存空间不足时候,GC可能回收
- 弱引用,更短的生命周期,一经发现,不论内存足否,都会标记回收。
- 虚引用,形同虚设,用以跟踪垃圾回收器的活动。不会决定对象的生命周期,必须与引用队列联合使用。
-
如何处理网络图片产生的OOM
图片占用内存大小 = 总像素数 x 单位像素
颜色模式 单位像素空间 ALPHA_8 1 byte ARGB_4444 2 bytes RGB_565 2 bytes ARGB_8888 4 bytes - 调整图片大小,根据显示需要来缩放,缩放计算的时候,Options.inJustDecodeBounds仅计算宽高,而不完全加载,节省内存;
- 适当的颜色模式
- 及时回收图片资源
- LruCache缓存图片,复用
-
如何检测内存泄漏
- DDMS-Heap
- MAT,Memory Analyzer Tool
- 解决内存泄漏的点
- 使用单例时候注意context的引用,避免Activity持有过长
- 避免非静态内部类中创建静态实例,会引用外部类
- I/O的及时关闭
- 及时回收ThreadLocal的绑定对象
- 及时回收与有效利用已有对象
5、JNI相关
-
JNI的简单描述
创建Java工程,声明native方法
创建.h文件
编写c/c++代码,函数命名与上述的native方法相关联
创建.mk文件,配置JNI编译环境
执行ndk的build
Java中即可调用
6、异常相关问题
-
捕获全局异常
- 创建crashHandler,实现UncaughtExceptionHandler
- 在Application 中注册为全局默认异常捕获器
- 在uncaughtException中处理对应异常问题
-
如何避免ANR
Application Not responding,程序无响应,Android中有三类常见
- KeyDispatchTimeout ,按键/触摸事件无响应,5s超时
- BroadcastTimeout 广播无法处理 10s超时
- ServiceTimeout 服务无法处理 20s 超时
注意避免方式
- 主线程避免耗时操作,如网络、IO、大量计算等
- 避免广播中的复杂操作,如遇到,可用另起service处理
- 避免synchronized,死锁等错误处理不当的情况
增强灵敏性
-
如何测试
- Junit单元测试
- Monkey测试
7、第三方框架相关
-
支付宝/微信 支付流程
- 商户签约
- 密钥配置
- 集成sdk
-
REST REpresentational State Transfer 表属性状态转移,软件架构风格。通过资源的表现形式来操作资源。
优点:
- 可以利用cache提高响应速度
- 通信无状态,可让不同服务器处理一系列请求中的不同请求,提高服务器的扩展性
- 浏览器即为client,简化软件需求
- 相比于其他Http协议之上的机制,REST的软件依赖性更小
- 不需要额外的资源发现机制
缺点:
- 复杂应用对应URL变长
- REST不支持事务
- REST安全性不足
- 风格规范,并非标准,现实实现各有差异;
-
RESTful Web Service
-
RxJava的理解
响应式编程框架、专注于异步和控制可观察数据/事件;
- Observable
- Subscriber
通过订阅建立关系,配合schedules调度线程分配,结果中onNext、onCompleted、onError处理不同状态返回。
-
REtrofit库的理解
使用注解简化网络请求,默认OKHttp为httpClient,使用retrofit的前提是服务器代码遵循REST规范;
- 性能最好、处理最快
- 配合REST API非常方便
- 传输层默认OkHttp框架
- 支持NIO,同时支持URL参数替换和查询参数
- 返回结果可转换为Java对象(Json字符串或Protocol BuffersProtocol)
- 支持Multipart请求和文件上传
8、屏幕适配问题
-
屏幕适配方案
- 套图适配,完美适配不失真,较难实现,App臃肿
- 9patch适配,省精力省时间省内存,减少代码量;不能完全适配;
- 布局适配
- 权重适配,约束比例,少用具体值,但复杂页面上效果不好;
- 约束布局、线性、相对布局;
- 纯色背景,多用shape代替png
-
屏幕尺寸、分辨率、像素密度
- 屏幕尺寸是屏幕物理对角线长度,单位英寸
- 分辨率只单位像素点数,px,1px为1像素点。如1920x1080
- 像素密度,单位dpi, dot per inch;即每英寸像素点数
px 像素单位
dp/dip density independent pixel,密度无关像素;Android中160dpi 为基准 1dip = 1px ;320dpi时候,则 1dp = 2px
dpi , dots per inch 每英寸的像素数 ,表示对角线的像素值。例如 1920x1080分辨率 5英寸的屏幕,dpi =19202+10802/5.0\sqrt{1920^2+1080^2}/5.019202+10802/5.0
9、程序打包问题
-
数字签名的几种模式
- debug模式
- release模式
配置keystore,在AS中build的apk通过AS安装的实质是
adb install -t xxx.apk,没有签名也能使用。实际发布,不论是debug还是release的apk,都有签名文件,在apk的解压后签名目录META-INF内有cert文件; -
使用相同数字证书的好处
- 利于维护升级
- 便于程序模块化设计和开发
- 可用于多应用共享数据
-
多渠道打包
- 普通的gradle的productFlavors配置占位符
- walle 开源打包框架
-
代码混淆
- pro gua r d.cfg配置
- minifyEnable true
-
加固
-
瘦身apk
- 混淆
- code clean
- png压缩 tinyPng
- svg代替
- 删除替换support包,冗余jar依赖
- 动态加载,插件化
本文档详尽总结了Android面试的准备策略,包括简历制作、Java基础、Android基础知识、多线程、设计模式、数据结构、网络通信、多媒体处理、优化技巧、JNI、异常处理和第三方框架等内容,助你全面提升技术竞争力。

4060

被折叠的 条评论
为什么被折叠?



