Android复习指南

基础无外乎几部分:语言(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》

上一篇:ajaxSubmit() 上传文件和进度条显示


下一篇:MVC中分页的实现