基础无外乎几部分:语言(C/C++或java),操作系统,TCP/IP,数据结构与算法,再加上你所熟悉的领域。这里面其实有很多东西,各大面试宝典都有列举。
在这只列举了Android客户端所需要的和我面试中所遇到的知识点,尽量做到全面,如果你掌握了以下知识点,去面android客户端应该得心应手。
J2SE基础
1. 九种基本数据类型的大小,以及他们的封装类。
2. Switch能否用string做参数?
3. equals与==的区别。
4. Object有哪些公用方法?
5. Java的四种引用,强弱软虚,用到的场景。
6. Hashcode的作用。
7. ArrayList、LinkedList、Vector的区别。
8. String、StringBuffer与StringBuilder的区别。
9. Map、Set、List、Queue、Stack的特点与用法。
10. HashMap和HashTable的区别。
11. HashMap和ConcurrentHashMap的区别,HashMap的底层源码。
12. TreeMap、HashMap、LindedHashMap的区别。
13. Collection包结构,与Collections的区别。
14. try catch finally,try里有return,finally还执行么?
15. Excption与Error包结构。OOM你遇到过哪些情况,SOF你遇到过哪些情况。
16. Java面向对象的三个特征与含义。
17. Override和Overload的含义去区别。
18. Interface与abstract类的区别。
19. Static class 与non static class的区别。
20. java多态的实现原理。
21. 实现多线程的两种方法:Thread与Runable。
22. 线程同步的方法:sychronized、lock、reentrantLock等。
23. 锁的等级:方法锁、对象锁、类锁。
24. 写出生产者消费者模式。
25. ThreadLocal的设计理念与作用。
26. ThreadPool用法与优势。
27. Concurrent包里的其他东西:ArrayBlockingQueue、CountDownLatch等等。
28. wait()和sleep()的区别。
29. foreach与正常for循环效率对比。
30. Java IO与NIO。
31. 反射的作用于原理。
32. 泛型常用特点,List<String>能否转为List<Object>。
33. 解析XML的几种方式的原理与特点:DOM、SAX、PULL。
34. Java与C++对比。
35. Java1.7与1.8新特性。
36. 设计模式:单例、工厂、适配器、责任链、观察者等等。
37. JNI的使用。
Java里有很多很杂的东西,有时候需要你阅读源码,大多数可能书里面讲的不是太清楚,需要你在网上寻找答案。
推荐书籍:《java核心技术卷I》《Thinking in java》《java并发编程》《effictive java》《大话设计模式》
JVM
1. 内存模型以及分区,需要详细到每个区放什么。
2. 堆里面的分区:Eden,survival from to,老年代,各自的特点。
3. 对象创建方法,对象的内存分配,对象的访问定位。
4. GC的两种判定方法:引用计数与引用链。
5. GC的三种收集方法:标记清除、标记整理、复制算法的原理与特点,分别用在什么地方,如果让你优化收集方法,有什么思路?
6. GC收集器有哪些?CMS收集器与G1收集器的特点。
7. Minor GC与Full GC分别在什么时候发生?
8. 几种常用的内存调试工具:jmap、jstack、jconsole。
9. 类加载的五个过程:加载、验证、准备、解析、初始化。
10. 双亲委派模型:Bootstrap ClassLoader、Extension ClassLoader、ApplicationClassLoader。
11. 分派:静态分派与动态分派。
JVM过去过来就问了这么些问题,没怎么变,内存模型和GC算法这块问得比较多,可以在网上多找几篇博客来看看。
推荐书籍:《深入理解java虚拟机》
操作系统
1. 进程和线程的区别。
2. 死锁的必要条件,怎么处理死锁。
3. Window内存管理方式:段存储,页存储,段页存储。
4. 进程的几种状态。
5. IPC几种通信方式。
6. 什么是虚拟内存。
7. 虚拟地址、逻辑地址、线性地址、物理地址的区别。
因为是做android的这一块问得比较少一点,还有可能上我简历上没有写操作系统的原因。
推荐书籍:《深入理解现代操作系统》
TCP/IP
1. OSI与TCP/IP各层的结构与功能,都有哪些协议。
2. TCP与UDP的区别。
3. TCP报文结构。
4. TCP的三次握手与四次挥手过程,各个状态名称与含义,TIMEWAIT的作用。
5. TCP拥塞控制。
6. TCP滑动窗口与回退N针协议。
7. Http的报文结构。
8. Http的状态码含义。
9. Http request的几种类型。
10. Http1.1和Http1.0的区别
11. Http怎么处理长连接。
12. Cookie与Session的作用于原理。
13. 电脑*问一个网页,整个过程是怎么样的:DNS、HTTP、TCP、OSPF、IP、ARP。
14. Ping的整个过程。ICMP报文是什么。
15. C/S模式下使用socket通信,几个关键函数。
16. IP地址分类。
17. 路由器与交换机区别。
网络其实大体分为两块,一个TCP协议,一个HTTP协议,只要把这两块以及相关协议搞清楚,一般问题不大。
推荐书籍:《TCP/IP协议族》
数据结构与算法
1. 链表与数组。
2. 队列和栈,出栈与入栈。
3. 链表的删除、插入、反向。
4. 字符串操作。
5. Hash表的hash函数,冲突解决方法有哪些。
6. 各种排序:冒泡、选择、插入、希尔、归并、快排、堆排、桶排、基数的原理、平均时间复杂度、最坏时间复杂度、空间复杂度、是否稳定。
7. 快排的partition函数与归并的Merge函数。
8. 对冒泡与快排的改进。
9. 二分查找,与变种二分查找。
10. 二叉树、B+树、AVL树、红黑树、哈夫曼树。
11. 二叉树的前中后续遍历:递归与非递归写法,层序遍历算法。
12. 图的BFS与DFS算法,最小生成树prim算法与最短路径Dijkstra算法。
13. KMP算法。
14. 排列组合问题。
15. 动态规划、贪心算法、分治算法。(一般不会问到)
16. 大数据处理:类似10亿条数据找出最大的1000个数.........等等
算法的话其实是个重点,因为最后都是要你写代码,所以算法还是需要花不少时间准备,这里有太多算法题,写不全,我的建议是没事多在OJ上刷刷题(牛客网、leetcode等),剑指offer上的算法要能理解并自己写出来,编程之美也推荐看一看。
推荐书籍:《大话数据结构》《剑指offer》《编程之美》
Android
1. Activity与Fragment的生命周期。
2. Acitivty的四中启动模式与特点。
3. Activity缓存方法。
4. Service的生命周期,两种启动方法,有什么区别。
5. 怎么保证service不被杀死。
6. 广播的两种注册方法,有什么区别。
7. Intent的使用方法,可以传递哪些数据类型。
8. ContentProvider使用方法。
9. Thread、AsycTask、IntentService的使用场景与特点。
10. 五种布局: FrameLayout 、 LinearLayout 、 AbsoluteLayout 、 RelativeLayout 、 TableLayout 各自特点及绘制效率对比。
11. Android的数据存储形式。
12. Sqlite的基本操作。
13. Android中的MVC模式。
14. Merge、ViewStub的作用。
15. Json有什么优劣势。
16. 动画有哪两类,各有什么特点?
17. Handler、Loop消息队列模型,各部分的作用。
18. 怎样退出终止App。
19. Asset目录与res目录的区别。
20. Android怎么加速启动Activity。
21. Android内存优化方法:ListView优化,及时关闭资源,图片缓存等等。
22. Android中弱引用与软引用的应用场景。
23. Bitmap的四中属性,与每种属性队形的大小。
24. View与View Group分类。自定义View过程:onMeasure()、onLayout()、onDraw()。
25. Touch事件分发机制。
26. Android长连接,怎么处理心跳机制。
27. Zygote的启动过程。
28. Android IPC:Binder原理。
29. 你用过什么框架,是否看过源码,是否知道底层原理。
30. Android5.0、6.0新特性。
Android的话,多是一些项目中的实践,使用多了,自然就知道了,还有就是多逛逛一些名人的博客,书上能讲到的东西不多。另外android底层的东西,有时间的话可以多了解一下,加分项。
推荐书籍:《疯狂android讲义》《深入理解android》
JavaSe基础
1. 九种基本数据类型的大小,以及他们的封装类
boolean 无明确指定 Boolean
char 16bits Character
byte 8bits Byte
short 16bits Short
int 32bits Integer
long 64bits Long
float 32bits Float
double 64bits Double
void Void
2. switch能否用string做参数?
参数必须是int或char那样的整数值 字符串或浮点数不可以
3. equals与==的区别。
4. Object有哪些公用方法?
equals()
getClass()
hashCode()
notify()
5. Java的四种引用,强弱软虚,用到的场景。
强引用
程序代码中普遍存在 类似Object obj = new Object() 这类引用
只要强引用还存在 垃圾回收器永远不会回收掉
软引用
描述一些还有用但非必须的对象 SoftReference
弱引用
描述非必须对象 强度比软引用更弱
垃圾回收器工作时 无论当前内存是否足够 都会回收掉 WeakReference
虚引用
最弱的一种引用关系
设置虚引用的唯一目的就是能在这个对象被收集器回收时收到一个系统通知
6. Hashcode的作用。
Java中的hashCode方法就是根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个数值,这个数值称作为散列值
http://www.cnblogs.com/dolphin0520/p/3681042.html
7. ArrayList、LinkedList、Vector的区别。
ArrayList 随机访问元素较快 插入和移除较慢
LinkedList 随机访问元素较慢 插入和移除较快
Vector 过时 Java1.0/1.1的容器
8. String、StringBuffer与StringBuilder的区别。
String 对象不可变
StringBuffer 线程安全
StringBuilder JavaSE5引入
9. Map、Set、List、Queue、Stack的特点与用法。
Map 一组成对的键值对对象
Set 不保存重复的元素
Queue 先进先出的容器
Stack 后进先出
10. HashMap和Hashtable的区别。
HashMap Map基于散列表的实现 取代了Hashtable 插入和查询键值对的开销是固定的
11. HashMap和ConcurrentHashMap的区别,HashMap的底层源码。
ConcurrentHashMap 一种线程安全的Map 它不涉及同步加锁
12. TreeMap、HashMap、LindedHashMap的区别。
TreeMap 基于红黑树的实现 查看键或键值对时 他们会被排序
HashMap Map基于散列表的实现
LindedHashMap 使用链表维护内部次序
13. Collection包结构,与Collections的区别。
14. try catch finally,try里有return,finally还执行么?
finally子句总是会执行
15. Excption与Error包结构。OOM你遇到过哪些情况,SOF你遇到过哪些情况。
16. Java面向对象的三个特征与含义。
封装
继承
多态
17. Override和Overload的含义去区别。
Override 重写就是子类重写了父类的方法
Overload 重载 同一个类中,允许存在同名函数,但它们的参数个数或者参数类型不同
18. interface与abstract类的区别。
1 接口可以多重继承,抽象类不可以
2 接口定义方法,不给实现 而抽象类可以实现部分方法
3 接口中基本数据类型的数据成员,都默认为static和final 抽象类则不是
19. static class 与non static class的区别。
20. java多态的实现原理。
21. 实现多线程的两种方法:Thread与Runable。
22. 线程同步的方法:sychronized、lock、reentrantLock等。
23. 锁的等级:方法锁、对象锁、类锁。
24. 写出生产者消费者模式。
25. ThreadLocal的设计理念与作用。 线程本地变量 为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量
26. ThreadPool用法与优势。
27. Concurrent包里的其他东西:ArrayBlockingQueue、CountDownLatch等等。
28. wait()和sleep()的区别。
29. foreach与正常for循环效率对比。
30. Java IO与NIO。
31. 反射的作用于原理。
32. 泛型常用特点,List<String>能否转为List<Object>。
33. 解析XML的几种方式的原理与特点:DOM、SAX、PULL。
34. Java与C++对比。
35. Java1.7与1.8新特性。
36. 设计模式:单例、工厂、适配器、责任链、观察者等等。
37. JNI的使用。
Java里有很多很杂的东西,有时候需要你阅读源码,大多数可能书里面讲的不是太清楚,需要你在网上寻找答案。
推荐书籍:《java核心技术卷I》《Thinking in java》《java并发编程》《effictive java》《大话设计模式》
1. 内存模型以及分区,需要详细到每个区放什么。
//运行时数据区域
方法区 Method Area
各个线程共享的内存区域
存储已被虚拟机加载的类信息 常量 静态变量 即时编译器编译后的代码
虚拟机栈 VM Stack
线程私有 Java方法执行的内存模型 每个方法执行的同时会创建一个栈帧 用于存储局部变量表 操作数栈 动态链接 方法出口等信息
每一个方法从调用到执行完成的过程 对应一个栈帧在虚拟机栈中入栈到出栈的过程 局部变量表存放了编译器可知的各种基本数据类型(boolean byte char short int float long double)
对象引用 returnAddress类型
本地方法栈 Native Method Stack
为虚拟机使用的native方法服务
堆 Heap
Java虚拟机所管理内存最大的一块
所有线程共享的一块内存区域 虚拟机启动时创建 存
放所有对象实例及数组 垃圾收集器管理的主要区域 也被称为GC堆
程序计算器 Program Counter Register
当前线程所执行的字节码的行号指示器 线程私有内存
///
运行时产量池
方法区的一部分 用于存放编译期生成的各种字面量和符号引用
直接内存
不是虚拟机运行时数据区的一部分 NIO
2. 堆里面的分区:Eden,survival from to,老年代,各自的特点。
3. 对象创建方法,对象的内存分配,对象的访问定位。
4. GC的两种判定方法:引用计数与引用链。
引用计数算法
给对象添加一个引用计数器 每当有一个地方引用到它时 计数器就加1 引用失效时 计数器就减1 任何时刻计数器为0的对象不可能再被使用
但是很难解决对象之间的相互循环引用的问题
可达性分析算法
通过一系列的GC Roots的对象作为起始点 从这些节点开始向下搜索 所走过的路径称为引用链
当一个对象到GC Roots没有任何引用链相连 则证明此对象不可用
5. GC的三种收集方法:标记清除、标记整理、复制算法的原理与特点,分别用在什么地方,如果让你优化收集方法,有什么思路?
标记清除算法
首先标记处所有需要回收的对象 在标记完成后统一回收
两点不足 一是标记和清除两个过程的效率都不高 二是标记清除后会产生大量不连续的内存碎片
复制算法
将可用内存按容量划分为大小相等的两块 每次只使用其中的一块 当这一块的内存用完了 将还存活着的对象复制到另外一块上面 然后把已经使用内存空间一次清理掉
好处是不用考虑内存碎片 代价是内存缩小为原来的一半
标记整理算法
适合老年代 首先标记处所有需要回收的对象 让所有存活对象都向一端移动 然后直接清理掉端边界以外的内存
分代收集算法
6. GC收集器有哪些?CMS收集器与G1收集器的特点。
Serial收集器
ParNew收集器
Parallel Scavenge收集器
Serial Old收集器
Parallel Old收集器
CMS收集器
一种以获取最短回收停顿时间为目标的收集器 基于标记清除算法实现
优点 并发收集 低停顿 缺点 对CPU资源非常敏感 无法处理浮动垃圾 大量空间碎片产生
G1收集器
面向服务端应用的垃圾收集器 特点 并行和并发 分代收集 空间整合 可预测的停顿
7. Minor GC与Full GC分别在什么时候发生?
8. 几种常用的内存调试工具:jmap、jstack、jconsole。
jmap
内存映像工具
jstack
堆栈跟踪工具
jconsole
监视与管理控制台
9. 类加载的五个过程:加载、验证、准备、解析、初始化。
加载
1 通过一个类的全限定名来获取定义此类的二进制字节流
2 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
3 在内存中生成一个代表这个类的java.lang.Class对象 作为方法区这个类的各种数据的访问入口
验证
确保Class文件的字节流包含的信息符合当前虚拟机的要求
文件格式验证
元数据验证
字节码验证
符合引用验证
准备 正式为类变量分配内存并设置类变量初始值得阶段
解析 将常量池内的符号引用替换为直接引用 类或接口解析 字段解析 类方法解析 接口方法解析
初始化
10. 双亲委派模型:Bootstrap ClassLoader、Extension ClassLoader、ApplicationClassLoader。
Bootstrap ClassLoader 启动类加载器 将JAVA_HOME/lib中类库加载到虚拟机内存中
Extension ClassLoader 扩展类加载器 将JAVA_HOME/lib/ext中类库加载
ApplicationClassLoader 加载用户路径上指定类库
11. 分派:静态分派与动态分派。
JVM过去过来就问了这么些问题,没怎么变,内存模型和GC算法这块问得比较多,可以在网上多找几篇博客来看看。
推荐书籍:《深入理解java虚拟机》
基础3 算法
数据结构与算法
1. 链表与数组。
2. 队列和栈,出栈与入栈。
3. 链表的删除、插入、反向。
4. 字符串操作。
5. Hash表的hash函数,冲突解决方法有哪些。
6. 各种排序:冒泡、选择、插入、希尔、归并、快排、堆排、桶排、基数的原理、平均时间复杂度、最坏时间复杂度、空间复杂度、是否稳定。
7. 快排的partition函数与归并的Merge函数。
8. 对冒泡与快排的改进。
9. 二分查找,与变种二分查找。
10. 二叉树、B+树、AVL树、红黑树、哈夫曼树。
11. 二叉树的前中后续遍历:递归与非递归写法,层序遍历算法。
12. 图的BFS与DFS算法,最小生成树prim算法与最短路径Dijkstra算法。
13. KMP算法。
14. 排列组合问题。
15. 动态规划、贪心算法、分治算法。(一般不会问到)
16. 大数据处理:类似10亿条数据找出最大的1000个数.........等等
算法的话其实是个重点,因为最后都是要你写代码,所以算法还是需要花不少时间准备,这里有太多算法题,写不全,我的建议是没事多在OJ上刷刷题(牛客网、leetcode等),剑指offer上的算法要能理解并自己写出来,编程之美也推荐看一看。
推荐书籍:《大话数据结构》《剑指offer》《编程之美》
常用数据结构
数组 Array 将具有相同类型得若干变量有序的组织在一起的集合
栈 Stack 特殊线性表 只能在表的一个固定端进行数据结点的插入和删除操作 后进先出
队列 Queue 特殊线性表 只能在表的一端进行插入操作 另一端进行删除操作 先进先出
链表 Linked List 一种数据元素安装链式存储结构进行存储的数据结构
树 Tree 非线性结构 包含n个结点的有穷集合K 图 Graph
堆 Heap 特殊的树型数据结构 二叉堆 根结点的值是所有结点中最小或最大的
散列表 Hash 源于散列函数 在结构中存在关键字和T相等的记录 则必定在F(T)的存储位置可以找到该记录
冒泡排序 BubbleSort
思路 相邻元素比较 两两交换 一轮排序结束 最大的元素沉底
复制代码
public class BubbleSort {
static final int SIZE=10;
public static void main(String[] args) {
int[] testArray=new int[SIZE];
//初始化数组 值为随机值
for(int i=0;i<SIZE;i++){
testArray[i]=(int)(100+Math.random()*(100+1));
}
System.out.print("排序前");
printArray(testArray);
bubbleSort(testArray);
System.out.print("排序后");
printArray(testArray);
}
public static void bubbleSort(int[] a) {
int temp;
for (int i = 1; i < a.length; i++) {
//将相邻两个数进行比较,较大的数往后冒泡
for (int j = 0; j < a.length - i; j++) {
if (a[j] > a[j + 1]) {
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
System.out.print("第"+i+"步排序结果:");
printArray(a);
}
}
//打印数组元素
public static void printArray(int[] a){
for (int i = 0; i < a.length; i++) {
System.out.print(" "+a[i]);
}
System.out.print("\n");
}
}
复制代码
输出结果
复制代码
排序前 162 161 117 139 196 107 173 179 132 160
第1步排序结果: 161 117 139 162 107 173 179 132 160 196
第2步排序结果: 117 139 161 107 162 173 132 160 179 196
第3步排序结果: 117 139 107 161 162 132 160 173 179 196
第4步排序结果: 117 107 139 161 132 160 162 173 179 196
第5步排序结果: 107 117 139 132 160 161 162 173 179 196
第6步排序结果: 107 117 132 139 160 161 162 173 179 196
第7步排序结果: 107 117 132 139 160 161 162 173 179 196
第8步排序结果: 107 117 132 139 160 161 162 173 179 196
第9步排序结果: 107 117 132 139 160 161 162 173 179 196
排序后 107 117 132 139 160 161 162 173 179 196
复制代码
选择排序 SelectionSort
思路 选择第1个位置 两两比较元素 让第1一个位置上的元素最小 依次。。。
复制代码
public class SelectionSort {
static final int SIZE = 10;
public static void main(String[] args) {
int[] testArray = new int[SIZE];
// 初始化数组 值为随机值
for (int i = 0; i < SIZE; i++) {
testArray[i] = (int) (100 + Math.random() * (100 + 1));
}
System.out.print("排序前");
printArray(testArray);
selectSort(testArray);
System.out.print("排序后");
printArray(testArray);
}
public static void selectSort(int[] a) {
int index, temp;
for (int i = 0; i < a.length - 1; i++) {
index = i;
for (int j = i + 1; j < a.length; j++) {
if (a[j] < a[index]) {
index = j;
}
}
// 第i个元素是处在大小i的位置上 则不交换 否则交换两个数
if (index != i) {
temp = a[i];
a[i] = a[index];
a[index] = temp;
}
System.out.print("第" + i + "步排序结果:"); // 输出每步排序的结果
printArray(a);
}
}
// 打印数组元素
public static void printArray(int[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(" " + a[i]);
}
System.out.print("\n");
}
}
复制代码
复制代码
排序前 188 180 166 142 197 196 105 120 184 125
第0步排序结果: 105 180 166 142 197 196 188 120 184 125
第1步排序结果: 105 120 166 142 197 196 188 180 184 125
第2步排序结果: 105 120 125 142 197 196 188 180 184 166
第3步排序结果: 105 120 125 142 197 196 188 180 184 166
第4步排序结果: 105 120 125 142 166 196 188 180 184 197
第5步排序结果: 105 120 125 142 166 180 188 196 184 197
第6步排序结果: 105 120 125 142 166 180 184 196 188 197
第7步排序结果: 105 120 125 142 166 180 184 188 196 197
第8步排序结果: 105 120 125 142 166 180 184 188 196 197
排序后 105 120 125 142 166 180 184 188 196 197
复制代码
插入排序 InsertionSort
思路 将数组前两个元素排好 将第3个元素插入到前两个元素中 依次。。。
复制代码
public class InsertionSort {
static final int SIZE = 10;
public static void main(String[] args) {
int[] testArray = new int[SIZE];
// 初始化数组 值为随机值
for (int i = 0; i < SIZE; i++) {
testArray[i] = (int) (100 + Math.random() * (100 + 1));
}
System.out.print("排序前");
printArray(testArray);
selectSort(testArray);
System.out.print("排序后");
printArray(testArray);
}
//插入排序
public static void selectSort(int[] a) {
int i, j, t;
for (i = 1; i < a.length; i++) {
t = a[i]; //需要插入的元素
j = i - 1; //需要插入的位置
while (j >= 0 && t < a[j]) {
a[j + 1] = a[j];
j--;
}
a[j + 1] = t;
System.out.print("第" + i + "步排序结果:"); // 输出每步排序的结果
printArray(a);
}
}
// 打印数组元素
public static void printArray(int[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(" " + a[i]);
}
System.out.print("\n");
}
}
复制代码
复制代码
排序前 111 195 143 198 186 192 137 170 111 141
第1步排序结果: 111 195 143 198 186 192 137 170 111 141
第2步排序结果: 111 143 195 198 186 192 137 170 111 141
第3步排序结果: 111 143 195 198 186 192 137 170 111 141
第4步排序结果: 111 143 186 195 198 192 137 170 111 141
第5步排序结果: 111 143 186 192 195 198 137 170 111 141
第6步排序结果: 111 137 143 186 192 195 198 170 111 141
第7步排序结果: 111 137 143 170 186 192 195 198 111 141
第8步排序结果: 111 111 137 143 170 186 192 195 198 141
第9步排序结果: 111 111 137 141 143 170 186 192 195 198
排序后 111 111 137 141 143 170 186 192 195 198
复制代码
shell排序 ShellSort
思路 将n个元素的数组分成n/2个数字序列 第1个数据和第n/2+1个数据为一对 两两比较交换 再变成n/4个序列。。。
复制代码
public class ShellSort {
static final int SIZE = 10;
public static void main(String[] args) {
int[] testArray = new int[SIZE];
// 初始化数组 值为随机值
for (int i = 0; i < SIZE; i++) {
testArray[i] = (int) (100 + Math.random() * (100 + 1));
}
System.out.print("排序前");
printArray(testArray);
shellSort(testArray);
System.out.print("排序后");
printArray(testArray);
}
public static void shellSort(int[] a) // Shell排序
{
int i, j;
int r, temp;
int x = 0;
for (r = a.length / 2; r >= 1; r /= 2) // 划组排序
{
for (i = r; i < a.length; i++) {
temp = a[i];
j = i - r;
while (j >= 0 && temp < a[j]) {
a[j + r] = a[j];
j -= r;
}
a[j + r] = temp;
}
x++;
System.out.print("第" + x + "步排序结果:"); // 输出每步排序的结果
printArray(a);
}
}
// 打印数组元素
public static void printArray(int[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(" " + a[i]);
}
System.out.print("\n");
}
}
复制代码
排序前 169 128 175 135 191 118 181 128 184 192
第1步排序结果: 118 128 128 135 191 169 181 175 184 192
第2步排序结果: 118 128 128 135 181 169 184 175 191 192
第3步排序结果: 118 128 128 135 169 175 181 184 191 192
排序后 118 128 128 135 169 175 181 184 191 192
快速排序 QuickSort
思路 设定一个分界值 将大于等于分界值得数据集中到数组右边 小于的到左边 递归。。。
复制代码
public class QuickSort {
static final int SIZE = 10;
public static void main(String[] args) {
int[] testArray = new int[SIZE];
// 初始化数组 值为随机值
for (int i = 0; i < SIZE; i++) {
testArray[i] = (int) (100 + Math.random() * (100 + 1));
}
System.out.print("排序前");
printArray(testArray);
quickSort(testArray, 0, SIZE - 1);
System.out.print("排序后");
printArray(testArray);
}
// 快速排序算法
public static void quickSort(int[] arr, int left, int right) {
int f, t;
int rtemp, ltemp;
ltemp = left;
rtemp = right;
f = arr[(left + right) / 2]; // 分界值
while (ltemp < rtemp) {
while (arr[ltemp] < f) {
++ltemp;
}
while (arr[rtemp] > f) {
--rtemp;
}
if (ltemp <= rtemp) {
t = arr[ltemp];
arr[ltemp] = arr[rtemp];
arr[rtemp] = t;
--rtemp;
++ltemp;
}
}
if (ltemp == rtemp) {
ltemp++;
}
if (left < rtemp) {
quickSort(arr, left, ltemp - 1); // 递归调用
}
if (ltemp < right) {
quickSort(arr, rtemp + 1, right); // 递归调用
}
}
// 打印数组元素
public static void printArray(int[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(" " + a[i]);
}
System.out.print("\n");
}
}
复制代码
排序前 158 184 117 192 136 113 116 164 133 123
排序后 113 116 117 123 133 136 158 164 184 192
堆排序 HeapSort
思路 基于堆结构
复制代码
public class HeapSort {
static final int SIZE = 10;
public static void main(String[] args) {
int[] testArray = new int[SIZE];
// 初始化数组 值为随机值
for (int i = 0; i < SIZE; i++) {
testArray[i] = (int) (100 + Math.random() * (100 + 1));
}
System.out.print("排序前");
printArray(testArray);
heapSort(testArray, SIZE);
System.out.print("排序后");
printArray(testArray);
}
// 堆排序
public static void heapSort(int a[], int n) {
int i, j, h, k;
int t;
for (i = n / 2 - 1; i >= 0; i--) // 将a[0,n-1]建成大根堆
{
while (2 * i + 1 < n) // 第i个结点有右子树
{
j = 2 * i + 1;
if ((j + 1) < n) {
if (a[j] < a[j + 1]) // 右左子树小于右子树,则需要比较右子树
j++; // 序号增加1,指向右子树
}
if (a[i] < a[j]) // 比较i与j为序号的数据
{
t = a[i]; // 交换数据
a[i] = a[j];
a[j] = t;
i = j; // 堆被破坏,需要重新调整
} else // 比较左右子结点均大则堆未破坏,不再需要调整
{
break;
}
}
}
// 输出构成的堆
System.out.print("原数据构成的堆:");
for (h = 0; h < n; h++) {
System.out.print(" " + a[h]); // 输出
}
System.out.print("\n");
for (i = n - 1; i > 0; i--) {
t = a[0]; // 与第i个记录交换
a[0] = a[i];
a[i] = t;
k = 0;
while (2 * k + 1 < i) // 第i个结点有右子树
{
j = 2 * k + 1;
if ((j + 1) < i) {
if (a[j] < a[j + 1]) // 右左子树小于右子树,则需要比较右子树
{
j++; // 序号增加1,指向右子树
}
}
if (a[k] < a[j]) // 比较i与j为序号的数据
{
t = a[k]; // 交换数据
a[k] = a[j];
a[j] = t;
k = j; // 堆被破坏,需要重新调整
} else // 比较左右子结点均大则堆未破坏,不再需要调整
{
break;
}
}
System.out.print("第" + (n - i) + "步排序结果:"); // 输出每步排序的结果
printArray(a);
}
}
// 打印数组元素
public static void printArray(int[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(" " + a[i]);
}
System.out.print("\n");
}
}
复制代码
复制代码
排序前 172 146 123 150 164 159 106 189 150 195
原数据构成的堆: 195 189 159 172 164 123 106 150 150 146
第1步排序结果: 189 172 159 150 164 123 106 146 150 195
第2步排序结果: 172 164 159 150 150 123 106 146 189 195
第3步排序结果: 164 150 159 146 150 123 106 172 189 195
第4步排序结果: 159 150 123 146 150 106 164 172 189 195
第5步排序结果: 150 150 123 146 106 159 164 172 189 195
第6步排序结果: 150 146 123 106 150 159 164 172 189 195
第7步排序结果: 146 106 123 150 150 159 164 172 189 195
第8步排序结果: 123 106 146 150 150 159 164 172 189 195
第9步排序结果: 106 123 146 150 150 159 164 172 189 195
排序后 106 123 146 150 150 159 164 172 189 195
复制代码
合并排序 MergeSort
复制代码
public class MergeSort {
static final int SIZE = 15;
static void mergeOne(int a[], int b[], int n, int len) // 完成一遍合并的函数
{
int i, j, k, s, e;
s = 0;
while (s + len < n) {
e = s + 2 * len - 1;
if (e >= n) // 最后一段可能少于len个结点
{
e = n - 1;
}
// 相邻有序段合并
k = s;
i = s;
j = s + len;
while (i < s + len && j <= e) // 如果两个有序表都未结束时,循环比较
{
if (a[i] <= a[j]) // 如果较小的元素复制到数组b中
{
b[k++] = a[i++];
} else {
b[k++] = a[j++];
}
}
while (i < s + len) // 未合并的部分复制到数组b中
{
b[k++] = a[i++];
}
while (j <= e) {
b[k++] = a[j++]; // 未合并的部分复制到数组b中
}
s = e + 1; // 下一对有序段中左段的开始下标
}
if (s < n) // 将剩余的一个有序段从数组A中复制到数组b中
{
for (; s < n; s++) {
b[s] = a[s];
}
}
}
static void mergeSort(int a[], int n) // 合并排序
{
int h, count, len, f;
count = 0; // 排序步骤
len = 1; // 有序序列的长度
f = 0; // 变量f作标志
int[] p = new int[n];
while (len < n) {
if (f == 1) // 交替在A和P之间合并
{
mergeOne(p, a, n, len); // p合并到a
} else {
mergeOne(a, p, n, len); // a合并到p
}
len = len * 2; // 增加有序序列长度
f = 1 - f; // 使f值在0和1之间切换
count++;
System.out.printf("第" + count + "步排序结果:"); // 输出每步排序的结果
for (h = 0; h < SIZE; h++) {
System.out.printf(" " + a[h]); // 输出
}
System.out.print("\n");
}
if (f == 1) // 如果进行了排序
{
for (h = 0; h < n; h++) // 将内存p中的数据复制回数组a
{
a[h] = p[h];
}
}
}
public static void main(String[] args) {
int[] testArray = new int[SIZE];
for (int i = 0; i < SIZE; i++) {
testArray[i] = (int) (100 + Math.random() * (100 + 1)); // 初始化数组
}
System.out.print("排序前的数组为:\n"); // 输出排序前的数组
printArray(testArray);
mergeSort(testArray, SIZE); // 排序操作
System.out.print("排序后的数组为:\n");
printArray(testArray);
}
// 打印数组元素
public static void printArray(int[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(" " + a[i]);
}
System.out.print("\n");
}
}
复制代码
复制代码
排序前的数组为:
180 192 146 174 156 108 116 136 121 142 167 116 159 156 186
第1步排序结果: 180 192 146 174 156 108 116 136 121 142 167 116 159 156 186
第2步排序结果: 146 174 180 192 108 116 136 156 116 121 142 167 156 159 186
第3步排序结果: 146 174 180 192 108 116 136 156 116 121 142 167 156 159 186
第4步排序结果: 108 116 116 121 136 142 146 156 156 159 167 174 180 186 192
排序后的数组为:
108 116 116 121 136 142 146 156 156 159 167 174 180 186 192
复制代码
基础4 Android基础
1. Activity与Fragment的生命周期。
Activity生命周期 onCreate onStart onResume onPause onStop onDestory onRestart
打开应用 onCreate()->onStart()->onResume
按BACK键 onPause()->onStop()->onDestory()
按HOME键 onPause()->onStop()
再次启动 onRestart()->onStart()->onResume()
Fragment的生命周期
切换到该Fragment onAttach() onCreate() onCreateView() onActivityCreated() onStart() onResume()
屏幕灭掉 onPause() onSaveInstanceState() onStop()
屏幕解锁 onStart() onResume()
切换到其他Fragment onPause() onStop() onDestroyView()
切换回本身的Fragment onCreateView() onActivityCreated() onStart() onResume()
回到桌面 onPause() onSaveInstanceState() onStop()
回到应用 onStart() onResume()
退出应用 onPause() onStop() onDestroyView() onDestroy() onDetach()
2. Acitivty的四种启动模式与特点。
当应用运行起来后就会开启一条线程,线程中会运行一个任务栈,当Activity实例创建后就会放入任务栈中 Activity启动模式的设置在AndroidManifest.xml文件中,通过配置Activity的属性android:launchMode=""设置
Standard模式(默认) 只要你创建了Activity实例,一旦激活该Activity,则会向任务栈中加入新创建的实例,退出Activity则会在任务栈中销毁该实例
SingleTop模式 考虑当前要激活的Activity实例在任务栈中是否正处于栈顶,如果处于栈顶则无需重新创建新的实例,会重用已存在的实例,否则会在任务栈中创建新的实例
SingleTask模式 如果任务栈中存在该模式的Activity实例,则把栈中该实例以上的Activity实例全部移除,调用该实例的newInstance()方法重用该Activity,使该实例处於栈顶位置,否则就重新创建一个新的Activity实例
SingleInstance模式 当该模式Activity实例在任务栈中创建后,只要该实例还在任务栈中,即只要激活的是该类型的Activity,都会通过调用实例的newInstance()方法重用该Activity,此时使用的都是同一个Activity实例,它都会处于任务栈的栈顶。 此模式一般用于加载较慢的,比较耗性能且不需要每次都重新创建的Activity
3. Activity缓存方法。
onSaveInstanceState() 和 onRestoreInstanceState()不属于Activity的生命周期,只有意外销毁一个Activity时才被调用,
onSaveInstanceState的调用时机
1 用户按下HOME键
2 长按HOME键,选择运行其他的程序时
3 按下电源按键(关闭屏幕显示)时
4 从activity A中启动一个新的activity时
5 屏幕方向切换时,例如从竖屏切换到横屏时。
onRestoreInstanceState的调用时机
activity A“确实”被系统销毁了,而如果仅仅是停留在有这种可能性的情况下,则该方法不会被调用
下面百度地图应用中的例子,就用到了这两种方法,用来保存和恢复地图的视图。
复制代码
@Override
protected void onSaveInstanceState(Bundle outState) {
cPoint = mapView.getMapCenter(); //得到当前MapView的中心点。
outState.putInt("lat", cPoint.getLatitudeE6()); //暂存在outState中
outState.putInt("lon", cPoint.getLongitudeE6());
super.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
int lat = savedInstanceState.getInt("lat"); //从保存的数据中恢复
int lon = savedInstanceState.getInt("lon");
cPoint = new GeoPoint(lat, lon);
super.onRestoreInstanceState(savedInstanceState);
}
4. Service的生命周期,两种启动方法,有什么区别。
startService 访问者退出 Service仍然允许 onCreate onStartCommand onDestroy
主要用于启动一个服务执行后台任务,不进行通信。停止服务使用stopService
bindService 访问者退出 Service终止onCreate onBind onUnbind onDestroy
该方法启动的服务要进行通信 停止服务使用unbindService
5. 怎么保证service不被杀死。
1 onStartCommand方法,返回START_STICKY
2 提升service优先级 android:priority = "1000"
3 提升service进程优先级
4 onDestroy方法里重启service
6. 广播的两种注册方法,有什么区别。
静态注册 常驻性 应用关闭发广播也会自动启动
<receiver
android:name=".MyReceiver" >
<intent-filter>
<action android:name="android.intent.action.MY_BROADCAST" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
动态注册 退出就关闭
//动态注册
dynamicReceiver = new DynamicReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.intent.action.Dynamic_BROADCAST");
registerReceiver(dynamicReceiver, intentFilter);
Activity或Service被销毁时如果没有解除注册 系统会报异常
//解除注册
@Override
protected void onDestroy() {
super.onDestroy();
//取消注册
unregisterReceiver(dynamicReceiver);
}
7. Intent的使用方法,可以传递哪些数据类型。
putExtra()
基本数据类型 boolean byte char short int long float double
String CharSequence Parcelable Serializable Bundle 数组 集合
8. ContentProvider使用方法。
增删改查
增
// 插入数据
ContentValues contentValues = new ContentValues();
contentValues.put(Media.DISPLAY_NAME, "test");
contentValues.put(Media.DESCRIPTION, "mytest");
contentValues.put(Media.MIME_TYPE, "image/jpeg");
Uri uri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, contentValues);
//真正写入数据
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test);
try {
OutputStream outputStream = getContentResolver().openOutputStream(uri);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
} catch (Exception e) {
}
删
Uri url = Media.EXTERNAL_CONTENT_URI;
// 设置删除条件
String where = Media.DISPLAY_NAME + "=?";
String[] selectionArgs = { "test" };
getContentResolver().delete(url, where, selectionArgs);
改
Uri uri = Media.EXTERNAL_CONTENT_URI;
// 设置更改条件
ContentValues values = new ContentValues();
values.put(Media.DISPLAY_NAME, "hello");
String where = Media.DISPLAY_NAME + "=?";
String[] selectionArgs = { "test" };
getContentResolver().update(uri, values, where, selectionArgs);
查
Cursor cursor = getContentResolver().query(Media.EXTERNAL_CONTENT_URI, null, null, null, null);
while (cursor.moveToNext()) {
byte[] data = cursor.getBlob(cursor.getColumnIndex(Media.DATA)); // 图片的保存位置的数据
fileNames.add(new String(data, 0, data.length - 1));
}
9. Thread、AsycTask、IntentService的使用场景与特点。
Thread 由于UI线程不能执行耗时操作 所以通常在子线程中执行 为了更新UI 通常与Handler一起结合使用
AsycTask 是Thread+Handler的良好封装 简单快捷
IntentService 执行后台耗时的任务 任务执行完自动停止 适合高优先级的后台任务
HandleThread和Handler的封装
Thread 由于UI线程不能执行耗时操作 所以通常在子线程中执行 为了更新UI 通常与Handler一起结合使用
例子
public class MainActivity extends Activity {
ProgressBar progressbar;
public static final int UPDATE_TEXT = 1;
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE_TEXT:
// 在这里可以进行UI操作
progressbar.setProgress(msg.arg1);
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressbar = (ProgressBar) findViewById(R.id.progressbar);
progressbar.setProgress(0);
Button bn = (Button) findViewById(R.id.bn);
bn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
try {
boolean flag = true;
int count = 0;
while (flag) {
// 为了演示进度,休眠100毫秒
Thread.sleep(100);
Log.i("TAG", " -------------------------------count--------------------" + ++count);
Message message = new Message();
message.what = UPDATE_TEXT;
message.arg1 = count;
handler.sendMessage(message); // 将Message对象发送出去
if (count == 100) {
flag = false;
}
}
} catch (Exception e) {
}
}
}).start();
}
});
}
}
AsycTask 是Thread+Handler的良好封装 简单快捷
一个例子
public class MyTask extends AsyncTask<String, Integer, String> {
//Params 启动任务执行的输入参数
//Progress 后台任务执行的进度
//Result 后台计算结果的类型
//1 执行后台任务前做一些UI操作
@Override
protected void onPreExecute() {
super.onPreExecute();
Log.i("TAG", " -------------------------------onPreExecute--------------------" );
progressbar.setProgress(0);
}
//2 执行较为费时的操作 不可操作UI
@Override
protected String doInBackground(String... params) {
Log.i("TAG", " -------------------------------doInBackground----------params[0]----------" + params[0] );
try {
boolean flag = true;
int count = 0;
while (flag) {
//调用publishProgress公布进度,最后onProgressUpdate方法将被执行
publishProgress( count++ );
//为了演示进度,休眠100毫秒
Thread.sleep(100);
Log.i("TAG", " -------------------------------count--------------------" + count);
if (count == 100) {
flag = false;
}
}
} catch (Exception e) {
}
return null;
}
//3 更新进度信息
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
Log.i("TAG", " -------------------------------onProgressUpdate--------------------");
progressbar.setProgress(values[0]);
}
//4 执行完后台任务后更新UI,显示结果
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Log.i("TAG", " -------------------------------onPostExecute--------------------");
Toast.makeText(MainActivity.this, "执行完成", Toast.LENGTH_SHORT).show();
}
@Override
protected void onCancelled() {
super.onCancelled();
Log.i("TAG", " -------------------------------onCancelled--------------------");
progressbar.setProgress(0);
}
}
IntentService 执行后台耗时的任务 任务执行完自动停止 适合高优先级的后台任务
HandleThread和Handler的封装
一个例子
public class MyIntentService extends IntentService{
public MyIntentService( ) {
super("com.example.intentservicetest.MyIntentService");
Log.i("TAG", " -------------------------------MyIntentService--------------------" );
}
@Override
protected void onHandleIntent(Intent intent) {
Log.i("TAG", " -------------------------------onHandleIntent--------------------" );
try {
boolean flag = true;
int count = 0;
while (flag) {
//为了演示进度,休眠100毫秒
Thread.sleep(100);
Log.i("TAG", " -------------------------------count--------------------" + count++);
if (count == 100) {
flag = false;
}
}
} catch (Exception e) {
}
}
@Override
public void onCreate() {
super.onCreate();
Log.i("TAG", " -------------------------------onCreate--------------------" );
}
@Override
public void onDestroy() {
super.onDestroy();
//onHandleIntent中的任务执行完成后 自动执行onDestroy
Log.i("TAG", " -------------------------------onDestroy--------------------" );
}
}
10. 五种布局: FrameLayout 、 LinearLayout 、 AbsoluteLayout 、 RelativeLayout 、 TableLayout 各自特点及绘制效率对比。
FrameLayout 一层层盖上去 摄像机相关的模块会用到
LinearLayout 横着或者竖着依次排列控件 比较常用
AbsoluteLayout 按坐标来布局 基本不用
RelativeLayout 依照与父控件或其它控件的相对位置来布局 比较常用
TableLayout 表格布局 基本不用
11. Android的数据存储形式。
SharedPreference
文件
SQLite
ContentProvider
12. Sqlite的基本操作。
13. Android中的MVC模式。
MVC是三个单词的缩写,分别为: 模型(Model),视图(View)和控制Controller
Model层实现系统中的业务逻辑。 View层用于与用户的交互。 Controller层是Model与View之间沟通的桥梁,
它可以分派用户的请求并选择恰当的视图以用于显示,同时它也可以解释用户的输入并将它们映射为模型层可执行的操作
GridView显示
GridView就是MVC中的View负责显示
获取设备上安装的应用信息所有对应的方法,这就是对应的Model
BaseAdapter,是Model和View中的桥梁,就是 Controller
14. Merge、ViewStub的作用。
<include />标签能够重用布局文件
<merge /> 删减多余的层级
<ViewStub /> 当你需要时才会加载
加载布局时
((ViewStub) findViewById(R.id.stub_import)).setVisibility(View.VISIBLE);
或者
View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();
15. Json有什么优劣势。
JSON的优点:
A.数据格式比较简单,易于读写,格式都是压缩的,占用带宽小;
B.易于解析,客户端JavaScript可以简单的通过eval()进行JSON数据的读取;
C.支持多种语言,包括ActionScript, C, C#, ColdFusion, Java, JavaScript, Perl, PHP, Python, Ruby等服务器端语言,便于服务器端的解析;
D.在PHP世界,已经有PHP-JSON和JSON-PHP出现了,偏于PHP序列化后的程序直接调用,PHP服务器端的对象、数组等能直接生成JSON格式,便于客户端的访问提取;
E.因为JSON格式能直接为服务器端代码使用,大大简化了服务器端和客户端的代码开发量,且完成任务不变,并且易于维护。
JSON的缺点
A.没有XML格式这么推广的深入人心和喜用广泛,没有XML那么通用性;
B.JSON格式目前在Web Service中推广还属于初级阶段。
C 可读性不太好
16. 动画有哪两类,各有什么特点?
一类是Tween动画,就是对场景里的对象不断的进行图像变化来产生动画效果(旋转、平移、放缩和渐变)
alpha 渐变
scale 大小
translate 移动
rotate 旋转
二类就是Frame动画,即顺序的播放事先做好的图像,与gif图片原理类似
http://www.cnblogs.com/bastard/archive/2012/06/29/2570405.html
17. Handler、Loop消息队列模型,各部分的作用。
http://www.cnblogs.com/bastard/archive/2012/06/08/2541944.html
18. 怎样退出终止App。
复制代码
public void exit(){
for (Activity activity : activities) {
if (activity!=null) {
activity.finish();
}
}
System.exit(0);
}
复制代码
19. Asset目录与res目录的区别。
1 assets目录下的资源文件不会在R.java自动生成ID 所以读取assets目录下的文件必须指定文件的路径
2 assets目录能获取子目录下的资源
复制代码
Bitmap bgImg = getImageFromAssetFile( "background.png" );
/**
* 从assets中读取图片
*/
private Bitmap getImageFromAssetsFile(String fileName)
{
Bitmap image = null;
AssetManager am = getResources().getAssets();
try
{
InputStream is = am.open(fileName);
image = BitmapFactory.decodeStream(is);
is.close();
}
catch (IOException e)
{
e.printStackTrace();
}
return image;
}
复制代码
20. Android怎么加速启动Activity。
硬件加速
android:hardwareAccelerated="true"
21. Android内存优化方法:ListView优化,及时关闭资源,图片缓存等等。
22. Android中弱引用与软引用的应用场景。
软引用
描述一些还有用但非必须的对象 SoftReference
弱引用
描述非必须对象 强度比软引用更弱
垃圾回收器工作时 无论当前内存是否足够 都会回收掉 WeakReference
23. Bitmap的四中属性,与每种属性队形的大小。
图片压缩质量参数
枚举变量
public static final Bitmap.Config ALPHA_8
public static final Bitmap.Config ARGB_4444
public static final Bitmap.Config ARGB_8888
public static final Bitmap.Config RGB_565
ARGB指的是一种色彩模式,里面A代表Alpha,R表示red,G表示green,B表示blue,
其实所有的可见色都是红绿蓝组成的,所以红绿蓝又称为三原色,每个原色都存储着所表示颜色的信息值
所以就ALPHA_8就是Alpha由8位组成
ARGB_4444就是由4个4位组成即16位,
ARGB_8888就是由4个8位组成即32位,
RGB_565就是R为5位,G为6位,B为5位共16位
由此可见:
ALPHA_8 代表8位Alpha位图
ARGB_4444 代表16位ARGB位图
ARGB_8888 代表32位ARGB位图
RGB_565 代表8位RGB位图
24. View与View Group分类。自定义View过程:onMeasure()、onLayout()、onDraw()。
25. Touch事件分发机制。
http://www.cnblogs.com/sunzn/archive/2013/05/10/3064129.html
事件分发 dispatchTouchEvent
Touch 事件发生时 Activity 的 dispatchTouchEvent(MotionEvent ev) 方法会以隧道方式
(从根元素依次往下传递直到最内层子元素或在中间某一元素中由于某一条件停止传递)
将事件传递给最外层 View 的 dispatchTouchEvent(MotionEvent ev) 方法,
并由该 View 的 dispatchTouchEvent(MotionEvent ev) 方法对事件进行分发。dispatchTouchEvent 的事件分发逻辑如下:
如果 return true,事件会分发给当前 View 并由 dispatchTouchEvent 方法进行消费,同时事件会停止向下传递;
如果 return false,事件分发分为两种情况:
如果当前 View 获取的事件直接来自 Activity,则会将事件返回给 Activity 的 onTouchEvent 进行消费;
如果当前 View 获取的事件来自外层父控件,则会将事件返回给父 View 的 onTouchEvent 进行消费。
如果返回系统默认的 super.dispatchTouchEvent(ev),事件会自动的分发给当前 View 的 onInterceptTouchEvent 方法。
事件拦截 onInterceptTouchEvent
在外层 View 的 dispatchTouchEvent(MotionEvent ev) 方法返回系统默认的 super.dispatchTouchEvent(ev) 情况下,
事件会自动的分发给当前 View 的 onInterceptTouchEvent 方法。onInterceptTouchEvent 的事件拦截逻辑如下:
如果 onInterceptTouchEvent 返回 true,则表示将事件进行拦截,并将拦截到的事件交由当前 View 的 onTouchEvent 进行处理;
如果 onInterceptTouchEvent 返回 false,则表示将事件放行,当前 View 上的事件会被传递到子 View 上,
再由子 View 的 dispatchTouchEvent 来开始这个事件的分发;
如果 onInterceptTouchEvent 返回 super.onInterceptTouchEvent(ev),事件默认会被拦截,
并将拦截到的事件交由当前 View 的 onTouchEvent 进行处理。
事件响应 onTouchEvent
在 dispatchTouchEvent 返回 super.dispatchTouchEvent(ev) 并且 onInterceptTouchEvent 返回 true
或返回 super.onInterceptTouchEvent(ev) 的情况下 onTouchEvent 会被调用。onTouchEvent 的事件响应逻辑如下:
如果事件传递到当前 View 的 onTouchEvent 方法,而该方法返回了 false,那么这个事件会从当前 View 向上传递,
并且都是由上层 View 的 onTouchEvent 来接收,如果传递到上面的 onTouchEvent 也返回 false,这个事件就会“消失”,而且接收不到下一次事件。
如果返回了 true 则会接收并消费该事件。
如果返回 super.onTouchEvent(ev) 默认处理事件的逻辑和返回 false 时相同。
26. Android长连接,怎么处理心跳机制。
27. Zygote的启动过程。
28. Android IPC:Binder原理。
29. 你用过什么框架,是否看过源码,是否知道底层原理。
30. Android5.0、6.0新特性。
Android的话,多是一些项目中的实践,使用多了,自然就知道了,还有就是多逛逛一些名人的博客,书上能讲到的东西不多。另外android底层的东西,有时间的话可以多了解一下,加分项。
推荐书籍:《疯狂android讲义》《深入理解android》