适用于初中级Android面试
个人资料
求职意向
专业技能
自我评价
自学能力强、踏实勤奋、爱钻研,热爱研发工作,责任心强;做事认真,工作积极;求知好学,分析问题解决问题能力突出,敢于接受挑战,有毅力耐力;团队合作,善于沟通和协调。
面向对象和面向过程
AOP、OOP
面向对象的特征
封装
将对象的属性
和行为
封装成类,对外隐藏实现细节
继承
多态
表现出多种形态,具有多样的实现方式
这里的名词都是C++语言中的概念;
虚函数,就是Java中的抽象函数的意思;
纯虚类,就是Java中的抽象类;
实现继承就是继承没有抽象函数的基类;
可视继承就是继承抽象类
抽象和封装的区别
抽象事将食物的共有、本质性的特征抽取描述;
封装则是将抽象得到的数据和行为相结合构成一个描述类;
接口和抽象类的区别
抽象类 | 接口 |
---|---|
可以有非抽象函数和变量 | 只能有public的抽象函数(Kotlin可以有函数默认实现) |
成员变量可以多样化 | 只能有public static final的成员变量 |
可以有静态代码块和静态方法 | 不能有静态代码块和静态方法 |
类只能继承一个抽象类 | 类可以实现多个接口 |
设计层面
抽象类 | 接口 |
---|---|
对问题领域分析设计得到的抽象概念,是对类的抽象,整体的。 | 接口是对行为的抽象,局部的。 |
继承 is的关系 | 实现是has的关系 |
ArrayList和Vector的区别
ArrayList | Vector |
---|---|
基于Object[]实现,具有数组特性,可以自扩容 | 基于Object[]也具有数组特性,可自扩容 |
有索引查询效率高 | 有索引查询效率高 |
线程不安全 | 线程安全synchronized修饰 |
自扩容默认50% | 自扩容100% |
若扩容后还不足,则minCapaxity设为size大小 | capacityIncrement的赋值与否来确定扩容的方式 |
HashMap的特点
HashMap的工作原理
通过Hash算法计算Key的hash值来存储对象(entry);
调用put时,调用hashCode计算hash值,得到对应table中的位置,若对应Key的table上存在元素,HashMap通过链表将产生碰撞的元素组织起来。冲突元素超过限制(默认是8),换用红黑树替换链表,从而提高效率。
I/O流常见子类及特点
I/O流结构
NIO的作用
传统I/O操作时阻塞的;
NIO是非阻塞的,提高程序性能,CPU利用率;
IO | NIO |
---|---|
面向流 | 面向缓冲区 |
没有缓存区 | 有缓冲区 |
不能前后移动读取流数据的区段 | 可读取缓冲区的数据区段 |
阻塞 | 非阻塞 |
无选择器 | 有选择器,可用于监控多通道的数据 |
磁盘I/O的工作机制
File创建于磁盘,Java有File对象,并有与之关联的FileDescriptor
多线程的实现方式
基于硬件及操作系统支持的前提下,Java实现多线程的方式
线程的运行状态
终止线程的方法
Sleep和Yield
sleep | yield |
---|---|
是当前线程休眠 | 暂停正在执行的线程对象,并去执行其他线程。即,交出cpu执行权 |
sleep(0)相当于yield | |
sleep让自身不占用执行,其他任意优先级的线程都有机会抢到执行权 | yield释放cpu交给同优先级,或者高优先级的线程来使用 |
sleep(xxx)之后,线程处于阻塞状态 | yield之后,线程处于就绪状态 |
sleep会抛出InterruptedException | yield无异常抛出 |
sleep更易于移植 |
Sleep和wait
synchronized和lock的异同
Java内存模型
基本类型的变量和对象的引用变量,存放在栈内存;
堆内存存放对象实例和数组,JVM垃圾回收机制GC
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());
}
}
}
简述对树的理解
如何遍历二叉树
单例模式的理解
为了避免状态不一致,常见的有日志对象、线程池、缓存、对话框、打印对象、驱动对象等
常见的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系统架构
Activity的生命周期
横竖屏切换
Activity的启动方式
Activity启动模式
Activity之间传递数据
Intent传参,基础数据类型、数组、bundle、serializable、parcelable
Intent最大参数1024KB数据,也就是Binder的数据大小
Intent和PendingIntent区别
intent | pendingIntent |
---|---|
即时性 | 延时 |
程序结束则Intent终止 | 仍然有效 |
需要context调用 | 自带context |
运行在原task中 | 新task |
一般用于四大组建Activity、service、broadcaseReceiver之间传参 | 一般用于消息通知 |
如何安全退出多个Activity
应对Activity被系统回收
内存不足、切换配置、节省电量等时候可能会被回收。注意onSaveInstanceState保存状态
Service启动方式
综合而言,bindService启动服务并能调用服务内部的方法。
常用的混合调用方式
start->bind->unbind->stop
service生命周期
广播相关
android:property属性配置优先级
EventBus事件总线
ContentProvider的理解
用于不同应用程序间的数据共享,如通讯录、系统相册等。
不论数据源的形式如何,ContentProvider都按照表的形式对外提供,CURD也就是增删改查操作,query、insert、update、delete
在3.0开始出现,必须依赖于Activity,可以动态加载和静态加载;
动态加载用到事务,事务具有原子性、不可拆分的操作。
开启事务->添加fragment->提交事务
Fragment向下兼容使用support包
生命周期onAttach->onCreate->onCreateView->onActivityCreated->onStart->onResume->onPause->onStop->onDestroyView->onDestroy->onDetach
Fragment和Activity的交互
FragmentManager fm = getFragmentManager();
FragmentTranscation ft = fm.beginTranscation();
//示例fragment
XXXFragment fg = new XXXFragment();
ft.replace(R.id.content,fg);
ft.commit();
RecyclerView
在5.0出现的控件,用以替换listView、GridView等,有Adapter、ViewHolder、LayoutManager、ItemDecoration、ItemAnimator等几部分分工协作
WebView控件
XML解析
Dom解析
基于文档驱动的解析,构建Dom树,在内存中持久,可修改数据和结构
优点:直观、简单,适用于小文件
缺点:加载整个XML文件,资源消耗大,不适合大文件
SAX解析
Simple API for XML,基于事件的解析器,扫描文件的标签;
优点:效率高、内存占用小
缺点:需要代码负责tag的处理逻辑,适用麻烦,单向导航,不便于反问文档的不同部分,不支持XPath
Pull解析
类似于SAX,基于事件,但是在开始时就完成了大多数处理,而非坚挺tag结束;
优点:小巧轻便、解析速度快、简单易用
Json数据
{}
和数组[]
两种结构SQLite相关
数据库的表对应关系,一对一、一对多、多对多;常见的数据库框架greenDao、Realm、Room;
SQLiteDatabase操作数据库
SQLiteOpenHelper
调用如上函数时候,数据库若无,则会被create创建
Cursor
base64编码
AES加密,强安全性、高性能、高效率、易用灵活
DES加密,密钥长度小于56位,所以被AES代替了
RSA加密
公钥加密算法、非对称加密;
两个大素数的乘积,作为公钥;自身作为私钥;
效率略低,安全性高;
MD5算法
数字摘要 Message-Digest Algorithm 5,用于确保数据信息的完整、一致性
常用于密码摘要;
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请求的几种形式
//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框架
适用于数据量小、通信频繁的网络操作;
//RequestQueue是请求队列,根据内部算法,可适时的并发的发出队列的请求,一个requestQueue即可
RequestQueue mQueue = Volley.newRequestQueue(context);
StringRequest request = new StringRequest();//这里可以设置post,get的方式
mQueue.add(request);
Volley异步加载图片
ImageLoader内部使用IamgeRequest,做了缓存以及过滤重复请求等。
Volley的NetworkImageView加载网络图片
netImageView.setImageUrl("");
线程间通信
Android是UI单线程机制,主线程避免ANR,所以存在需要子线程交互的问题。线程间通信可用Hanlder
线程池的理解
面向对象的编程中,创建/销毁 对象都是相对耗时消耗资源的。
尽可能减少对象的创建和销毁的频次,用到线程池。
概念,优点,使用方式;
多线程应用在启动之初,创建一个线程集合,存放一定量的线程空闲队列中;不消耗cpu,占用较少内存;
有请求的时候,分配任务给空闲线程;
预制线程不足用时,线程池可自由创建新的线程,来处理请求任务;
超出最大设定线程数的时候,抛出异常,拒绝任务;
任务清闲时候,会移除停用状态的线程;
如何创建线程池
ThreadPoolExecutor,提供管理任务执行、线程调度、线程池管理的功能;
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler){
}
Android中动画
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结合使用。
Vitamio视频框架/ExoPlayer框架
Handler运行机制
事件驱动型程序设计模型,与其他线程协同工作,接收其他线程消息并更新主线程;
App点击事件的响应、Activity的启动、更新界面等,都是handler的应用;
handler可用于异步请求、定时操作;
Message
线程间的消息
MessageQueue
消息集合,用以存放Runnable和Message
Looper
不断循环消息队列,取出消息
Handler
接收消息回调
如需在自己线程创建handler,则必须调用Looper的perpare()和loop();
事件驱动型程序设计模型
特点:
- 有消息队列,用以存放消息
- 有轮询器,用以处理消息队列,无消息时候就休眠
- 有消息实体,每个消息都与一个消息处理器handler绑定。handler生命周期很短。
避免传统时间模型的持久轮询,阻塞耗费cpu资源;
AsynaTask异步任务的理解
为耗时操作开启新线程,AsyncTask是抽象类;Params、Progress、Result三个范型参数;
可用Void表示空参数类型;
AsyncTask适用于小型、简单的异步处理。
注:AsyncTask后续版本已经废弃,看似比Handler简单轻量,实则更耗资源;
类名 | 优点 | 缺点 |
---|---|---|
AsyncTask | 简单、快捷、过程可控 | 多个异步操作并都去更新UI时,变得复杂 |
Handler | 结构清晰、功能定义明确 | 单个后台异步处理时,显得代码繁多,结构相对复杂 |
Android的事件分发
Android的手势冲突,多用内部拦截或外部拦截处理;View的分发机制涉及dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent三个重要函数;
图示中、super/true/false代表的是return返回值,super调用父类实现;
onInterceptTouchEvent在dispatchTouchEvent中调用,用以判断自身消费还是向下分发;
ouTouchEvent也是在dispatchTouchEvent中调用用于处理事件,返回值false则表示自身不消费也不拦截,true表示自身消费掉;
Android消息推送
消息推送的实现有pull方式、push方式;
pull表示client定期请求,频次低则消息不及时,频次高,则耗费网络与内存cpu等资源
push则是通过长链接实现服务器到client的消息推送;消耗电量、占用资源。
如何绘制View
简单说分为三步:measure、layout、draw
OAuth2的认证机制
Open Authorization,获取第三方服务授权的方式;
安全、开放、简易;
服务令牌,而不需要密码账号,来获取用户信息数据
AIDL的理解
Android进程间通信机制,进程间不能共享内存;Inter Progress Communication;
AIDL Android Interface Definition Language,类似Java 接口语法;
说明AIDL的使用
A应用调用B应用的服务,得到计算结果;
如何优化Listview
避免BaseAdapter中使用static全局变量,尤其避免其引用context,引起内存泄漏
避免ListView的Adapter中使用线程,其生命周期不可控,避免内存泄漏;
Android布局优化
嵌套层级深引起堆栈溢出问题,推荐层级小于10,view个数小于80;
使用Hierarchy Viewer分析布局
Android中使用的引用
如何处理网络图片产生的OOM
图片占用内存大小 = 总像素数 x 单位像素
颜色模式 | 单位像素空间 |
---|---|
ALPHA_8 | 1 byte |
ARGB_4444 | 2 bytes |
RGB_565 | 2 bytes |
ARGB_8888 | 4 bytes |
如何检测内存泄漏
JNI的简单描述
创建Java工程,声明native方法
创建.h文件
编写c/c++代码,函数命名与上述的native方法相关联
创建.mk文件,配置JNI编译环境
执行ndk的build
Java中即可调用
捕获全局异常
如何避免ANR
Application Not responding,程序无响应,Android中有三类常见
注意避免方式
增强灵敏性
如何测试
支付宝/微信 支付流程
REST REpresentational State Transfer 表属性状态转移,软件架构风格。通过资源的表现形式来操作资源。
优点:
缺点:
RESTful Web Service
RxJava的理解
响应式编程框架、专注于异步和控制可观察数据/事件;
通过订阅建立关系,配合schedules调度线程分配,结果中onNext、onCompleted、onError处理不同状态返回。
REtrofit库的理解
使用注解简化网络请求,默认OKHttp为httpClient,使用retrofit的前提是服务器代码遵循REST规范;
屏幕适配方案
屏幕尺寸、分辨率、像素密度
px 像素单位
dp/dip density independent pixel,密度无关像素;Android中160dpi 为基准 1dip = 1px ;320dpi时候,则 1dp = 2px
dpi , dots per inch 每英寸的像素数 ,表示对角线的像素值。例如 1920x1080分辨率 5英寸的屏幕,dpi = 192 0 2 + 108 0 2 / 5.0 \sqrt{1920^2+1080^2}/5.0 19202+10802/5.0
数字签名的几种模式
配置keystore,在AS中build的apk通过AS安装的实质是adb install -t xxx.apk
,没有签名也能使用。实际发布,不论是debug还是release的apk,都有签名文件,在apk的解压后签名目录META-INF内有cert文件;
使用相同数字证书的好处
多渠道打包
代码混淆
加固
瘦身apk