Android面试题以及我的回答_网易
1.描述Activity生命周期
答:Activity的生命周期主要由以下七种状态构成:onCreate(创建),onStart(启动),onResume(开始),onPause(暂停),onStop(停止),onDestory(摧毁),onRestart(重启动);
他们在以下几种状况下,按顺序执行:
- 启动:onCreate->onStart->onResume;
- 进入透明状态:onResume->onPause;
- 从透明状态复原:onPause->onResume;
- 进入后台:onResume->onPause->onStop;
- 从后台复原:onStop->onRestart->onStart->onResume;
- 关闭当前Activity;onResume->onPause->onStop->onDestory;
同时,在Activity不正常关闭的时候会在onPause或onStop之前调用onSaveInstanceState方法,恢复时,会在onStart或onResume之前调用onRestoreInstanceState方法;
2.什么是ANR,如何规避;
答:
ANR全称是Application Not Responding,即应用无响应。是指如果应用程序如果有一段时间内响应不灵敏,系统会弹出一个应用程序无响应对话框。这个对话框将严重影响用户的程序使用体验,所以我们应该避免该对话框的出现。
ANR的避免我们需要从触发条件分析,在Android系统中,应用程序的响应性是Activity Manager和Window Manager系统服务监视的。当它们监测到一下其中一种超时情况,将显示ANR:
- 在5秒内没有响应输入的事件;
- BroadcastReciver在10秒内没有执行完毕;
而导致以上超时的原因主要是在UI线程中进行了一些耗时操作(网络访问,数据库操作或其他等),阻塞了UI界面的响应导致。因此我们在程序设计的时候应该做到以下几点避免ANR:
- UI线程只做更新UI的操作;
- 耗时操作应该另起线程处理;
- 使用Handler,AsyncTask或RxJava进行线程间通信;
3.描述android Handler工作机制;
答: 安卓的Handler机制由四个类组成:
- Looper:循环泵,用于循环取出消息队列中的消息;
- Handler:信息处理者,用于发送和接收消息;
- Message:消息载体;
- MessageQueue:消息队列,用于存储消息,先进先出原则。
过程:在线程中,通过Looper在线程中循环,不停而有序的访问MessageQueue,从消息队列中取出Message消息,然后通知Handler,让Handler接收消息并进行处理。而当我们需要往MessageQueue存储消息的时候,需要调用Handler的post方法,利用Handler将消息有序的插入到消息队列中。
4.android service启动方式以及区别;
答:
service一共有两种启动方式:Context.startService()和Context.bindService();
两者存在不同生命周期:
startService:onCreate -> onStartCommand -> onDestroy;
bindService: onCreate -> onBind -> onUnBind -> onDestory;
startService与程序不具有强联系,可以运行在非程序主线程中,也可以运行在其他应用的上下文中,可以不随程序的退出而摧毁,但是较难与程序进行数据交互;bindService与程序存在强联系,需要绑定在组件上,会随着组件生命周期的结束而摧毁,能通过ServiceConnection进行数据交互;
5.android常用控件有哪些;
答:
- TextView;
- ImageView;
- Button;
- RecyclerView;
- ListView;
- RadioButton;
- RadioGroup;
- Progress;
- Spinner;
- EditText;
- CheckBox;
6.android 布局方式有哪些;
答: 主要有以下六种布局:
- LinearLayout;
- RelativeLayout;
- FrameLayout;
- TableLayout;
- CorstraintLayout;
- AbsoluteLayout;(基本已弃用)
7.final finally finalize区别用法
答:
final:java中的关键字,修饰符。
主要用途:
- 定义变量:如果final修饰的是一个基本类型,就表示该变量被赋予的值不可改变,即常量;如果final修饰的是一个对象,则表示该变量被赋予的引用是不可变的,但是对象里面的属性等是可以变的。变量必须初始化。
- 定义方法的参数:与第一种情况相同,指进入方法后的属性在方法中不可变。
- 定义方法:被修饰的方法无法被子类所重写
- 定义类:被修饰的类没有子类,无法被继承。
finally:java的一种异常处理机制。
主要用途:用于try/catch语句中,并且附带一个语句块,表示该语句块不管程序报不报错,最终都将被执行。
finalize:java中的一个方法名。
主要用途:java技术使用finalize()方法,在垃圾收集器将对象从内存清除出去之前,做必要的清理工作。这个方法是由垃圾收集器在对定这个对象没有被应用时对这个对象调用的,会在垃圾收集器删除对象之前对这个对象调用。
8.写一个单例模式
public class Single{
public static Single INSTANCE;
private Single(){};
public Single getInstance(){
//避免多次进入线程锁
if(INSTANCE==null){
//避免两次new的调用
synchronized(Single.class){
//避免第二次以上的new操作
if(INSTANCE==null){
INSTANCE = new Single();
}
}
}
return INSTANCE;
}
}
最简单的单例模式大家都会写,但其实单例模式存在几种改进版的变种,这是目前最好的一种变种(欢迎补充其他更好的方式)。
9.HashMap和HashTable区别;
答:
- 继承的父类不同,但实现了相同的接口:HashMap继承自AbstractMap类;HashTable继承自Dictionary类;但都是实现了Map接口。
- 线程安全性不同:HashMap是线程不安全的,HashTable是线程安全的。
- 是否提供contains方法:HashMap不存在容易被误解的contains方法,而改为containsKey和containsValue两个方法;HashTable则是三个方法共存,其中contains方法与containsValue方法功能相同。
- key和value是否允许null值:HashTable的key和value都不允许null值。而HashMap的key和value则都允许null值。
- 两者的遍历方式的内部实现不同。
- Hash值的使用不同:HashTable直接使用对象的hashCode,而HashMap重新计算hash值。
- 内部实现使用的数组初始化和扩容方式不同:在不指定容量的情况下,HashTable的默认容量较小,为11,而HashMap为16。在扩容时,HashTable一次扩容为原来的两倍加一,而HashMap为原来的两倍。
10.写一个二分算法;
public static int binarySearch(int[] nums, int number) {
return binarySearch(nums, number, 0, nums.length - 1);
}
private static int binarySearch(int[] nums, int number, int beginIndex, int endIndex) {
System.out.println("beginIndex=" + beginIndex + " endIndex=" + endIndex);
if (beginIndex > endIndex) return -1;
int minNumber = (beginIndex + endIndex) / 2;
System.out.println("minNumber=" + minNumber);
if (nums[minNumber] == number) {
return minNumber;
} else if (nums[minNumber] > number) {
return binarySearch(nums, number, beginIndex, minNumber - 1);
} else {
return binarySearch(nums, number, minNumber + 1, endIndex);
}
}