Android Common Interview Questions

Android-Common-Interview-Questions

面试题总结

##通用

  • 安卓学习途径, 寻找资料学习的博客网站
  • AndroidStudio使用, 插件使用
  • 安卓和苹果的区别

##初级(基础1年左右)

  • 四大组件
  • 五大存储方式
  • Layout布局有哪几种 FrameLayout什么时候用
  • ListView的优化
  • 点击事件设置监听的几种方式
  • 安卓主线程和子线程的关系
  • Activity生命周期 onStart onResume区别
  • Fragment生命周期 Activity和Fragment区别
  • 页面之间如何传递数据, 如果传递一个对象如何处理, 如何传递集合
  • dp px sp的区别
  • gravity和layout_gravity的区别
  • margin和padding的区别
  • weight的作用
  • Handler机制
  • 什么的ANR, 如何避免
  • 显式意图和隐式意图区别,隐式意图的使用
  • 广播几种接收方式, 广播有几种类型, 区别
  • 开启Service的几种方式, 区别, Service和Activity之间如何传递数据
  • Service中如果要start一个Activity要如何特殊处理,为什么

    还有很多,都是网上常见面试题, 百度搜看看, 背下来即可

##中级(2~3年, 也问部分基础问题)

  • 自定义控件
  • 常用开源框架的使用
  • 动画类型
  • 任务栈,页面启动方式
  • Material Design / 新控件RecyclerView CardView等使用
  • 图片压缩和双缓存原理
  • 多层View的onTouch事件分发

    简单了解记下来, 最好自己写个demo试验下

##高级(3年+, 也问部分中级问题)

  • Android绘制原理 onMeasure onLayout onDraw作用
  • MeasureSpec的集中类型区别和作用
  • 自定义控件
  • 什么是MVC MVP,区别
  • 响应式编程
  • 常见开源框架源码
  • 单元测试常用框架和实际使用 场景

    需要阅读源码和项目编码练习

其他

##多媒体

  • 音频的环绕声和混响等如何处理
  • 音频录制播放
  • 视频的录制和播放
  • 播放使用的常用框架
  • Android原生支持格式
  • 软解码硬解码的区别
  • 如果要做一个按住屏幕右侧滑动调整声音功能如何处理

    特殊公司做这方面相关的会问的多

#Android
##一.基础

  1. 四大组件,五大布局.

    • 四大组件:Activity Service ContentProvider BroadCastReceiver
    • 五大布局:线性布局 相对布局 帧布局 表格布局 帧布局
  2. 数据持久化几种方式,都有什么.

    五种方式:文件存储 数据库 SharedPreferences 网络 内容提供者

  3. 有哪些种动画,具体说一下区别.

  4. Activity的生命周期,并说明在Activity的哪个特定时刻会执行哪个特定的方法.要理解透彻

  5. Fragment的生命周期,同上.

  6. Service的生命周期,根据不同的启动方式有不同的生命周期.

  7. ContentProvider的作用是干嘛的,如何使用.

  8. BroadcastReceiver分为几种.Broadcast有几种.

  9. 原生的网络请求是什么.

  10. 原生的数据库是什么.

  11. 请求回来的网络数据如何解析.

  12. ADT/ADB/SDK/ANR/OOM都是什么意思.

  13. 当前的SDK最高版本是多少,AS的版本是多少.

  14. 6.0与7.0均新加的什么特性.

  15. AS的常用快捷键.

  16. 什么情况下会导致ANR,如何避免.

  17. ListView的运行机制.

  18. 适配器的优化方式,适配器几个方法的意义.

  19. ListView如何加载不同的行布局.

  20. 如何解决和避免内存泄露.

  21. 横竖屏切换的时候Activity会重新加载布局,那么数据如何保存.

  22. 你常用哪种Http请求方式.(Post和Get),二者的区别.

  23. 简述Http,TCP/IP,Socket三者的关系.

  24. 说一下你所了解的网络请求框架,都有什么.他们之间的区别.

  25. Volley的基本使用方法,封装原则.

  26. 项目中你是如何使用Volley的,是否对Request类进行了重写.

  27. Volley能不能进行同步的网络请求,如果可以,怎么做.

  28. Volley加载图片的方法用过没有,图片的缓存是如何实现的.

  29. OkHttp的使用方式.与Volley有何不同.

  30. OkHttp如何下载文件,Volley能不能下载.

  31. 大文件的下载过程你一般是如何做的.

  32. 用过Retrofit么,对它进行一下简单的介绍,包括使用方式.

  33. 你是如何进行数据库的操作的.

  34. 图片你是如何加载的.

  35. design包下的控件都使用过什么.

  36. 知道材料设计(material design)么.

  37. Fragment有几种使用方式.

  38. Serializable 和 Parcelable的联系和区别.

  39. 如何将Activity设置为窗口模式.

##二.进阶

  1. 简述Handler机制的原理.

  2. 说一下事件分发机制.

  3. View的绘制过程.

  4. 都有哪些方式可以实现进程间通信.

  5. 代码混淆是干嘛的.

  6. gradle是干嘛的.

  7. 关于内存优化,你都做过什么.

  8. Activity的启动方式.

  9. ActivityA启动了ActivityB,那么A的onPause()方法和B的onCreate()方法谁先执行.

  10. Fragment与宿主Activity进行通信,有哪些方式,请说明.

  11. 一般来说,一个应用程序一共有多少个Context.

    Context的个数等于Activity的个数 + Service个数 + 1 (Application也是Context)

  12. 如何一次性退出所有的Activity,有哪些解决方案.

Java面试题

##一.基础

  1. Java面向对象的三大特性,并说出你的理解.

  2. Collection和Collections有什么区别.

    Collection是一个集合接口,它提供了对集合对象进行基本糙所的通用接口方法.Collection接口在Java类库中有很多具体的实现,例如LinkedList Set等;

    Collections是一个包装类它包含有各种有关集合操作的静态多态方法。此类不能实例化,是一个工具类,有类似排序等功能,服务于Java的Collection框架。

  3. 抽象类与接口的区别.

    抽象类可以有构造方法 接口不行

    抽象类可以有普通成员变量 接口没有

    抽象类可以有非抽象的方法 接口必须全部抽象

    抽象类的访问类型都可以 接口只能是 public abstract

    一个类可以实现多个接口 但只能继承一个抽象类

  4. 类能不能多继承类,能不能多实现接口.接口能不能多继承接口,接口能不能实现接口.

    一个类只能继承一个类,但是可以实现多个接口;

    一个接口可以继承多个接口,但是不能实现接口

  5. 重写(覆写)与重载的区别.

    • 重写是子类对父类的函数进行重新定义,即子类中定义的方法与其父类具有相同的方法名和参数,重写的时候子类不能函数的访问权限不能少于父类的
    • 重载(Overloading)是 是在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义。调用方法时通过传递给它们的不同参数个数和参数类型来决定具体使用哪个方法, 这就是多态性。
  6. 构造方法能不能被覆写.

  7. 覆写父类的方法,方法的哪个组成部分可以不同.

  8. 能不能继承String类.

    不能,String是final类型的,不能被继承

  9. String/StringBuffer/StringBuilder的区别.

  10. final/finally/finalize的区别.

  • final 用于声明属性,方法和类, 分别表示属性不可变, 方法不可覆盖, 类不可继承.
  • finally 是异常处理语句结构的一部分,表示总是执行该代码块
    • finalize 是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等. JVM不保证此方法总被调用.
  1. throw与throws的作用.

  2. try…catch…finally语句块的用法,哪部分可以省略.

  3. 数据流的分类,常用的数据流.

  4. 基本概念,JDK/JRE/JVM

    • JDK Java Development Kit Java开发包.包含JRE和Java的常用类库.

    • JRE Java Runtime Environment Java运行时环境.可以单独在Oracle官网下载,运行Java程序必须安装.

    • JVM Java Virtual Machine Java虚拟机.Oracle官网不提供单独下载,集成在JRE中.Java程序最终运行在JVM中.
      在搭建环境时,只需要安装JDK即可.

  5. 内部类与静态内部类有什么区别.

  6. switch能否作用在byte/char/long/String上.

  7. toString/equals/hashCode分别是谁的方法,一般用来干嘛.

  8. Java中如何退出多重循环.

  • 如下所示:
    // 标记双重循环开始的位置
    ABC:
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
            // 在某个时刻结束双重循环
            break ABC;    
        }
    }
  1. 实例方法可不可以访问静态属性,静态方法可不可以访问实例属性.

##二.进阶

  1. Java中Class类是用来干嘛的.

  2. 说一下反射可以干什么.

  3. 开启线程有几种方式,线程池的执行原理.

  4. Java中存在几种引用的方式.

    • 强引用:如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。

    • 软引用:如果一个对象具有软引用,内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。SoftReference的特点是它的一个实例保存对一个Java对象的软引用, 该软引用的存在不妨碍垃圾收集线程对该Java对象的回收。

    • 弱引用:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它 所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。

    • 虚引用:如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。虚引用主要用来跟踪对象被垃圾回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用。

      引用类型 被GC回收时间 用途 生存时间
      强引用 从来不会 对象的一般形态 JVM停止运行时
      软引用 内存不足时 对象缓存 内存不足时终止
      弱引用 在GC运行时 对象缓存 GC运行后停止
  5. Java的垃圾回收机制.

  6. 存在继承关系时,子类与父类构造方法的调用顺序.

  7. Error与Exception有什么区别.

  8. List/Set/Map三者的区别.

  9. 如何比较两个对象的大小.或者换句话说,如何让对象之间有可比性.

  10. 面向对象的六大原则.

  11. 简述一下你了解的设计模式.

  12. 单例模式什么情况下会失效.

  13. 内存泄露与内存溢出.


Android面试题

  1. 什么是数据结构?
    数据结构是一门研究非数值计算的程序设计问题中的操作对象,以及它们之间的关系和操作等相关问题的学科.
    程序设计 = 数据结构 + 算法
    传统上,我们把数据结构分为逻辑结构和物理结构。
    逻辑结构:是指数据对象中数据元素之间的相互关系,也是我们今后最需要关注和讨论的问题。
    {

    集合结构(仅仅同属一个集合),线性结构(一对一的关系), 树形结构(一对多的层次关系), 图形结构(多对多的关系)

    }
    物理结构:是指数据的逻辑结构在计算机中的存储形式。

    顺序存储:是把数据元素存放在地址连续的存储单元里,其数据间的逻辑关系和物理关系是一致的。例如我们编程语言的数组结构就是这样滴。
    链式存储:是把数据元素存放在任意的存储单元里,这组存储单元可以是连续的,也可以是不连续的。(因此需要用一个指针存放数据元素的地址,这样子通过地址就可以找到相关联数据元素的位置。)

  2. 算法
    算法是解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每条指令表示一个或多个操作。

    算法的特征:输入、输出、有穷性、确定性和可行性。
    输入:算法具有零个或多个输入。
    输出:算法至少有一个或多个输出。
    有穷性:指算法在执行有限的步骤之后,自动结束而不会出现无限循环,并且每一个步骤在可接受的时间内完成。
    确定性:算法的每一个步骤都具有确定的含义,不会出现二义性。
    可行性:算法的每一步都必须是可行的,也就是说,每一步都能够通过执行有限次数完成。

    算法设计的要求:
    正确性:算法的正确性是指算法至少应该具有输入、输出和加工处理无歧义性、能正确反映问题的需求、能够得到问题的正确答案。
    大体分为以下四个层次:
    算法程序没有语法错误。
    算法程序对于合法输入能够产生满足要求的输出。
    算法程序对于非法输入能够产生满足规格的说明。
    算法程序对于故意刁难的测试输入都有满足要求的输出结果。
    可读性:算法设计另一目的是为了便于阅读、理解和交流。
    健壮性:当输入数据不合法时,算法也能做出相关处理,而不是产生异常、崩溃或莫名其妙的结果。
    时间效率高和存储量低:
    3. 时间复杂度和空间复杂度

    int i, sum = 0, n = 100;   // 执行1次
    for( i=1; i <= n; i++ )    // 执行了n+1次
    {
       	sum = sum + i;         // 执行n次
    }
    int sum = 0, n = 100;     // 执行1次
    sum = (1+n)*n/2;          // 执行1次

    第一种算法执行了1+(n+1)+n=2n+2次。
    第二种算法,是1+1=2次
    我们研究算法的复杂度,侧重的是研究算法随着输入规模扩大增长量的一个抽象,而不是精确地定位需要执行多少次。
    我们在分析一个算法的运行时间时,重要的是把基本操作的数量和输入模式关联起来。
    函数的渐近增长:给定两个函数f(n)和g(n),如果存在一个整数N,使得对于所有的n>N,f(n)总是比g(n)大。那么,我们说f(n)的增长渐近快于g(n)。
    判断一个算法的效率时,函数中的常数和其他次要项常常可以忽略,而更应该关注主项(最高项)的阶数。
    算法时间复杂度的定义:在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定T(n)的数量级。
    算法的时间复杂度,也就是算法的时间量度,记作:T(n)= O(f(n))。
    它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐近时间复杂度,简称为时间复杂度。其中f(n)是问题规模n的某个函数。
    这样用大写O()来体现算法时间复杂度的记法,我们称之为大O记法。
    一般情况下,随着输入规模n的增大,T(n)增长最慢的算法为最优算法。
    显然,由此算法时间复杂度的定义可知,我们的三个求和算法的时间复杂度分别为O(1),O(n),O(n^2)。

    推导大O阶方法:
    用常数1取代运行时间中的所有加法常数。
    在修改后的运行次数函数中,只保留最高阶项。
    如果最高阶项存在且不是1,则去除与这个项相乘的常数。
    得到的最后结果就是大O阶。
    线性阶:一般含有非嵌套循环涉及线性阶,线性阶就是随着问题规模n的扩大,对应计算次数呈直线增长。
    平方阶:
    对数阶:
    在应用中,这是一种最重要的需求,通常除非特别指定,我们提到的运行时间都是最坏情况的运行时间。

    算法的空间复杂度:
    算法的空间复杂度通过计算算法所需的存储空间实现,算法的空间复杂度的计算公式记作:S(n)=O(f(n)),其中,n为问题的规模,f(n)为语句关于n所占存储空间的函数。

  3. 线性表
    线性表(List):由零个或多个数据元素组成的有限序列。
    首先它是一个序列,也就是说元素之间是有个先来后到的
    若元素存在多个,则第一个元素无前驱,而最后一个元素无后继,其他元素都有且只有一个前驱和后继。
    另外,线性表强调是有限的,事实上无论计算机发展到多强大,它所处理的元素都是有限的。
    若将线性表记为(a1,…,ai-1,ai,ai+1,…an),则表中ai-1领先于ai,ai领先于ai+1,称ai-1是ai的直接前驱元素,ai+1是ai的直接后继元素。
    所以线性表元素的个数n(n>=0)定义为线性表的长度,当n=0时,称为空表。

    第一个元素无前驱,而最后一个元素无后继,其他元素都有且只有一个前驱和后继。

    数据类型:是指一组性质相同的值的集合及定义在此集合上的一些操作的总称。
    {

    原子类型:不可以再分解的基本类型,例如整型、浮点型、字符型等。
    结构类型:由若干个类型组合而成,是可以再分解的,例如整型数组是由若干整型数据组成的。

    }
    抽象:是指抽取出事物具有的普遍性的本质。它要求抽出问题的特征而忽略非本质的细节,是对具体事物的一个概括。抽象是一种思考问题的方式,它隐藏了繁杂的细节。
    我们对已有的数据类型进行抽象,就有了抽象数据类型。
    抽象数据类型(Abstract Data Type,ADT)是指一个数学模型及定义在该模型上的一组操作。
    抽象数据类型的定义仅取决于它的一组逻辑特性,而与其在计算机内部如何表示和实现无关。
    “抽象”的意义在于数据类型的数学抽象特性。
    描述抽象数据类型的标准格式:
    ADT 抽象数据类型名
    Data
    数据元素之间逻辑关系的定义

    Operation

    操作
    endADT

    所谓抽象数据类型就是把数据类型和相关操作捆绑在一起。
    总结下,顺序存储结构封装需要三个属性:
    存储空间的起始位置,数组data,它的存储位置就是线性表存储空间的存储位置。
    线性表的最大存储容量:数组的长度MaxSize。
    线性表的当前长度:length。

    数组的长度是存放线性表的存储空间的总长度,一般初始化后不变。
    而线性表的当前长度是线性表中元素的个数,是会变化的。

    线性表顺序存储结构的优缺点:
    线性表的顺序存储结构,在存、读数据时,不管是哪个位置,时间复杂度都是O(1)。而在插入或删除时,时间复杂度都是O(n)。
    优点:
    无须为表示表中元素之间的逻辑关系而增加额外的存储空间。
    可以快速地存取表中任意位置的元素。
    缺点:
    插入和删除操作需要移动大量元素。
    当线性表长度变化较大时,难以确定存储空间的容量。
    容易造成存储空间的“碎片”。

    线性表链式存储结构定义:
    线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素,这组存储单元可以存在内存中未被占用的任意位置。比起顺序存储结构每个数据元素只需要存储一个位置就可以了。
    单链表:
    现在链式存储结构中,除了要存储数据元素信息外,还要存储它的后继元素的存储地址(指针)。
    也就是说除了存储其本身的信息外,还需存储一个指示其直接后继的存储位置的信息。
    我们把存储数据元素信息的域称为数据域,把存储直接后继位置的域称为指针域。
    指针域中存储的信息称为指针或链。
    这两部分信息组成数据元素称为存储映像,称为结点(Node)。
    n个结点链接成一个链表,即为线性表(a1, a2, a3, …, an)的链式存储结构。
    因为此链表的每个结点中只包含一个指针域,所以叫做单链表。
    我们把链表中的第一个结点的存储位置叫做头指针,最后一个结点指针为空(NULL)。

    头指针是指链表指向第一个结点的指针,若链表有头结点,则是指向头结点的指针。
    头指针具有标识作用,所以常用头指针冠以链表的名字(指针变量的名字)。
    无论链表是否为空,头指针均不为空。
    头指针是链表的必要元素。

    头结点是为了操作的统一和方便而设立的,放在第一个元素的结点之前,其数据域一般无意义(但也可以用来存放链表的长度)。
    有了头结点,对在第一元素结点前插入结点和删除第一结点起操作与其它结点的操作就统一了。
    头结点不一定是链表的必须要素。
    获得链表第i个数据的算法思路:
    声明一个结点p指向链表第一个结点,初始化j从1开始;
    当j<i时,就遍历链表,让p的指针向后移动,不断指向一下结点,j+1;
    若到链表末尾p为空,则说明第i个元素不存在;
    否则查找成功,返回结点p的数据。
    其核心思想叫做“工作指针后移”,这其实也是很多算法的常用技术。
    单链表的插入:s->next = p->next;p->next = s;
    单链表第i个数据插入结点的算法思路:
    声明一结点p指向链表头结点,初始化j从1开始;
    当j<1时,就遍历链表,让p的指针向后移动,不断指向下一结点,j累加1;
    若到链表末尾p为空,则说明第i个元素不存在;
    否则查找成功,在系统中生成一个空结点s;
    将数据元素e赋值给s->data;
    单链表的插入刚才两个标准语句;
    返回成功。
    单链表的删除:
    可以这样:p->next = p->next->next;
    也可以是:q=p->next; p->next=q->next;
    单链表第i个数据删除结点的算法思路:
    声明结点p指向链表第一个结点,初始化j=1;
    当j<1时,就遍历链表,让P的指针向后移动,不断指向下一个结点,j累加1;
    若到链表末尾p为空,则说明第i个元素不存在;
    否则查找成功,将欲删除结点p->next赋值给q;
    单链表的删除标准语句p->next = q->next;
    将q结点中的数据赋值给e,作为返回;
    释放q结点。
    效率PK:
    我们最后的环节是效率PK,我们发现无论是单链表插入还是删除算法,它们其实都是由两个部分组成:第一部分就是遍历查找第i个元素,第二部分就是实现插入和删除元素。
    从整个算法来说,我们很容易可以推出它们的时间复杂度都是O(n)。
    再详细点分析:如果在我们不知道第i个元素的指针位置,单链表数据结构在插入和删除操作上,与线性表的顺序存储结构是没有太大优势的。
    但如果,我们希望从第i个位置开始,插入连续10个元素,对于顺序存储结构意味着,每一次插入都需要移动n-i个位置,所以每次都是O(n)。
    而单链表,我们只需要在第一次时,找到第i个位置的指针,此时为O(n),接下来只是简单地通过赋值移动指针而已,时间复杂度都是O(1)。
    显然,对于插入或删除数据越频繁的操作,单链表的效率优势就越是明显啦~
    单链表整表创建的算法思路如下:
    声明一结点p和计数器变量i;
    初始化一空链表L;
    让L的头结点的指针指向NULL,即建立一个带头结点的单链表;
    循环实现后继结点的赋值和插入。
    头插法建立单链表:头插法从一个空表开始,生成新结点,读取数据存放到新结点的数据域中,然后将新结点插入到当前链表的表头上,直到结束为止。
    简单来说,就是把新加进的元素放在表头后的第一个位置:
    先让新节点的next指向头节点之后
    然后让表头的next指向新节点
    尾插法建立单链表:
    头插法建立链表虽然算法简单,但生成的链表中结点的次序和输入的顺序相反。
    就像现实社会我们鄙视插队不遵守纪律的孩子,那编程中我们也可以不这么干,我们可以把思维逆过来:把新结点都插入到最后,这种算法称之为尾插法。

    单链表整表删除的算法思路如下:
    声明结点p和q;
    将第一个结点赋值给p,下一结点赋值给q;
    循环执行释放p和将q赋值给p的操作;

    单链表结构与顺序存储结构优缺点:
    存储分配方式:
    顺序存储结构用一段连续的存储单元依次存储线性表的数据元素。
    单链表采用链式存储结构,用一组任意的存储单元存放线性表的元素。
    时间性能:
    查找
    顺序存储结构O(1)
    单链表O(n)
    插入和删除
    顺序存储结构需要平均移动表长一半的元素,时间为O(n)
    单链表在计算出某位置的指针后,插入和删除时间仅为O(1)
    空间性能:
    顺序存储结构需要预分配存储空间,分大了,容易造成空间浪费,分小了,容易发生溢出。
    单链表不需要分配存储空间,只要有就可以分配,元素个数也不受限制。
    结论:
    若线性表需要频繁查找,很少进行插入和删除操作时,宜采用顺序存储结构。
    若需要频繁插入和删除时,宜采用单链表结构。
    比如说游戏开发中,对于用户注册的个人信息,除了注册时插入数据外,绝大多数情况都是读取,所以应该考虑用顺序存储结构。
    而游戏中的玩家的武器或者装备列表,随着玩家的游戏过程中,可能会随时增加或删除,此时再用顺序存储就不太合适了,单链表结构就可以大展拳脚了。
    当线性表中的元素个数变化较大或者根本不知道有多大时,最好用单链表结构,这样可以不需要考虑存储空间的大小问题。
    而如果事先知道线性表的大致长度,比如一年12个月,一周就是星期一至星期日共七天,这种用顺序存储结构效率会高很多。
    快速找到未知长度单链表的中间节点?
    既然是面试题就一定有普通方法和高级方法,而高级方法无疑会让面试官大大加分!
    普通的方法很简单,首先遍历一遍单链表以确定单链表的长度L。然后再次从头节点出发循环L/2次找到单链表的中间节点。
    算法复杂度为:O(L+L/2)=O(3L/2)。
    能否再优化一下这个时间复杂度呢?
    有一个很巧妙的方法:利用快慢指针!
    利用快慢指针原理:设置两个指针search、*mid都指向单链表的头节点。其中 search的移动速度是mid的2倍。当search指向末尾节点的时候,mid正好就在中间了。这也是标尺的思想。

    将单链表中终端结点的指针端由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相接的单链表成为单循环链表,简称循环链表。
    判断单链表中是否有环
    有环的定义是,链表的尾节点指向了链表中的某个节点。
    方法一:使用p、q两个指针,p总是向前走,但q每次都从头开始走,对于每个节点,看p走的步数是否和q一样。如图,当p从6走到3时,用了6步,此时若q从head出发,则只需两步就到3,因而步数不等,出现矛盾,存在环。
    方法二:使用p、q两个指针,p每次向前走一步,q每次向前走两步,若在某个时候p == q,则存在环。

双向链表的插入操作
插入操作其实并不复杂,不过顺序很重要,千万不能写反了。
s->next = p;
s->prior = p->prior;
p->prior->next = s;
p->prior = s;
双向链表的删除操作
p->prior->next = p->next;
p->next->prior = p->prior;
free(p);
双向链表相对于单链表来说,是要更复杂一点,每个结点多了一个prior指针,对于插入和删除操作的顺序大家要格外小心。不过,双向链表可以有效提高算法的时间性能,说白了就是用空间来换取时间。
栈是一种重要的线性结构,可以这样讲,栈是前面讲过的线性表的一种具体形式。
清空一个栈
所谓清空一个栈,就是将栈中的元素全部作废,但栈本身物理空间并不发生改变(不是销毁)。
因此我们只要将s->top的内容赋值为s->base即可,这样s->base等于s->top,也就表明这个栈是空的了。
这个原理跟高级格式化只是但单纯地清空文件列表而没有覆盖硬盘的原理是一样的。
ClearStack(sqStack s)
{
s->top = s->base;
}
销毁一个栈
销毁一个栈与清空一个栈不同,销毁一个栈是要释放掉该栈所占据的物理内存空间,因此不要把销毁一个栈与清空一个栈这两种操作混淆。
DestroyStack(sqStack s)
{
int i, len;
len = s->stackSize;
for( i=0; i < len; i++ )
{
free( s->base );
s->base++;
}
s->base = s->top = NULL;
s->stackSize = 0;
}
计算栈的当前容量
计算栈的当前容量也就是计算栈中元素的个数,因此只要返回s.top-s.base即可。
注意,栈的最大容量是指该栈占据内存空间的大小,其值是s.stackSize,它与栈的当前容量不是一个概念哦。
int StackLen(sqStack s)
{
return(s.top – s.base); // 初学者需要重点讲解
}
逆波兰计算
逆波兰表达式
a+b —> a b +
a+(b-c) —> a b c – +
a+(b-c)
d —> a b c – d * +
a+d
(b-c)—> a d b c – * +
队列的链式存储结构
我们将队头指针指向链队列的头结点,而队尾指针指向终端结点。(注:头结点不是必要的,但为了方便操作,我们加上了。)
空队列时,front和rear都指向头结点。
创建一个队列
创建一个队列要完成两个任务:一是在内存中创建一个头结点,二是将队列的头指针和尾指针都指向这个生成的头结点,因为此时是空队列。
入队列操作
InsertQueue(LinkQueue *q, ElemType e)
{
QueuePtr p;

    p = (QueuePtr)malloc(sizeof(QNode));
    if( p == NULL )
        exit(0);

    p->data = e;
    p->next = NULL;
    q->rear->next = p;
    q->rear = p;
}
出队列操作
出队列操作是将队列中的第一个元素移出,队头指针不发生改变,改变头结点的next指针即可。
DeleteQueue(LinkQueue *q, ELemType *e)
{
    QueuePtr p;

    if( q->front == q->rear )
        return;

    p = q->front->next;
    *e = p->data;
    q->front->next = p->next;

    if( q->rear == p )
        q->rear = q->front;

    free(p);
}
销毁一个队列
由于链队列建立在内存的动态区,因此当一个队列不再有用时应当把它及时销毁掉,以免过多地占用内存空间。
DestroyQueue(LinkQueue *q)
{
    while( q->front )
    {
        q->rear = q->front->next;
        free( q->front );
        q->front = q->rear;
    }
}
树结构
树(Tree)是n(n>=0)个结点的有限集。当n=0时成为空树,在任意一棵非空树中:
有且仅有一个特定的称为根(Root)的结点;
当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1、T2、…、Tm,其中每一个集合本身又是一棵树,并且称为根的子树(SubTree)。

虽然从概念上很容易理解树,但是有两点还是需要大家注意下:
n>0时,根结点是唯一的,坚决不可能存在多个根结点。
m>0时,子树的个数是没有限制的,但它们互相是一定不会相交的。

结点分类
刚才所有图片中,每一个圈圈我们就称为树的一个结点。
结点拥有的子树数称为结点的度-(Degree),树的度取树内各结点的度的最大值。
度为0的结点称为叶结点(Leaf)或终端结点;
度不为0的结点称为分支结点或非终端结点,除根结点外,分支结点也称为内部结点。

树中结点的最大层次称为树的深度(Depth)或高度。

二叉树的特点
每个结点最多有两棵子树,所以二叉树中不存在度大于2的结点。(注意:不是都需要两棵子树,而是最多可以是两棵,没有子树或者有一棵子树也都是可以的。)
左子树和右子树是有顺序的,次序不能颠倒。
即使树中某结点只有一棵子树,也要区分它是左子树还是右子树,
二叉树的性质一:在二叉树的第i层上至多有2^(i-1)个结点(i>=1)
二叉树的性质二:深度为k的二叉树至多有2^k-1个结点(k>=1)
二叉树的性质三:对任何一棵二叉树T,如果其终端结点数为n0,度为2的结点数为n2,则n0=n2+1
首先我们再假设度为1的结点数为n1,则二叉树T的结点总数n=n0+n1+n2
其次我们发现连接数总是等于总结点数n-1,并且等于n1+2n2
所以n-1=n1+2
n2
所以n0+n1+n2-1=n1+n2+n2
最后n0=n2+1
二叉树的性质四:具有n个结点的完全二叉树的深度为⌊log₂n⌋+1
二叉树的性质五:如果对一棵有n个结点的完全二叉树(其深度为⌊log₂n⌋+1)的结点按层序编号,对任一结点i(1<=i<=n)有以下性质:
如果i = 1,则结点 i 是二叉树的根,无双亲;如果i > 1,则其双亲是结点⌊i/2⌋
如果2i > n,则结点 i 无做左孩子(结点 i 为叶子结点);否则其左孩子是结点2i
如果2i+1 > n,则结点 i 无右孩子;否则其右孩子是结点2i+1

    既然顺序存储方式的适用性不强,那么我们就要考虑链式存储结构啦。二叉树的存储按照国际惯例来说一般也是采用链式存储结构的。

二叉树每个结点最多有两个孩子,所以为它设计一个数据域和两个指针域是比较自然的想法,我们称这样的链表叫做二叉链表。
    typedef struct BiTNode
{
    ElemType data;
    struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
二叉树的遍历方式可以很多,如果我们限制了从左到右的习惯方式,那么主要就分为一下四种:
前序遍历
    若二叉树为空,则空操作返回,否则先访问根结点,然后前序遍历左子树,再前序遍历右子树。
中序遍历
    若树为空,则空操作返回,否则从根结点开始(注意并不是先访问根结点),中序遍历根结点的左子树,然后是访问根结点,最后中序遍历右子树。
后序遍历
    若树为空,则空操作返回,否则从左到右先叶子后结点的方式遍历访问左右子树,最后访问根结点。
层序遍历
    若树为空,则空操作返回,否则从树的第一层,也就是根结点开始访问,从上而下逐层遍历,在同一层中,按从左到右的顺序对结点逐个访问。

赫夫曼树定义与原理
    我们先把这两棵二叉树简化成叶子结点带权的二叉树(注:树结点间的连线相关的数叫做权,Weight)。
    结点的路径长度:从根结点到该结点的路径上的连接数。
    树的路径长度:树中每个叶子结点的路径长度之和。
    结点带权路径长度:结点的路径长度与结点权值的乘积。
    WPL的值越小,说明构造出来的二叉树性能越优。
名词解释:定长编码,变长编码,前缀码
定长编码:像ASCII编码
变长编码:单个编码的长度不一致,可以根据整体出现频率来调节
前缀码:所谓的前缀码,就是没有任何码字是其他码字的前缀
图的定义
    图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。
对于图的定义,我们需要明确几个注意的地方:
    线性表中我们把数据元素叫元素,树中叫结点,在图中数据元素我们则称之为顶点(Vertex)。
    线性表可以没有数据元素,称为空表,树中可以没有结点,叫做空树,而图结构在咱国内大部分的教材中强调顶点集合V要有穷非空。
    线性表中,相邻的数据元素之间具有线性关系,树结构中,相邻两层的结点具有层次关系,而图结构中,任意两个顶点之间都可能有关系,顶点之间的逻辑关系用边来表示,边集可以是空的。
无向边:若顶点Vi到Vj之间的边没有方向,则称这条边为无向边(Edge),用无序偶(Vi,Vj)来表示。
有向边:若从顶点Vi到Vj的边有方向,则称这条边为有向边,也成为弧(Arc),用有序偶<Vi,Vj>来表示,Vi称为弧尾,Vj称为弧头。
简单图:在图结构中,若不存在顶点到其自身的边,且同一条边不重复出现,则称这样的图为简单图。
无向完全图:在无向图中,如果任意两个顶点之间都存在边,则称该图为无向完全图。含有n个顶点的无向完全图有n*(n-1)/2条边。
有向完全图:在有向图中,如果任意两个顶点之间都存在方向互为相反的两条弧,则称该图为有向完全图。含有n个顶点的有向完全图有n*(n-1)条边。
稀疏图和稠密图:这里的稀疏和稠密是模糊的概念,都是相对而言的,通常认为边或弧数小于n*logn(n是顶点的个数)的图称为稀疏图,反之称为稠密图。
有些图的边或弧带有与它相关的数字,这种与图的边或弧相关的数叫做权(Weight),带权的图通常称为网(Network)。
假设有两个图G1=(V1,E1)和G2=(V2,E2),如果V2⊆V1,E2⊆E1,则称G2为G1的子图(Subgraph)。
边(V1,V2)依附(incident)于顶点V1和V2,或者说边(V1,V2)与顶点V1和V2相关联。
顶点V的度(Degree)是和V相关联的边的数目,记为TD(V),如下图,顶点A与B互为邻接点,边(A,B)依附于顶点A与B上,顶点A的度为3。
对于有向图G=(V,E),如果有<V1,V2>∈E,则称顶点V1邻接到顶点V2,顶点V2邻接自顶点V1。
以顶点V为头的弧的数目称为V的入度(InDegree),记为ID(V),以V为尾的弧的数目称为V的出度(OutDegree),记为OD(V),因此顶点V的度为TD(V)=ID(V)+OD(V)。
如果G是有向图,则路径也是有向的。
下图用红线列举顶点B到顶点D的两种路径,而顶点A到顶点B就不存在路径啦:
路径的长度是路径上的边或弧的数目。
第一个顶点到最后一个顶点相同的路径称为回路或环(Cycle)。
序列中顶点不重复出现的路径称为简单路径,除了第一个顶点和最后一个顶点之外,其余顶点不重复出现的回路,称为简单回路或简单环。
连通图:在无向图G中,如果从顶点V1到顶点V2有路径,则称V1和V2是连通的,如果对于图中任意两个顶点Vi和Vj都是连通的,则称G是连通图(ConnectedGraph)
无向图中的极大连通子图称为连通分量。
如果一个有向图恰有一个顶点入度为0,其余顶点的入度均为1,则是一棵有向树。
邻接矩阵(无向图):
    图的邻接矩阵(Adjacency Matrix)存储方式是用两个数组来表示图。一个一维数组存储图中顶点信息,一个二维数组(称为邻接矩阵)存储图中的边或弧的信息。
对称矩阵:所谓对称矩阵就是n阶矩阵的元满足a[i][j]=a[j][i](0<=i,j<=n)。即从矩阵的左上角到右下角的主对角线为轴,右上角的元与左下角相对应的元全都是相等的。
邻接矩阵(有向图)
可见顶点数组vertex[4]={V0,V1,V2,V3},弧数组arc[4][4]也是一个矩阵,但因为是有向图,所以这个矩阵并不对称,例如由V1到V0有弧,得到arc[1][0]=1,而V0到V1没有弧,因此arc[0][1]=0。
另外有向图是有讲究的,要考虑入度和出度,顶点V1的入度为1,正好是第V1列的各数之和,顶点V1的出度为2,正好是第V1行的各数之和。
邻接矩阵(网)
在图的术语中,我们提到了网这个概念,事实上也就是每条边上带有权的图就叫网。
邻接表(无向图)
邻接矩阵看上去是个不错的选择,首先是容易理解,第二是索引和编排都很舒服~
但是我们也发现,对于边数相对顶点较少的图,这种结构无疑是存在对存储空间的极大浪费。因此我们可以考虑另外一种存储结构方式,例如把数组与链表结合一起来存储,这种方式在图结构也适用,我们称为邻接表(AdjacencyList)。
图中顶点用一个一维数组存储,当然,顶点也可以用单链表来存储,不过数组可以较容易地读取顶点信息,更加方便。
图中每个顶点Vi的所有邻接点构成一个线性表,由于邻接点的个数不确定,所以我们选择用单链表来存储。
邻接表(有向图)
若是有向图,邻接表结构也是类似的,我们先来看下把顶点当弧尾建立的邻接表,这样很容易就可以得到每个顶点的出度:
但也有时为了便于确定顶点的入度或以顶点为弧头的弧,我们可以建立一个有向图的逆邻接表:
邻接表(网)
对于带权值的网图,可以在边表结点定义中再增加一个数据域来存储权值即可:
十字链表
    十字链表的好处就是因为把邻接表和逆邻接表整合在了一起,这样既容易找到以Vi为尾的弧,也容易找到以Vi为头的弧,因而容易求得顶点的出度和入度。
    十字链表除了结构复杂一点外,其实创建图算法的时间复杂度是和邻接表相同的,因此,在有向图的应用中,十字链表也是非常好的数据结构模型。
邻接多重表
    其中iVex和jVex是与某条边依附的两个顶点在顶点表中的下标。iLink指向依附顶点iVex的下一条边,jLink指向依附顶点jVex的下一条边。
    也就是说在邻接多重表里边,边表存放的是一条边,而不是一个顶点。
边集数组
    边集数组是由两个一维数组构成,一个是存储顶点的信息,另一个是存储边的信息,这个边数组每个数据元素由一条边的起点下标(begin)、终点下标(end)和权(weight)组成。
图的遍历
树的遍历我们谈了四种方式,大家回忆一下,树因为根结点只有一个,并且所有的结点都只有一个双亲,所以不是很难理解。
    但是谈到图的遍历,那就复杂多了,因为它的任一顶点都可以和其余的所有顶点相邻接,因此极有可能存在重复走过某个顶点或漏了某个顶点的遍历过程。
    对于图的遍历,如果要避免以上情况,那就需要科学地设计遍历方案,通常有两种遍历次序方案:它们是深度优先遍历和广度优先遍历。
    深度优先遍历
        我们可以约定右手原则:在没有碰到重复顶点的情况下,分叉路口始终是向右手边走,每路过一个顶点就做一个记号。
回溯法:
    之前我们谈过回溯法,还是那句话,指导思想很简单,就是一条路走到黑,碰壁了再回来一条路走到黑……一般和递归可以很好的搭配使用,还有深度优先搜索(DFS)。
哈密尔顿路径:
    图G中的哈密尔顿路径指的是经过图G中每个顶点,且只经过一次的一条轨迹。如果这条轨迹是一条闭合的路径(从起点出发不重复地遍历所有点后仍能回到起始点),那么这条路径称为哈密尔顿回路。

图的遍历(广度优先遍历)
广度优先遍历(BreadthFirstSearch),又称为广度优先搜索,简称BFS。
一个无环的有向图称为无环图(Directed Acyclic Graph),简称DAG图。
在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网,我们称之为AOV网(Active On Vertex Network)。
拓扑序列含义:
设G=(V,E)是一个具有n个顶点的有向图,V中的顶点序列V1,V2,……,Vn满足若从顶点Vi到Vj有一条路径,则在顶点序列中顶点Vi必在顶点Vj之前。则我们称这样的顶点序列为一个拓扑序列。
对AOV网进行拓扑排序的方法和步骤如下:
从AOV网中选择一个没有前趋的顶点(该顶点的入度为0)并且输出它;
从网中删去该顶点,并且删去从该顶点发出的全部有向边;
重复上述两步,直到剩余网中不再存在没有前趋的顶点为止。
算法时间复杂度:
对一个具有n个顶点,e条边的网来说,初始建立入度为零的顶点栈,要检查所有顶点一次,执行时间为O(n)。
排序中,若AOV网无回路,则每个顶点入、出栈各一次,每个表结点被检查一次,因而执行时间是 O(n+e)。
所以,整个算法的时间复杂度是 O(n+e)。
我们把AOE网中没有入边的顶点称为始点或源点,没有出边的顶点称为终点或汇点。
etv(Earliest Time Of Vertex):事件最早发生时间,就是顶点的最早发生时间;
ltv(Latest Time Of Vertex):事件最晚发生时间,就是每个顶点对应的事件最晚需要开始的时间,如果超出此时间将会延误整个工期。
ete(Earliest Time Of Edge):活动的最早开工时间,就是弧的最早发生时间。
lte(Latest Time Of Edge):活动的最晚发生时间,就是不推迟工期的最晚开工时间。
顺序查找
顺序查找又叫线性查找,是最基本的查找技术,它的查找过程是:从第一个(或者最后一个)记录开始,逐个进行记录的关键字和给定值进行比较,若某个记录的关键字和给定值相等,则查找成功。如果查找了所有的记录仍然找不到与给定值相等的关键字,则查找不成功。
二叉排序数(Binary Sort Tree)又称为二叉查找树,它或者是一棵空树,或者是具有下列性质的二叉树:
若它的左子树不为空,则左子树上所有结点的值均小于它的根结构的值;
若它的右子树不为空,则右子树上所有结点的值均大于它的根结构的值;
它的左、右子树也分别为二叉排序树(递归)。
散列表的查找步骤
当存储记录时,通过散列函数计算出记录的散列地址
当查找记录时,我们通过同样的是散列函数计算记录的散列地址,并按此散列地址访问该记录
排序的稳定性
假设ki=kj(1<=i<=n,1<=j<=n,i!=j),且在排序前的序列中ri领先于rj(即i<j)。 如果排序后ri仍领先于rj,则称所用的排序方法是稳定的; 反之,若可能使得排序后的序列中rj领先ri,则称所用的排序方法是不稳定的。
冒泡排序的要点:
1. 两两注意是相邻的两个元素的意思
2. 如果有n个元素需要比较n-1次,每一轮减少1次比较
3. 既然叫冒泡排序,那就是从下往上两两比较,所以看上去就跟泡泡往上冒一样。
优化冒泡排序算法
我们发现如果使用正宗的冒泡排序算法,当i等于1执行完的时候,我们发现程序只进行两两相邻元素的比较,而不用进行任何移动,所以完全可以不用再继续循环。
希尔排序的原理
希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本,希尔排序是非稳定排序算法。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
插入排序在对几乎已经排好序的数据操作时, 效率高, 即可以达到线性排序的效率
但插入排序一般来说是低效的, 因为插入排序每次只能将数据移动一位
堆排序
上节课我们介绍的希尔排序是对直接插入排序的改进,而我们这节课谈的堆排序是对选择排序进行改进的排序算法,堆排序算法的时间复杂度和希尔排序是一样的,都是O(nlogn).
堆是具有下列性质的完全二叉树:每个结点的值都大于或者等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或者等于其左右孩子结点的值,称为小顶堆。
堆排序算法:
堆排序(Heap Sort)就是利用堆进行排序的算法,它的基本思想是:
将待排序的序列构造成一个大顶堆(或小顶堆)。
此时,整个序列的最大值就是堆顶的根结点。将它移走(就是将其与堆数组的末尾元素交换,此时末尾元素就是最大值)。
然后将剩余的n-1个序列重新构造成一个堆,这样就会得到n个元素中的此大值。
如此反复执行,便能得到一个有序序列了。
归并排序(递归实现)
归并”一词在中文含义中就是合并的意思,而在数据结构中的定义是将两个或者两个以上的有序表组合成一个新的有序表,就叫归并。
归并排序(Merge Sort)就是利用归并的思想实现的排序方法。它的原理是假设初始序列有n个记录,则 可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到⌈n/2⌉个长度为2或1的有序子序列;再两两归并,……,如此重复,直至得到一个长度为n的有序序列为止,这种排序方法称为2路归并排序。
快速排序
排序算法(Quict Sort)的基本思想是:
通过一趟排序将待排序记录分割成独立地两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的。


1.activity的生命周期。
2.横竖屏切换时候activity的生命周期
1.不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次.
2.设置Activity的android:configChanges=”orientation”时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次.
3.设置Activity的android:configChanges=”orientation|keyboardHidden”时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法.
3.android中的动画有哪几类,它们的特点和区别是什么?
两种,一种是Tween动画、还有一种是Frame动画。Tween动画,这种实现方式可以使视图组件移动、放大、缩小以及产生透明度的变化;另一种Frame动画,传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影。
4.一条最长的短信息约占多少byte?
中文70(包括标点),英文160个字节。
5.handler机制的原理
andriod提供了 Handler 和 Looper 来满足线程间的通信。Handler 先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(Message Exchange)。
  1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)。
2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper从Message Queue取出)所送来的消息。
  3) Message Queue(消息队列):用来存放线程放入的消息。
  4)线程:UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。
6.什么是嵌入式实时操作系统, Android 操作系统属于实时操作系统吗? 
嵌入式实时操作系统是指当外界事件或数据产生时,能够接受并以足够快的速度予以处理,其处理的结果又能在规定的时间之内来控制生产过程或对处理系统作出快速响应,并控制所有实时任务协调一致运行的嵌入式操作系统。主要用于工业控制、 军事设备、 航空航天等领域对系统的响应时间有苛刻的要求,这就需要使用实时系统。又可分为软实时和硬实时两种,而android是基于linux内核的,因此属于软实时。
7.android中线程与线程,进程与进程之间如何通信
1、一个 Android 程序开始运行时,会单独启动一个Process。
默认情况下,所有这个程序中的Activity或者Service都会跑在这个Process。
默认情况下,一个Android程序也只有一个Process,但一个Process下却可以有许多个Thread。
2、一个 Android 程序开始运行时,就有一个主线程Main Thread被创建。该线程主要负责UI界面的显示、更新和控件交互,所以又叫UI Thread。
一个Android程序创建之初,一个Process呈现的是单线程模型–即Main Thread,所有的任务都在一个线程中运行。所以,Main Thread所调用的每一个函数,其耗时应该越短越好。而对于比较费时的工作,应该设法交给子线程去做,以避免阻塞主线程(主线程被阻塞,会导致程序假死 现象)。
3、Android单线程模型:Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。如果在子线程中直接修改UI,会导致异常。
8.Android dvm的进程和Linux的进程, 应用程序的进程是否为同一个概念
DVM指dalivk的虚拟机。每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例。而每一个DVM都是在Linux 中的一个进程,所以说可以认为是同一个概念。
9.sim卡的EF 文件有何作用
sim卡的文件系统有自己规范,主要是为了和手机通讯,sim本 身可以有自己的操作系统,EF就是作存储并和手机通讯用的
10.android中的动画有哪几类,它们的特点和区别是什么?
两种,一种是Tween动画、还有一种是Frame动画。Tween动画,这种实现方式可以使视图组件移动、放大、缩小以及产生透明度的变化;另一种Frame动画,传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影。
11.让Activity变成一个窗口:Activity属性设定
讲点轻松的吧,可能有人希望做出来的应用程序是一个漂浮在手机主界面的东西,那么很 简单你只需要设置 一下Activity的主题就可以了在AndroidManifest.xml 中定义 Activity的 地方一句话:
Xml代码
1.android :theme=”@android:style/Theme.Dialog”
 这就使你的应用程序变成对话框的形式弹出来了,或者
Xml代码
1.android:theme=”@android:style/Theme.Translucent”
就变成半透明的,[友情提示-.-]类似的这种activity的属性可以在android.R.styleable 类的AndroidManifestActivity 方法中看到,AndroidManifest.xml中所有元素的属性的介绍都可以参考这个类android.R.styleable
上面说的是属性名称,具体有什么值是在android.R.style中 可以看到,比如这个”@android:style/Theme.Dialog” 就对应于android.R.style.Theme_Dialog ,(‘_’换成’.’ < –注意:这个是文章内容不是笑脸)就可以用在描述文件 中了,找找类定义和描述文件中的对应关系就都明白了。
12.如何将SQLite数据库(dictionary.db文件)与apk文件一起发布?
解答:可以将dictionary.db文件复制到Eclipse Android工程中的res aw目录中。所有在res aw目录中的文件不会被压缩,这样可以直接提取该目录中的文件。可以将dictionary.db文件复制到res aw目录中
13.如何将打开res aw目录中的数据库文件?
解答:在Android中不能直接打开res aw目录中的数据库文件,而需要在程序第一次启动时将该文件复制到手机内存或SD卡的某个目录中,然后再打开该数据库文件。复制的基本方法是使用getResources().openRawResource方法获得res aw目录中资源的 InputStream对象,然后将该InputStream对象中的数据写入其他的目录中相应文件中。在Android SDK中可以使用SQLiteDatabase.openOrCreateDatabase方法来打开任意目录中的SQLite数据库文件。
14.在android中mvc的具体体现
Android 的官方建议应用程序的开发采用MVC 模式。何谓MVC?先看看下图
MVC 是Model,View,Controller 的缩写,从上图可以看出MVC 包含三个部分:
.. 模型(Model)对象:是应用程序的主体部分,所有的业务逻辑都应该写在该
层。
.. 视图(View)对象:是应用程序中负责生成用户界面的部分。也是在整个
MVC 架构中用户唯一可以看到的一层,接收用户的输入,显示处理结果。
.. 控制器(Control)对象:是根据用户的输入,控制用户界面数据显示及更新
Model 对象状态的部分,控制器更重要的一种导航功能,想用用户出发的相
关事件,交给M 哦得了处理。
Android 鼓励弱耦合和组件的重用,在Android 中MVC 的具体体现如下
1)视图层(view):一般采用xml文件进行界面的描述,使用的时候可以非常方便的引入,当然,如何你对android了解的比较的多了话,就一定可 以想到在android中也可以使用javascript+html等的方式作为view层,当然这里需要进行java和javascript之间的通 信,幸运的是,android提供了它们之间非常方便的通信实现。
2)控制层(controller):android的控制层的重 任通常落在了众多的acitvity的肩上,这句话也就暗含了不要在acitivity中写代码,要通过activity交割model业务逻辑层处理, 这样做的另外一个原因是android中的acitivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。
3)模型层(model):对数据库的操作、对网络等的操作都应该在model里面处理,当然对业务计算等操作也是必须放在的该层的。
15.Android系统的架构
android的系统架构和其操作系统一样,采用了分层的架构。从架构图看,android分为四个层,从高层到低层分别是应用程序层、应用程序框架层、系统运行库层和linux核心层。
1.应用程序 Android会同一系列核心应用程序包一起发布,该应用程序包包括email客户端,SMS短消息程序,日历,地图,浏览器,联系人管理程序等。所有的应用程序都是使用JAVA语言编写的。
2.应用程序框架 开发人员也可以完全访问核心应用程序所使用的API框架。该应用程序的架构设计简化了组件的重用;任何一个应用程序都可以发布它的功能块并且任何其它的应用程序都可以使用其所发布的功能块(不过得遵循框架的安全性限制)。同样,该应用程序重用机制也使用户可以方便的替换程序组件。
隐藏在每个应用后面的是一系列的服务和系统, 其中包括;

  • 丰富而又可扩展的视图(Views),可以用来构建应用程序, 它包括列表(lists),网格(grids),文本框(text boxes),按钮(buttons), 甚至可嵌入的web浏览器。
  • 内容提供器(Content Providers)使得应用程序可以访问另一个应用程序的数据(如联系人数据库), 或者共享它们自己的数据
  • 资源管理器(Resource Manager)提供 非代码资源的访问,如本地字符串,图形,和布局文件( layout files )。
  • 通知管理器 (Notification Manager) 使得应用程序可以在状态栏中显示自定义的提示信息。
  • 活动管理器( Activity Manager) 用来管理应用程序生命周期并提供常用的导航回退功能。
    有关更多的细节和怎样从头写一个应用程序,请参考 如何编写一个 Android 应用程序.

3.系统运行库
1)程序库
Android 包含一些C/C++库,这些库能被Android系统中不同的组件使用。它们通过 Android 应用程序框架为开发者提供服务。以下是一些核心库:

  • 系统 C 库 - 一个从 BSD 继承来的标准 C 系统函数库( libc ), 它是专门为基于 embedded linux 的设备定制的。
  • 媒体库 - 基于 PacketVideo OpenCORE;该库支持多种常用的音频、视频格式回放和录制,同时支持静态图像文件。编码格式包括MPEG4, H.264, MP3, AAC, AMR, JPG, PNG 。
  • Surface Manager - 对显示子系统的管理,并且为多个应用程序提 供了2D和3D图层的无缝融合。
  • LibWebCore - 一个最新的web浏览器引擎用,支持Android浏览器和一个可嵌入的web视图。
  • SGL - 底层的2D图形引擎
  • 3D libraries - 基于OpenGL ES 1.0 APIs实现;该库可以使用硬件 3D加速(如果可用)或者使用高度优化的3D软加速。
  • FreeType -位图(bitmap)和矢量(vector)字体显示。
  • SQLite - 一个对于所有应用程序可用,功能强劲的轻型关系型数据库引擎。
    2)Android 运行库
     Android 包括了一个核心库,该核心库提供了JAVA编程语言核心库的大多数功能。
     每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例。Dalvik被设计成一个设备可以同时高效地运行多个虚拟系统。 Dalvik虚拟机执行(.dex)的Dalvik可执行文件,该格式文件针对小内存使用做了优化。同时虚拟机是基于寄存器的,所有的类都经由JAVA编译器编译,然后通过SDK中 的 “dx” 工具转化成.dex格式由虚拟机执行。
     Dalvik虚拟机依赖于linux内核的一些功能,比如线程机制和底层内存管理机制。

4.Linux 内核
Android 的核心系统服务依赖于 Linux 2.6 内核,如安全性,内存管理,进程管理, 网络协议栈和驱动模型。 Linux 内核也同时作为硬件和软件栈之间的抽象层。
16.Android常用控件的信息
单选框(RadioButton与RadioGroup):
RadioGroup用于对单选框进行分组,相同组内的单选框只有一个单选框被选中。
事件:setOnCheckedChangeListener(),处理单选框被选择事件。把RadioGroup.OnCheckedChangeListener实例作为参数传入。
多选框(CheckBox):
每个多选框都是独立的,可以通过迭代所有的多选框,然后根据其状态是否被选中在获取其值。
事件:setOnCheckChangeListener()处理多选框被选择事件。把CompoundButton.OnCheckedChangeListener实例作为参数传入
下拉列表框(Spring):
Spinner.getItemAtPosition(Spinner.getSelectedItemPosition());获取下拉列表框的值。
事件:setOnItemSelectedListener(),处理下拉列表框被选择事件把AdapterView.OnItemSelectedListener实例作为参数传入;
拖动条(SeekBar):
SeekBar.getProgress()获取拖动条当前值
事件:setOnSeekBarChangeListener(),处理拖动条值变化事件,把SeekBar.OnSeekBarChangeListener实例作为参数传入。
菜单(Menu):
重写Activity的onCreatOptionMenu(Menu menu)方法,该方法用于创建选项菜单,咋用户按下手机的”Menu”按钮时就会显示创建好的菜单,在onCreatOptionMenu(Menu Menu)方法内部可以调用Menu.add()方法实现菜单的添加。
重写Activity的onMenuItemSelected()方法,该方法用于处理菜单被选择事件。
进度对话框(ProgressDialog):
创建并显示一个进度对话框:ProgressDialog.show(ProgressDialogActivity.this,”请稍等”,”数据正在加载中….”,true);
设置对话框的风格:setProgressStyle()
ProgressDialog.STYLE_SPINNER 旋转进度条风格(为默认风格)
ProgressDialog.STYLE_HORIZONTAL 横向进度条风格
17.请介绍下Android中常用的五种布局
Android布局是应用界面开发的重要一环,在Android中,共有五种布局方式,分别是:FrameLayout(框架布局),LinearLayout (线性布局),
AbsoluteLayout(绝对布局),RelativeLayout(相对布局),TableLayout(表格布局)。
1.FrameLayout
这个布局可以看成是墙脚堆东西,有一个四方的矩形的左上角墙脚,我们放了第一个东西,要再放一个,那就在放在原来放的位置的上面,这样依次的放,会盖住原来的东西。这个布局比较简单,也只能放一点比较简单的东西。
2.LinearLayout
线性布局,这个东西,从外框上可以理解为一个div,他首先是一个一个从上往下罗列在屏幕上。每一个LinearLayout里面又可分为垂直布局 (android:orientation=”vertical”)和水平布局(android:orientation=”horizontal” )。当垂直布局时,每一行就只有一个元素,多个元素依次垂直往下;水平布局时,只有一行,每一个元素依次向右排列。
linearLayout中有一个重要的属性 android:layout_weight=”1”,这个weight在垂直布局时,代表行距;水平的时候代表列宽;weight值越大就越大。
3.AbsoluteLayout
绝对布局犹如div指定了absolute属性,用X,Y坐标来指定元素的位置android:layout_x=”20px” android:layout_y=”12px” 这种布局方式也比较简单,但是在垂直随便切换时,往往会出问题,而且多个元素的时候,计算比较麻烦。
4.RelativeLayout
相对布局可以理解为某一个元素为参照物,来定位的布局方式。主要属性有:
相对于某一个元素
android:layout_below=”@id/aaa” 该元素在 id为aaa的下面
android:layout_toLeftOf=”@id/bbb” 改元素的左边是bbb
相对于父元素的地方
android:layout_alignParentLeft=”true” 在父元素左对齐
android:layout_alignParentRight=”true” 在父元素右对齐
还可以指定边距等,具体详见API
5.TableLayout
表格布局类似Html里面的Table。每一个TableLayout里面有表格行TableRow,TableRow里面可以具体定义每一个元素,设定他的对齐方式 android:gravity=”” 。
每一个布局都有自己适合的方式,另外,这五个布局元素可以相互嵌套应用,做出美观的界面。
18.如何启用Service,如何停用Service
Android中的服务和windows中的服务是类似的东西,服务一般没有用户操作界面,它运行于系统中不容易被用户发觉,可以使用它开发如监控之类的程序。服务的开发比较简单,如下:
第一步:继承Service类
public class SMSService extends Service {
}
第二步:在AndroidManifest.xml文件中的节点里对服务进行配置:

服务不能自己运行,需要通过调用Context.startService()或Context.bindService()方法启动服务。这两个方法都可以启动Service,但是它们的使用场合有所不同。使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。
如果打算采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。
如果打算采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()–>onDestroy()方法。
服务常用生命周期回调方法如下:
onCreate() 该方法在服务被创建时调用,该方法只会被调用一次,无论调用多少次startService()或bindService()方法,服务也只被创建一次。
onDestroy()该方法在服务被终止时调用。
与采用Context.startService()方法启动服务有关的生命周期方法
onStart() 只有采用Context.startService()方法启动服务时才会回调该方法。该方法在服务开始运行时被调用。多次调用startService()方法尽管不会多次创建服务,但onStart() 方法会被多次调用。
与采用Context.bindService()方法启动服务有关的生命周期方法
onBind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用,当调用者与服务已经绑定,多次调用Context.bindService()方法并不会导致该方法被多次调用。
onUnbind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务解除绑定时被调用
采用Context. bindService()方法启动服务的代码如下:
public class HelloActivity extends Activity {
ServiceConnection conn = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
}
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
Button button =(Button) this.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
Intent intent = new Intent(HelloActivity.this, SMSService.class);
bindService(intent, conn, Context.BIND_AUTO_CREATE);
//unbindService(conn);//解除绑定
}});
}
}
采用Context. bindService()方法启动服务的代码如下:
public class HelloActivity extends Activity {
ServiceConnection conn = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
}
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
Button button =(Button) this.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
Intent intent = new Intent(HelloActivity.this, SMSService.class);
bindService(intent, conn, Context.BIND_AUTO_CREATE);
//unbindService(conn);//解除绑定
}});
}
}
采用Context. bindService()方法启动服务的代码如下:
public class HelloActivity extends Activity {
ServiceConnection conn = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
}
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
Button button =(Button) this.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
Intent intent = new Intent(HelloActivity.this, SMSService.class);
bindService(intent, conn, Context.BIND_AUTO_CREATE);
//unbindService(conn);//解除绑定
}});
}
}
19.ListView优化
工作原理:
ListView 针对List中每个item,要求 adapter “给我一个视图” (getView)。
一个新的视图被返回并显示
如果我们有上亿个项目要显示怎么办?为每个项目创建一个新视图?NO!这不可能!
实际上Android为你缓存了视图。
Android中有个叫做Recycler的构件,下图是他的工作原理:
如果你有10亿个项目(item),其中只有可见的项目存在内存中,其他的在Recycler中。

  1. ListView先请求一个type1视图(getView)然后请求其他可见的项目。convertView在getView中是空(null)的。

  2. 当item1滚出屏幕,并且一个新的项目从屏幕低端上来时,ListView再请求一个type1视图。convertView此时不是空值了,它的值是item1。你只需设定新的数据然后返回convertView,不必重新创建一个视图。
    20.广播接收者生命周期
    一个广播接收者有一个回调方法:void onReceive(Context curContext, Intent broadcastMsg)。当一个广播消息到达接收者是,Android调用它的onReceive()方法并传递给它包含消息的Intent对象。广播接收者被认为仅当它执行这个方法时是活跃的。当onReceive()返回后,它是不活跃的。
    有一个活跃的广播接收者的进程是受保护的,不会被杀死。但是系统可以在任何时候杀死仅有不活跃组件的进程,当占用的内存别的进程需要时。
    这带来一个问题,当一个广播消息的响应时费时的,因此应该在独立的线程中做这些事,远离用户界面其它组件运行的主线程。如果onReceive()衍生线程然后返回,整个进程,包括新的线程,被判定为不活跃的(除非进程中的其它应用程序组件是活跃的),将使它处于被杀的危机。解决这个问题的方法是onReceive()启动一个服务,及时服务做这个工作,因此系统知道进程中有活跃的工作在做。
    21.设计模式和IoC(控制反转)
    Android 框架魅力的源泉在于IoC,在开发Android 的过程中你会时刻感受到IoC 带来
    的巨大方便,就拿Activity 来说,下面的函数是框架调用自动调用的:
    protected void onCreate(Bundle savedInstanceState) ;
    不是程序编写者主动去调用,反而是用户写的代码被框架调用,这也就反转
    了!当然IoC 本身的内涵远远不止这些,但是从这个例子中也可以窥视出IoC
    带来的巨大好处。此类的例子在Android 随处可见,例如说数据库的管理类,
    例如说Android 中SAX 的Handler 的调用等。有时候,您甚至需要自己编写简
    单的IoC 实现,上面展示的多线程现在就是一个说明。
    22.Android中的长度单位详解
    现在这里介绍一下dp 和sp。dp 也就是dip。这个和sp 基本类似。如果设置表示长度、高度等属性时可以使用dp 或sp。但如果设置字体,需要使用sp。dp 是与密度无关,sp 除了与密度无关外,还与scale 无关。如果屏幕密度为160,这时dp 和sp 和px 是一样的。1dp=1sp=1px,但如果使用px 作单位,如果屏幕大小不变(假设还是3.2 寸),而屏幕密度变成了320。那么原来TextView 的宽度设成160px,在密度为320 的3.2 寸屏幕里看要比在密度为160 的3.2 寸屏幕上看短了一半。但如果设置成160dp 或160sp 的话。系统会自动将width 属性值设置成320px 的。也就是160 * 320 / 160。其中320 / 160 可称为密
    度比例因子。也就是说,如果使用dp 和sp,系统会根据屏幕密度的变化自动
    进行转换。
    下面看一下其他单位的含义
    px:表示屏幕实际的象素。例如,320480 的屏幕在横向有320个象素,
    在纵向有480 个象素。
    in:表示英寸,是屏幕的物理尺寸。每英寸等于2.54 厘米。例如,形容
    手机屏幕大小,经常说,3.2(英)寸、3.5(英)寸、4(英)寸就是指这个
    单位。这些尺寸是屏幕的对角线长度。如果手机的屏幕是3.2 英寸,表示手机
    的屏幕(可视区域)对角线长度是3.2
    2.54 = 8.128 厘米。读者可以去量
    一量自己的手机屏幕,看和实际的尺寸是否一致。
    23.4种activity的启动模式
    standard: 标准模式,一调用startActivity()方法就会产生一个新的实例。
    singleTop: 如果已经有一个实例位于Activity栈的顶部时,就不产生新的实例,而只是调用Activity中的newInstance()方法。如果不位于栈顶,会产生一个新的实例。
    singleTask: 会在一个新的task中产生这个实例,以后每次调用都会使用这个,不会去产生新的实例了。
    singleInstance: 这个跟singleTask基本上是一样,只有一个区别:在这个模式下的Activity实例所处的task中,只能有这个activity实例,不能有其他的实例。
    24.什么是ANR 如何避免它?
    ANR:Application Not Responding,五秒
    在Android中,活动管理器和窗口管理器这两个系统服务负责监视应用程序的响应。当出现下列情况时,Android就会显示ANR对话框了:
      对输入事件(如按键、触摸屏事件)的响应超过5秒
      意向接受器(intentReceiver)超过10秒钟仍未执行完毕 Android应用程序完全运行在一个独立的线程中(例如main)。这就意味着,任何在主线程中运行的,需要消耗大量时间的操作都会引发ANR。因为此时,你的应用程序已经没有机会去响应输入事件和意向广播(Intent broadcast)。
      因此,任何运行在主线程中的方法,都要尽可能的只做少量的工作。特别是活动生命周期中的重要方法如onCreate()和 onResume()等更应如此。潜在的比较耗时的操作,如访问网络和数据库;或者是开销很大的计算,比如改变位图的大小,需要在一个单独的子线程中完成(或者是使用异步请求,如数据库操作)。但这并不意味着你的主线程需要进入阻塞状态已等待子线程结束 – 也不需要调用Therad.wait()或者Thread.sleep()方法。取而代之的是,主线程为子线程提供一个句柄(Handler),让子线程在即将结束的时候调用它(xing:可以参看Snake的例子,这种方法与以前我们所接触的有所不同)。使用这种方法涉及你的应用程序,能够保证你的程序对输入保持良好的响应,从而避免因为输入事件超过5秒钟不被处理而产生的ANR。这种实践需要应用到所有显示用户界面的线程,因为他们都面临着同样的超时问题。
    25.Android Intent的使用
    在一个Android应用中,主要是由一些组件组成,(Activity,Service,ContentProvider,etc.)在这些组件之间的通讯中,由Intent协助完成。
    正如网上一些人解析所说,Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用。Intent在这里起着实现调用者与被调用者之间的解耦作用。
    Intent传递过程中,要找到目标消费者(另一个Activity,IntentReceiver或Service),也就是Intent的响应者,有两种方法来匹配:
    1,显示匹配(Explicit):
    public TestB extents Activity
    {
    ………
    };
    public class Test extends Activity
    {

    ......  
    public void switchActivity()  
    {  
           Intent i = new Intent(Test.this, TestB.class);  
           this.startActivity(i);  
    }  

    }
    public TestB extents Activity
    {
    ………
    };
    public class Test extends Activity
    {

    ......  
    public void switchActivity()  
    {  
           Intent i = new Intent(Test.this, TestB.class);  
           this.startActivity(i);  
    }  

    }
    public TestB extents Activity
    {
    ………
    };
    public class Test extends Activity
    {

    ......  
    public void switchActivity()  
    {  
           Intent i = new Intent(Test.this, TestB.class);  
           this.startActivity(i);  
    }  

    }
    代码简洁明了,执行了switchActivity()函数,就会马上跳转到名为TestB的Activity中。
    2,隐式匹配(Implicit):
    隐式匹配,首先要匹配Intent的几项值:Action, Category, Data/Type,Component
    如果填写了Componet就是上例中的Test.class)这就形成了显示匹配。所以此部分只讲前几种匹配。匹配规则为最大匹配规则,
    1,如果你填写了Action,如果有一个程序的Manifest.xml中的某一个Activity的IntentFilter段中定义了包含了相同的Action那么这个Intent就与这个目标Action匹配,如果这个Filter段中没有定义Type,Category,那么这个Activity就匹配了。但是如果手机中有两个以上的程序匹配,那么就会弹出一个对话可框来提示说明。
    Action的值在Android中有很多预定义,如果你想直接转到你自己定义的Intent接收者,你可以在接收者的IntentFilter中加入一个自定义的Action值(同时要设定Category值为”android.intent.category.DEFAULT”),在你的Intent中设定该值为Intent的Action,就直接能跳转到你自己的Intent接收者中。因为这个Action在系统中是唯一的。
    2,data/type,你可以用Uri来做为data,比如Uri uri = Uri.parse(http://www.google.com );
    Intent i = new Intent(Intent.ACTION_VIEW,uri);手机的Intent分发过程中,会根据http://www.google.com 的scheme判断出数据类型type
    手机的Brower则能匹配它,在Brower的Manifest.xml中的IntenFilter中首先有ACTION_VIEW Action,也能处理http:的type,
    3,至于分类Category,一般不要去在Intent中设置它,如果你写Intent的接收者,就在Manifest.xml的Activity的IntentFilter中包含android.category.DEFAULT,这样所有不设置Category(Intent.addCategory(String c);)的Intent都会与这个Category匹配。
    4,extras(附加信息),是其它所有附加信息的集合。使用extras可以为组件提供扩展信息,比如,如果要执行“发送电子邮件”这个动作,可以将电子邮件的标题、正文等保存在extras里,传给电子邮件发送组件。
    26.如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态?
    当你的程序中某一个Activity A 在运行时中,主动或被动地运行另一个新的Activity B
    这个时候A会执行
    Java代码
    public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putLong(“id”, 1234567890);}
    B 完成以后又会来找A, 这个时候就有两种情况,一种是A被回收,一种是没有被回收,被回
    收的A就要重新调用onCreate()方法,不同于直接启动的是这回onCreate()里是带上参数savedInstanceState,没被收回的就还是onResume就好了。
    savedInstanceState是一个Bundle对象,你基本上可以把他理解为系统帮你维护的一个Map对象。在onCreate()里你可能会 用到它,如果正常启动onCreate就不会有它,所以用的时候要判断一下是否为空。
    Java代码
    if(savedInstanceState != null){
    long id = savedInstanceState.getLong(“id”);
    }
    就像官方的Notepad教程 里的情况,你正在编辑某一个note,突然被中断,那么就把这个note的id记住,再起来的时候就可以根据这个id去把那个note取出来,程序就完整 一些。这也是看你的应用需不需要保存什么,比如你的界面就是读取一个列表,那就不需要特殊记住什么,哦, 没准你需要记住滚动条的位置…
    27.如何退出Activity
    对于单一Activity的应用来说,退出很简单,直接finish()即可。当然,也可以用killProcess()和System.exit()这样的方法。现提供几个方法,供参考:
    1、抛异常强制退出:该方法通过抛异常,使程序Force Close。验证可以,但是,需要解决的问题是,如何使程序结束掉,而不弹出Force Close的窗口。
    2、记录打开的Activity:每打开一个Activity,就记录下来。在需要退出时,关闭每一个Activity即可。
    3、发送特定广播:在需要结束应用时,发送一个特定的广播,每个Activity收到广播后,关闭即可。
    4、递归退出在打开新的Activity时使用startActivityForResult,然后自己加标志,在onActivityResult中处理,递归关闭。除了第一个,都是想办法把每一个Activity都结束掉,间接达到目的。但是这样做同样不完美。你会发现,如果自己的应用程序对每一个Activity都设置了nosensor,在两个Activity结束的间隙,sensor可能有效了。但至少,我们的目的达到了,而且没有影响用户使用。为了编程方便,最好定义一个Activity基类,处理这些共通问题。
    28.请解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系。
    Message Queue(消息队列):用来存放通过Handler发布的消息,通常附属于某一个创建它的线程,可以通过Looper.myQueue()得到当前线程的消息队列
       Handler:可以发布或者处理一个消息或者操作一个Runnable,通过Handler发布消息,消息将只会发送到与它关联的消息队列,然也只能处理该消息队列中的消息
    Looper:是Handler和消息队列之间通讯桥梁,程序组件首先通过Handler把消息传递给Looper,Looper把消息放入队列。Looper也把消息队列里的消息广播给所有的Handler,Handler接受到消息后调用handleMessage进行处理
       Message:消息的类型,在Handler类中的handleMessage方法中得到单个的消息进行处理.
    29.你如何评价Android系统?优缺点。
    答:优点:1、学习的开源性
       2、软件兼容性比较好
       3、软件发展迅速
       4、界面布局好
       缺点:1、版本过多
       2、先有软件少 3、商务性能差
    30.谈谈android数据存储方式。
    Android提供了5种方式存储数据:
    (1)使用SharedPreferences存储数据;它是Android提供的用来存储一些简单配置信息的一种机制,采用了XML格式将数据存储到设备中。只能在同一个包内使用,不能在不同的包之间使用。
    (2)文件存储数据;文件存储方式是一种较常用的方法,在Android中读取/写入文件的方法,与Java中实现I/O的程序是完全一样的,提供了openFileInput()和openFileOutput()方法来读取设备上的文件。
    (3)SQLite数据库存储数据;SQLite是Android所带的一个标准的数据库,它支持SQL语句,它是一个轻量级的嵌入式数据库。
    (4)使用ContentProvider存储数据;主要用于应用程序之间进行数据交换,从而能够让其他的应用保存或读取此Content Provider的各种数据类型。
    (5)网络存储数据;通过网络上提供给我们的存储空间来上传(存储)和下载(获取)我们存储在网络空间中的数据信息。
    31.Android中Activity, Intent, Content Provider, Service各有什么区别。
    Activity: 活动,是最基本的android应用程序组件。一个活动就是一个单独的屏幕,每一个活动都被实现为一个独立的类,并且从活动基类继承而来。
    Intent: 意图,描述应用想干什么。最重要的部分是动作和动作对应的数据。
    Content Provider:内容提供器,android应用程序能够将它们的数据保存到文件、SQLite数据库中,甚至是任何有效的设备中。当你想将你的应用数据和其他应用共享时,内容提供器就可以发挥作用了。
    Service:服务,具有一段较长生命周期且没有用户界面的程序。
    32.View, surfaceView, GLSurfaceView有什么区别。
    view是最基础的,必须在UI主线程内更新画面,速度较慢。
    SurfaceView 是view的子类,类似使用双缓机制,在新的线程中更新画面所以刷新界面速度比view快
    GLSurfaceView 是SurfaceView的子类,opengl 专用的
    33.Manifest.xml文件中主要包括哪些信息?
    manifest:根节点,描述了package中所有的内容。
    uses-permission:请求你的package正常运作所需赋予的安全许可。
    permission: 声明了安全许可来限制哪些程序能你package中的组件和功能。
    instrumentation:声明了用来测试此package或其他package指令组件的代码。
    application:包含package中application级别组件声明的根节点。
    activity:Activity是用来与用户交互的主要工具。
    receiver:IntentReceiver能使的application获得数据的改变或者发生的操作,即使它当前不在运行。
    service:Service是能在后台运行任意时间的组件。
    provider:ContentProvider是用来管理持久化数据并发布给其他应用程序使用的组件。
    34.根据自己的理解描述下Android数字签名。
    (1)所有的应用程序都必须有数字证书,Android系统不会安装一个没有数字证书的应用程序
    (2)Android程序包使用的数字证书可以是自签名的,不需要一个权威的数字证书机构签名认证
    (3)如果要正式发布一个Android ,必须使用一个合适的私钥生成的数字证书来给程序签名,而不能使用adt插件或者ant工具生成的调试证书来发布。
    (4)数字证书都是有有效期的,Android只是在应用程序安装的时候才会检查证书的有效期。如果程序已经安装在系统中,即使证书过期也不会影响程序的正常功能。
    35.AIDL的全称是什么?如何工作?能处理哪些类型的数据?
    AIDL全称Android Interface Definition Language(AndRoid接口描述语言)是一种借口描述语言; 编译器可以通过aidl文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程跨界对象访问的目的.AIDL的IPC的机制和COM或CORBA类似, 是基于接口的,但它是轻量级的。它使用代理类在客户端和实现层间传递值. 如果要使用AIDL, 需要完成2件事情: 1. 引入AIDL的相关类.; 2. 调用aidl产生的class.理论上, 参数可以传递基本数据类型和String, 还有就是Bundle的派生类, 不过在Eclipse中,目前的ADT不支持Bundle做为参数,
    具体实现步骤如下:
    1、创建AIDL文件, 在这个文件里面定义接口, 该接口定义了可供客户端访问的方法和属性。
    2、编译AIDL文件, 用Ant的话, 可能需要手动, 使用Eclipse plugin的话,可以根据adil文件自动生产java文件并编译, 不需要人为介入.
    3、在Java文件中, 实现AIDL中定义的接口. 编译器会根据AIDL接口, 产生一个JAVA接口。这个接口有一个名为Stub的内部抽象类,它继承扩展了接口并实现了远程调用需要的几个方法。接下来就需要自己去实现自定义的几个接口了.
    4、向客户端提供接口ITaskBinder, 如果写的是service,扩展该Service并重载onBind ()方法来返回一个实现上述接口的类的实例。
    5、在服务器端回调客户端的函数. 前提是当客户端获取的IBinder接口的时候,要去注册回调函数, 只有这样, 服务器端才知道该调用那些函数
    AIDL语法很简单,可以用来声明一个带一个或多个方法的接口,也可以传递参数和返回值。 由于远程调用的需要, 这些参数和返回值并不是任何类型.下面是些AIDL支持的数据类型:

  3. 不需要import声明的简单Java编程语言类型(int,boolean等)

  4. String, CharSequence不需要特殊声明

  5. List, Map和Parcelables类型, 这些类型内所包含的数据成员也只能是简单数据类型, String等其他比支持的类型.
    (另外: 我没尝试Parcelables, 在Eclipse+ADT下编译不过, 或许以后会有所支持).
    实现接口时有几个原则:
    .抛出的异常不要返回给调用者. 跨进程抛异常处理是不可取的.
    .IPC调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在Activity的主线程中调用。也就是IPC调用会挂起应用程序导致界面失去响应. 这种情况应该考虑单起一个线程来处理.
    .不能在AIDL接口中声明静态属性。
    IPC的调用步骤:

  6. 声明一个接口类型的变量,该接口类型在.aidl文件中定义。

  7. 实现ServiceConnection。

  8. 调用ApplicationContext.bindService(),并在ServiceConnection实现中进行传递.

  9. 在ServiceConnection.onServiceConnected()实现中,你会接收一个IBinder实例(被调用的Service). 调用
    YourInterfaceName.Stub.asInterface((IBinder)service)将参数转换为YourInterface类型。

  10. 调用接口中定义的方法。你总要检测到DeadObjectException异常,该异常在连接断开时被抛出。它只会被远程方法抛出。

  11. 断开连接,调用接口实例中的ApplicationContext.unbindService()
    参考:http://buaadallas.blog.51cto.com/399160/372090
    36.android:gravity与android:layout_gravity的区别
    LinearLayout有两个非常相似的属性:android:gravity与android:layout_gravity。他们的区别在 于:android:gravity用于设置View组件的对齐方式,而android:layout_gravity用于设置Container组件的 对齐方式。
    举个例子,我们可以通过设置android:gravity=”center”来让EditText中的文字在EditText组件中居中显示;同 时我们设置EditText的android:layout_gravity=”right”来让EditText组件在LinearLayout中居中 显示。来实践以下:
    正如我们所看到的,在EditText中,其中的文字已经居中显示了,而EditText组件自己也对齐到了LinearLayout的右侧。


    <EditText

    android:layout_width="wrap_content"   
    android:gravity="center"   
    android:layout_height="wrap_content"   
    android:text="one"   
    android:layout_gravity="right"/>   


    <EditText

    android:layout_width="wrap_content"   
    android:gravity="center"   
    android:layout_height="wrap_content"   
    android:text="one"   
    android:layout_gravity="right"/>   
    这两个属性也可以用于 Framlayout Textview 等等,表示的意思大同小异 37.padding与margin的区别 padding填充的意思,指的是view中的content与view边缘的距离,类似文本中的indent 而margin表示的是view的左边缘与parent view的左边缘的距离 margin一般用来描述控件间位置关系,而padding一般描述控件内容和控件的位置关系。 简单,padding是站在父 view的角度描述问题,它规定它里面的内容必须与这个父view边界的距离。margin则是站在自己的角度描述问题,规定自己和其他(上下左右)的 view之间的距离,如果同一级只有一个view,那么它的效果基本上就和padding一样了。例如我的XML layout代码如下: view plaincopy to clipboardprint?


    <LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android"
    android:orientation=”vertical”
    android:layout_width=”fill_parent”
    android:layout_height=”fill_parent”
    android:paddingLeft=”10dip”
    android:paddingRight=”10dip”
    android:paddingTop=”10dip”
    android:paddingBottom=”10dip”





    <LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android"
    android:orientation=”vertical”
    android:layout_width=”fill_parent”
    android:layout_height=”fill_parent”
    android:paddingLeft=”10dip”
    android:paddingRight=”10dip”
    android:paddingTop=”10dip”
    android:paddingBottom=”10dip”




    那么我会得到如下的效果,图上已经很明确的标出来区别咯。 38. 注册广播接收者两种方式的区别 现在我们就来实现一个简单的广播程序。Android提供了两种注册广播接受者的形式,分别是在程序中动态注册和在xml中指定。他们之间的区别就是作用 的范围不同,程序动态注册的接收者只在程序运行过程中有效,而在xml注册的接收者不管你的程序有没有启动有会起作用。 39.Dalvik基于JVM的改进
  12. 几个class变为一个dex,constant pool,省内存

  13. Zygote,copy-on-write shared,省内存,省cpu,省电

  14. 基于寄存器的bytecode,省指令,省cpu,省电

  15. Trace-based JIT,省cpu,省电,省内存
    40.android中有哪几种解析xml的类,官方推荐哪种?以及它们的原理和区别.
    Ø DOM解析
    优点:

  16. XML树在内存中完整存储,因此可以直接修改其数据和结构.

  17. 可以通过该解析器随时访问XML树中的任何一个节点.

  18. DOM解析器的API在使用上也相对比较简单.
    缺点:如果XML文档体积比较大时,将文档读入内存是非常消耗系统资源的.
    使用场景:DOM 是用与平台和语言无关的方式表示 XML 文档的官方 W3C 标准.DOM 是以层次结构组织的节点的集合.这个层次结构允许开发人员在树中寻找特定信息.分析该结构通常需要加载整个文档和构造层次结构,然后才能进行任何工作.DOM是基于对象层次结构的.
    Ø SAX解析
    优点:
    SAX 对内存的要求比较低,因为它让开发人员自己来决定所要处理的标签.特别是当开发人员只需要处理文档中所包含的部分数据时,SAX 这种扩展能力得到了更好的体现.
    缺点:
    用SAX方式进行XML解析时,需要顺序执行,所以很难访问到同一文档中的不同数据.此外,在基于该方式的解析编码过程也相对复杂.
    使用场景:
    对于含有数据量十分巨大,而又不用对文档的所有数据进行遍历或者分析的时候,使用该方法十分有效.该方法不用将整个文档读入内存,而只需读取到程序所需的文档标签处即可.
    Ø Xmlpull解析
    android SDK提供了xmlpull api,xmlpull和sax类似,是基于流(stream)操作文件,然后根据节点事件回调开发者编写的处理程序.因为是基于流的处理,因此xmlpull和sax都比较节约内存资源,不会象dom那样要把所有节点以对橡树的形式展现在内存中.xmlpull比sax更简明,而且不需要扫描完整个流.
    41.Android系统中GC什么情况下会出现内存泄露呢?
    出现情况:

  19. 数据库的cursor没有关闭

  20. 构造adapter时,没有使用缓存contentview
    衍生listview的优化问题—–减少创建view的对象,充分使用contentview,可以使用一静态类来优化处理getview的过程/

  21. Bitmap对象不使用时采用recycle()释放内存

  22. activity中的对象的生命周期大于activity
    调试方法: DDMS==> HEAPSZIE==>dataobject==>[Total Size]
    42.谈谈对Android NDK的理解
    NDK 全称: Native Development Kit

  23. 误解
    误解一: NDK 发布之前, Android 不支持进行 C 开发
    在Google 中搜索 “NDK” ,很多 “Android 终于可以使用 C++ 开发 ” 之类的标题,这是一种对 Android 平台编程方式的误解.其实, Android 平台从诞生起,就已经支持 C . C++ 开发.众所周知, Android 的 SDK 基于 Java 实现,这意味着基于 Android SDK 进行开发的第三方应用都必须使用 Java 语言.但这并不等同于 “ 第三方应用只能使用 Java” .在 Android SDK 首次发布时, Google 就宣称其虚拟机 Dalvik 支持 JNI 编程方式,也就是第三方应用完全可以通过 JNI 调用自己的 C 动态库,即在 Android 平台上, “Java+C” 的编程方式是一直都可以实现的.
    当然这种误解的产生是有根源的:在Android SDK 文档里,找不到任何 JNI 方面的帮助.即使第三方应用开发者使用 JNI 完成了自己的 C 动态链接库( so )开发,但是 so 如何和应用程序一起打包成 apk 并发布?这里面也存在技术障碍.我曾经花了不少时间,安装交叉编译器创建 so ,并通过 asset (资源)方式,实现捆绑 so 发布.但这种方式只能属于取巧的方式,并非官方支持.所以,在 NDK 出来之前,我们将 “Java+C” 的开发模式称之为灰色模式,即官方既不声明 “ 支持这种方式 ” ,也不声明 “ 不支持这种方式 ” .
    误解二:有了 NDK ,我们可以使用纯 C 开发 Android 应用
    Android SDK采用 Java 语言发布,把众多的 C 开发人员排除在第三方应用开发外( 注意:我们所有讨论都是基于“ 第三方应用开发 ” , Android 系统基于 Linux ,系统级别的开发肯定是支持 C 语言的. ).NDK 的发布,许多人会误以为,类似于 Symbian . WM ,在 Android 平台上终于可以使用纯 C . C++ 开发第三方应用了!其实不然, NDK 文档明确说明: it is not a good way .因为 NDK 并没有提供各种系统事件处理支持,也没有提供应用程序生命周期维护.此外,在本次发布的 NDK 中,应用程序 UI 方面的 API 也没有提供.至少目前来说,使用纯 C . C++ 开发一个完整应用的条件还不完备.
    1.NDK 是一系列工具的集合.
    NDK提供了一系列的工具,帮助开发者快速开发 C (或 C++ )的动态库,并能自动将 so 和 java 应用一起打包成 apk .这些工具对开发者的帮助是巨大的.
    NDK集成了交叉编译器,并提供了相应的 mk 文件隔离 CPU .平台. ABI 等差异,开发人员只需要简单修改 mk 文件(指出 “ 哪些文件需要编译 ” . “ 编译特性要求 ” 等),就可以创建出 NDK可以自动地将 so 和 Java 应用一起打包,极大地减轻了开发人员的打包工作.
    2.NDK 提供了一份稳定.功能有限的 API 头文件声明.
    Google明确声明该 API 是稳定的,在后续所有版本中都稳定支持当前发布的 API .从该版本的 NDK 中看出,这些 API 支持的功能非常有限,包含有: C 标准库( libc ).标准数学库( libm ).压缩库( libz ). Log 库( liblog ).

  24. NDK 带来什么

  25. NDK 的发布,使 “Java+C” 的开发方式终于转正,成为官方支持的开发方式.
    使用NDK ,我们可以将要求高性能的应用逻辑使用 C 开发,从而提高应用程序的执行效率.
    使用NDK ,我们可以将需要保密的应用逻辑使用 C 开发.毕竟, Java 包都是可以反编译的.
    NDK促使专业 so 组件商的出现.(乐观猜想,要视乎 Android 用户的数量)
    2.NDK 将是 Android 平台支持 C 开发的开端. NDK提供了的开发工具集合,使开发人员可以便捷地开发.发布 C 组件.同时, Google承诺在 NDK 后续版本中提高 “ 可调式 ” 能力,即提供远程的 gdb 工具,使我们可以便捷地调试 C 源码.在支持 Android 平台 C 开发,我们能感觉到 Google 花费了很大精力,我们有理由憧憬 “C 组件支持 ” 只是 Google Android 平台上C 开发的开端.毕竟, C 程序员仍然是码农阵营中的绝对主力,将这部分人排除在 Android 应用开发之外,显然是不利于 Android 平台繁荣昌盛的.
    1、一个”.java”源文件中是否可以包括多个类(不是内部类)?有什么限制?


#Android面试题

四大组件很熟悉了吧,
ContentProvider的生命周期是什么;
http://www.cnblogs.com/bravestarrhu/archive/2012/05/02/2479461.html
Android设备开机的启动过程;
http://blog.jobbole.com/67931/
Activity的视图层次是什么?
打开一个对话框的时候,这个对话框是如何加入到视图上去的?
Dialog、PopupWindow、WindowManager加载视图的区别;
Service与Thread的区别;
ServiceManager、ActivityManager、XXXManager是干什么的;
为什么一定要在UI线程更新视图,为什么要这么设计;
打包APK的过程干了什么;
安装APK的过程干了什么;
启动APK的过程干了什么;
怎么玩DexLoader(动态升级);
View的生命周期是啥;
TWEEN动画跟熟悉动画在View的绘制过程是怎么作用的;
自定义动画玩过吗,里面的Matrix怎么控制。
res里面的XML资源最终都要转化成JavaCode,怎么完全脱离res,用纯代码的方式实现res资源的功能,怎么缩放一张点九图;
Binder原理是什么,出了Binder之外,还能怎么跟Service交互;
Touch事件的分发机制;
能不能用代码模拟一组TOUCH事件(比如自动点击广告,自动滚动);
ROOT的原理是什么,系统是怎么管理APP的权限的;
Material Desgin这么好看,为什么不出兼容包,让5.0以下的系统也能要动画效果;
ART模式与Dalvik有什么不同;
Render Thread是怎么工作的;
为什么TMD不把功能都用H5实现然后把需求都扔给前段的人去做;
ServiceManager、ActivityManager、packageManager 、*****Manager 都弄懂了?
Binder 也搞清楚了?
IPC 也弄明白了?
FrameWork 层的每个类都折腾了?
Hook 会玩了?
各种 SystemService 也知道怎么运行的了?
View 的渲染你明白是怎么回事了?
Intent 是如何实现 1 等之间的解耦合的?
单元测试会写了?
Monkey 能跑多长时间?
性能测试通过了?
ClassLoader 和 DexLoader 会玩了?
Context 是个啥你也知道了?
权限机制也弄清楚了?
触屏事件的分发呢?
Handler 、Message 和 Looper 是怎么跑起来的?
如果上面超过一半的东西题主还没有弄清楚,洗洗睡,明天早点起来看书。
1、 Service两种方式的区别

2、 Handler在项目怎么用的,线程间如何通信的

3、 AsyncTask和AsyncQueryHandler

5、 消息推送机制xmpp协议,客户端发送服务器好处理,只要知道服务器IP就可以,服务器如何给客户端推送消息呢

6、 oauth认证

7、 HTML和XML的区别

8、 多线程断点续传下载如何实现续传的

9、 TCP、UDP的区别

10、 aidl开发

11、 Android中JNI和NDK的使用,了解WebService调用技术

12、 Android安全机制,垃圾回收机制

13、 AJAX

14、 屏幕适配

15、 android ui的几个概念:px,dip(dp),sp,dpi,分辨率等,dpi是在Android资源随着不同手机的分辨率自动进行适配,res-》drawable-hdpi

16、 Launcher如何设置壁纸


Android面试试题

一般简单题

  1. Android dvm的进程和Linux的进程,应用程序的进程是否为同一个概念?
    DVM指Dalivk的虚拟机,每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalivk虚拟机实例。而每一个DVM都是在Linux中的一个进程,所以说可以认为是同一个概念。
  2. SIM卡的 EF 文件有何作用?
    sim卡的文件系统有自己的规范,主要是为了和手机通讯,sim本身可以有自己的操作系统,EF就是做存储并和手机通讯用的。
  3. 嵌入式操作系统内存管理有哪几种,各有何特性?
    页式,段式,段页,用到了MMU,虚拟控件等技术。
  4. 什么是嵌入式实时操作系统,Android 操作系统属于实时操作系统吗?
    嵌入式实时操作系统是指当外界事件或数据产生时,能够接受并以足够快的速度予以处理,其处理的结果又能在规定的时间之内来控制生产过程或对处理系统作出快速响应,并控制所有实时任务协调一致运行的嵌入式操作系统。主要用于工业控制、军事设备、航空航天等领域对系统的响应时间有苛刻的要求,这就需要使用实时系统。又可分为软实时和硬实时两种,而android是基于linux内核的,因此属于软实时。
  5. 一条最长的短信息约占多少byte?
    中文70(包括标点),英文占160字节。
  6. Android中的动画有哪几类,它们的特点和区别是什么?
    两种,一中是Tween动画,一种是Frame动画。这种实现方式可以使视图组件移动、放大、缩小以及产生透明度的变化;另一种Frame动画,传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影。
  7. Handler机制的原理
    Andriod提供了 Handler 和 Looper 来满足线程间的通信。Handler 先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(Message Exchange)。
    Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)。
    Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper从Message Queue取出)所送来的消息。
    Message Queue(消息队列):用来存放线程放入的消息。
    线程:UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。
  8. 说说MVC模式的原理,它在Android中的运用
    MVC(Model_view_controller)” 模型-视图-控制器”。 MVC应用程序总是由这三个部分组成。Event(事件)导致Controller改变Model或View,或者同时改变两者。只要 Controller改变了Models的数据或者属性,所有依赖的View都会自动更新。类似的,只要Controller改变了View,View会从潜在的Model中获取数据来刷新自己。

View重绘和内存泄露

  1. View的刷新
    在需要刷新的地方,使用Handler.sendmessage发送消息,然后在Handler的getmessage里面执行invalidate或者invalidate
  2. GC内存泄露
    出现情况:
    • 数据库的cursor没有关闭。
    • 构造adapter时,没有使用缓存contentview。衍生listview的优化问题:减少创建view的对象,充分使用contentview,可以使用一静态类来优化处理getview的过程。
    • Bitmap对象不使用时采用recycle()释放内存。
    • activity中的对象的生命周期大于activity。

Activity

  1. Activity的生命周期
      @Override
       protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_main);
           //在这里创建界面,做一些数据的初始化工作。
       }
    
       @Override
       protected void onStart() {
           super.onStart();
           //到这一步变成用户可见不可交互的。
       }
    
       @Override
       protected void onRestart() {
           super.onRestart();
           //從stop重新開始
       }
    
       @Override
       protected void onResume() {
           super.onResume();
           //变成和用户可交互的
       }
    
       @Override
       protected void onPause() {
           super.onPause();
           //到这一步是可见但不可交互的,系统会停止动画等消耗CPU的事情从上文的描述已经知道,应该在这里保存你的一些数据,
           // 因为这个时候你的程序的优先级降低,有可能被系统收回。在这里保存的数据,应该在 onResume里读出来,
           // 注意:这个方法里做的事情时间要短,因为下一个activity不会等到这个方法完成才启动。
       }
    
       @Override
       protected void onStop() {
           super.onStop();
           //变得不可见,被下一个activity覆盖了。
       }
    
       @Override
       protected void onDestroy() {
           super.onDestroy();
           //这是activity被干掉前最后一个被调用方法了,可能是外面类调用finish方法或者是系统为了
           // 节省空间将它暂时性的干掉,可以用isFinishing()来判断它,
           // 如果你有一个Progress Dialog在线程中转动,请在onDestroy里把他cancel掉,
           // 不然等线程结束的时候,调用Dialog的cancel方法会抛异常的。
       }
      ```  
    12. 让Activity变成一个窗口:Activity属性设定  
      可能有人希望做出来的应用程序是一个漂浮在手机主界面的东西,那么很简单你只需要设置一下Activity的主题就可以了在AndroidManifest.xml 中定义 Activity的地方一句话:
    android:theme=”@android:style/Theme.Dialog”
    这就使你的应用程序变成对话框的形式弹出来了,或者
    android:theme=”@android:style/Theme.Translucent”
      就变成半透明的,类似的这种activity的属性可以在android.R.styleable 类的AndroidManifestActivity 方法中看到,AndroidManifest.xml中所有元素的属性的介绍都可以参考这个类android.R.styleable上面说的是属性名称,具体有什么值是在android.R.style中可以看到,比如这个"@android:style/Theme.Dialog"就对应于android.R.style.Theme_Dialog ,('_'换成'.' )就可以用在描述文件中了,找找类定义和描述文件中的对应关系就都明白了。   
    13. 你后台的Activity被系统回收怎么办:onSaveInstanceState
      当你的程序中某一个Activity A 在运行时中,主动或被动地运行另一个新的Activity B 这个时候A会执行Java代码:
    @Override
    protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    }
    14. 面試流程[!http://www.bubuko.com/infodetail-992911.html]   http://www.testtao.com/thread-32127-1-1.html
    14. java.io包中定义了多个流类型来实现输入和输出功能,可以从不同的角度对其进行分                   类,按功能分为:(节点流和处理流),如果为读取的内容进行处理后再输出,需要使用下列哪种流?    Filter stream   
    15. 下列代码的执行结果是:(B)
    public class Test3{
    public static void main(String args[]){
    System.out.print(100%3);
    System.out.print(“,”);
    System.out.println(100%3.0);
    }
    }
      A、1,1 B、1,1.0 C、1.0,1 D、1.0,1.0
    16. 在继承中,关于构造方法的说明,下列说法错误的是(D)
        A、子类无条件的继承父类的无参构造方法,   
      B、子类可以引用父类中的有参构造方法,使用super关键字,   
      C、如果子类没有构造方法,则父类无参构造方法作为自已的构造方法,   
      D、如果子类有无参构造方法,而父类的无参构造方法则被覆盖。
    17. 以下程序的运行结果为(B)
    public class IfTest{

  public static void main(String args[]){

  int x=3;

  int y=1;

  if(x==y)

  System.out.println(“Not equal”);

  else

  System.out.println(“Equal”);

  }
  }

  A、Not equal B、Equal C、无输出 D、编译出错
18. Java语言中字符串“学Java”所占的内存空间是(a)   
  A. 6个字节 B. 7个字节 C. 10个字节 D. 11个字节
19. 关于下列程序段的输出结果,说法正确的是:( D)

public class MyClass{

  static int i; public static void main(Stringargv[]){ System.out.println(i); } }

  A、有错误,变量i没有初始化。 B、null C、1 D、0   
20. 下列哪些语句关于内存回收的说明是正确的? (B )   
    A、 程序员必须创建一个线程来释放内存

  B、 内存回收程序负责释放无用内存

  C、 内存回收程序允许程序员直接释放内存

  D、 内存回收程序可以在指定的时间释放内存对象
21. 下面异常是属于Runtime Exception 的是(ABCD)(多选)   
    A、ArithmeticException

  B、IllegalArgumentException

  C、NullPointerException

  D、BufferUnderflowException
22. Math.round(11.5)等于多少(). Math.round(-11.5)等于多少(C).   
  A、11 ,-11 B、11 ,-12 C、12 ,-11 D、12 ,-12
23. 下列程序段的输出结果是:(B )

void complicatedexpression_r(){ int x=20, y=30; boolean b; b=x>50&&y>60||x>50&&y<-60||x<-50&&y>60||x<-50&&y<-60; System.out.println(b); }
  A、true B、false C、1 D、0
24. activity对一些资源以及状态的操作保存,最好是保存在生命周期的哪个函数中进行(A)
  A、onPause() B、onCreate() C、 onResume() D、onStart()
25. Intent传递数据时,下列的数据类型哪些可以被传递(ABCD)(多选)
  A、Serializable B、charsequence C、Parcelable D、Bundle
26. android 中下列属于Intent的作用的是(C)   
    A、实现应用程序间的数据共享

  B、是一段长的生命周期,没有用户界面的程序,可以保持应用在后台运行,而不会因为切换页面而消失

  C、可以实现界面间的切换,可以包含动作和动作数据,连接四大组件的纽带

  D、处理一个应用程序整体性的工作
27. 下列属于SAX解析xml文件的优点的是(B)   
    A、将整个文档树在内存中,便于操作,支持删除,修改,重新排列等多种功能

  B、不用事先调入整个文档,占用资源少

  C、整个文档调入内存,浪费时间和空间

  D、不是长久驻留在内存,数据不是持久的,事件过后,若没有保存数据,数据就会

  消失
28. 在android中使用Menu时可能需要重写的方法有(AC)。(多选)
    A、onCreateOptionsMenu(AC)

  B、onCreateMenu()

  C、onOptionsItemSelected()

  D、onItemSelected()
29. 在android中使用SQLiteOpenHelper这个辅助类时,可以生成一个数据库,并可以对数 据库版本进行管理的方法可以是(AB)   
    A、getWriteableDatabase()

  B、getReadableDatabase()

  C、getDatabase()

  D、getAbleDatabase()   
30. android 关于service生命周期的onCreate()和onStart()说法正确的是(AD)(多选题)   
    A、当第一次启动的时候先后调用onCreate()和onStart()方法

  B、当第一次启动的时候只会调用onCreate()方法

  C、如果service已经启动,将先后调用onCreate()和onStart()方法

  D、如果service已经启动,只会执行onStart()方法,不在执行onCreate()方法
31. 下面是属于GLSurFaceView特性的是(ABC)(多选)   
    A、管理一个surface,这个surface就是一块特殊的内存,能直接排版到android的视图

  view上。

  B、管理一个EGL display,它能让opengl把内容渲染到上述的surface上。

  C、让渲染器在独立的线程里运作,和UI线程分离。

  D、可以直接从内存或者DMA等硬件接口取得图像数据   
32. 关于ContenValues类说法正确的是(A)   
    A、他和Hashtable比较类似,也是负责存储一些名值对,但是他存储的名值对当中的

  名是String类型,而值都是基本类型

  B、他和Hashtable比较类似,也是负责存储一些名值对,但是他存储的名值对当中的

  名是任意类型,而值都是基本类型

  C、他和Hashtable比较类似,也是负责存储一些名值对,但是他存储的名值对当中的

  名,可以为空,而值都是String类型

  D、他和Hashtable比较类似,也是负责存储一些名值对,但是他存储的名值对当中

  的名是String类型,而值也是String类型
33. 我们都知道Hanlder是线程与Activity通信的桥梁,如果线程处理不当,你的机器

  就会变得越慢,那么线程销毁的方法是(A)   
    A、onDestroy()

  B、onClear()

  C、onFinish()

  D、onStop()
34. 下面退出Activity错误的方法是(C)   
    A、finish()

  B、抛异常强制退出

  C、System.exit()

  D、onStop()
35. 下面属于android的动画分类的有(AB)(多项)
  A、Tween B、FrameC、Draw D、Animation
36. Android项目工程下面的assets目录的作用是什么   B
    A、放置应用到的图片资源。

  B、主要放置多媒体等数据文件

  C、放置字符串,颜色,数组等常量数据

  D、放置一些与UI相应的布局文件,都是xml文件
37. 关于res/raw目录说法正确的是   A
    A、 这里的文件是原封不动的存储到设备上不会转换为二进制的格式

  B、 这里的文件是原封不动的存储到设备上会转换为二进制的格式

  C、 这里的文件最终以二进制的格式存储到指定的包中

  D、 这里的文件最终不会以二进制的格式存储到指定的包中
38. 下列对android NDK的理解正确的是(ABCD )
    A、 NDK是一系列工具的集合

  B、 NDK 提供了一份稳定、功能有限的 API 头文件声明。

  C、 使“Java+C” 的开发方式终于转正,成为官方支持的开发方式

  D、 NDK 将是 Android 平台支持 C 开发的开端
39. 我们用____int___来定义一个整数,用____char___来定义一个字符类型,称为原始数据类型。   
40. android中常用的四个布局是________________________________________。   FrameLayout,LilnearLayout,RelativeLayout,TableLayout
41. android 的四大组件是__________,Activity,Broadcast,Service,ContentProvide
42. java.io包中的____________和____________类主要用于对对象(Object)的读写。   ObjectInputStream ObjectOutputSteam
43. android 中service的实现方法是:_____________和_____________。startService ,bindService
44.activity一般会重载7个方法用来维护其生命周期,除了onCreate(),onStart(),onDestory()外还有_____________,______________,____________,___________。   onRestart(),onResume(),onPause(),onStop()
45. android的数据存储的方式_________,___________,__________,_________,________。SharedPreferences存储,文件存储,SQLite存储,ContentProvider,网络存储
46. 当启动一个Activity并且新的Activity执行完后需要返回到启动它的Activity来执行的回调函数是____startActivityResult()_____________。
47. 请使用命令行的方式创建一个名字为myAvd,sdk版本为2.2,sd卡是在d盘的根目录下,名字为scard.img,并指定屏幕大小HVGA.____________________________________。adnroid create acd -n myAvd -t 8 -s HVDA - Cd:\card.img
48. 程序运行的结果是:_______good and gbc________。

public classExample{
  Stringstr=new String(“good”);
  char[]ch={‘a’,’b’,’c’};
  publicstatic void main(String args[]){
  Exampleex=new Example();
  ex.change(ex.str,ex.ch);
  System.out.print(ex.str+”and “);
  Sytem.out.print(ex.ch);
  }
  public voidchange(String str,char ch[]){
  str=”testok”;
  ch[0]=’g’;
  }
  }
  49. 横竖屏切换时候 activity 的生命周期   
  1. 不设置 Activity 的 android:configChanges 时 , 切屏会重新调用各个生命周期 , 切横屏时会执行一次 , 切竖屏时会执行两次 .
  2. 设置 Activity 的 android:configChanges="orientation" 时 , 切屏还是会重新调用各个生命周期 , 切横、竖屏时只会执行一次 .
  3. 设置 Activity 的 android:configChanges="orientation|keyboardHidden" 时 , 切屏不会重新调用各个生命周期 ,            只会执行onConfigurationChanged 方法 .
  50. android 中线程与线程,进程与进程之间如何通信   
    1 、一个 Android 程序开始运行时,会单独启动一个 Process 。   
    默认情况下,所有这个程序中的 Activity 或者 Service 都会跑在这个 Process 。   
     默认情况下,一个 Android 程序也只有一个 Process ,但一个 Process 下却可以有许多个 Thread 。   
     2 、一个 Android 程序开始运行时,就有一个主线程 Main Thread 被创建。该线程主要负责 UI 界面的显示、更新和控件交互,所以又叫 UI Thread 。   
     一个 Android 程序创建之初,一个 Process 呈现的是单线程模型 -- 即 Main Thread ,所有的任务都在一个线程中运行。所以, Main Thread 所调用的每一个函数,其耗时应该越短越好。而对于比较费时的工作,应该设法交给子线程去做,以避免阻塞主线程(主线程被阻塞,会导致程序假死 现象)。   
     3 、 Android 单线程模型: Android UI 操作并不是线程安全的并且这些操作必须在 UI 线程中执行。如果在子线程中直接修改 UI ,会导致异常。    
 51. 如何将 SQLite 数据库 (dictionary.db 文件 ) 与 apk 文件一起发布 ?    
  解答:可以将 dictionary.db 文件复制到 Eclipse Android 工程中的 res aw 目录中。所有在 res aw 目录中的文件不会被压缩,这样可以直接提取该目录中的文件。可以将 dictionary.db 文件复制到 res aw 目录中   
52. 如何将打开 res aw 目录中的数据库文件 ?    
  解答:在 Android 中不能直接打开 res aw 目录中的数据库文件,而需要在程序第一次启动时将该文件复制到手机内存或 SD 卡的某个目录中,然后再打开该数据库文件。复制的基本方法是使用 getResources().openRawResource 方法获得 res aw 目录中资源的 InputStream 对象,然后将该 InputStream 对象中的数据写入其他的目录中相应文件中。在 Android SDK 中可以使用 SQLiteDatabase.openOrCreateDatabase 方法来打开任意目录中的 SQLite 数据库文件。   
  53. Android中五种数据存储方式分别是什么?他们的特点?   
  (1)SharedPreference,存放较少的五种类型的数据,只能在同一个包内使
         用,生成XML的格式存放在设备中
 (2) SQLite数据库,存放各种数据,是一个轻量级的嵌入式数据库
 (3) File文件,通过读取写入方式生成文件存放数据
 (4) ContentProvider,主要用于让其他应用程序使用保存的数据
 (5) 通过网络获取数据和写入数据到网络存储空间

     答:Android提供了五种存取数据的方式   
  54. 说说 android 中 mvc 的具体体现   
  mvc是model,view,controller的缩写,mvc包含三个部分:
模型(model)对象:是应用程序的主体部分,所有的业务逻辑都应该写在该层。
视图(view)对象:是应用程序中负责生成用户界面的部分。也是在整个mvc架构中用户唯一可以看到的一层,接收用户的输入,显示处理结果。
控制器(control)对象:是根据用户的输入,控制用户界面数据显示及更新model对象状态的部分,控制器更重要的一种导航功能,响应用户出发的相关事件,交给m层处理。
android鼓励弱耦合和组件的重用,在android中mvc的具体体现如下:   
1)视图(view):一般采用xml文件进行界面的描述,使用的时候可以非常方便的引入。
2)控制层(controller):android的控制层的重任通常落在了众多的acitvity的肩上,这句话也就暗含了不要在acitivity中写过多的代码,要通过activity交割model业务逻辑层处理,这样做的另外一个原因是android中的acitivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。
3)模型层(model):对数据库的操作、对网络等的操作都应该在model里面处理,当然对业务计算等操作也是必须放在的该层的。   
55. 简述SharedPreferences存储方式以及SharedPreferences与SQLite数据库的区别   
  SharedPreferences也是一种轻型的数据存储方式,它的本质是基于XML文件存储key-value键值对数据,通常用来存储一些简单的配置信息。其存储位置在/data/data/<包名>/shared_prefs目录下。SharedPreferences对象本身只能读取数据而不支持写入数据,存储修改是通过Editor对象实现。SharedPreferences对象与SQLite数据库相比,免去了创建数据库,创建表,写SQL语句等诸多操作,相对而言更加方便,简洁。但是SharedPreferences也有其自身缺陷,比如其职能存储booleanintfloatlongString五种简单的数据类型,比如其无法进行条件查询等。所以不论SharedPreferences的数据存储操作是如何简单,它也只能是存储方式的一种补充,而无法完全替代如SQLite数据库这样的其他数据存储方式。
  56. 描述handler 机制的原理   
  andriod提供了 Handler 和 Looper 来满足线程间的通信。
Handler 先进先出原则。
Looper类用来管理特定线程内对象之间的消息交换(Message Exchange)。
1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)。
2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper从Message Queue取出)所送来的消息。
3) Message Queue(消息队列):用来存放线程放入的消息。
4)线程:UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。
57. 显式intent和隐式intent的区别是什么(android)   
答:Intent定义:Intent是一种在不同组件之间传递的请求消息,是应用程序发出的请求和意图。作为一个完整的消息传递机制,Intent不仅需要发送端,还需要接收端。
显式Intent定义:对于明确指出了目标组件名称的Intent,我们称之为显式Intent。
隐式Intent定义:对于没有明确指出目标组件名称的Intent,则称之为隐式Intent。
说明:Android系统使用IntentFilter 来寻找与隐式Intent相关的对象。
58. sqlite升级步骤:   
1.自己写一个类继承自SqliteOpenHelper

  2.会实现SqliteOpenHelper的两个方法 onCreate与onUpgrade,google文档对两个回调方法的解释是创建数据库的时候调用与更新数据库的版本的时候调用

  3.Sqlite数据库主要是用来缓存应用的数据,而应用却是一直在更新版本,相应的数据的表的字段也会一直增加会改变或减少

  4.这个时候就需要控制数据库的版本,因为Sqlite数据库中的字段假设新版的应用里面设计的表是10个字段,而缓存却是之前缓存的只有9个字段的话,查询数据库之后的列

  然后取的值会出现空指针异常或报错

  5.所以android中引入了Sqlite数据库的版本,让应用的旧版数据库能够与新版的数据库的字段兼容

  6.为了兼容之前的数据库的版本,只需要在应用的版本更新的时候,添加字段或者删除字段即可

  7.你开发程序当前是1.0.0的版本,该程序用到了数据库,但是版本迭代之后到1.0.1的时候,数据库的某个表添加了某个字段在软件1.0.1的版本就需要升级

  8.数据库升级可以为了能够让旧的数据不能丢,所以不能删除掉之前数据库中的所有数据,那么就需要有地方能够检测到版本的变化,这个跟Android的APP升级是一个道理

  当然这个检测就是在SqliteOpenHelper的onUpgrade方法中
59. 数据库升级应该注意什么?   
软件的1.0版本升级到1.1版本时,老的数据不能丢。那么在1.1版本的程序中就要有地方能够检测出来新的软件版本与老的
  数据库不兼容,并且能够有办法把1.0软件的数据库升级到1.1软件能够使用的数据库。换句话说,要在1.0软件的数据库的那个表中增加那个字段,并赋予这个字段默认值。
60. 程序如何知道数据库需要升级?   
SQLiteOpenHelper类的构造函数有一个参数是int version,它的意思就是指数据库版本号。比如在软件1.0版本中,我们使用SQLiteOpenHelper访问数据库时,

该参数为1,那么数据库版本号1就会写在我们的数据库中。

 到了1.1版本,我们的数据库需要发生变化,那么我们1.1版本的程序中就要使用一个大于1的整数来构造SQLiteOpenHelper类,用于访问新的数据库,比如2。

 当我们的1.1新程序读取1.0版本的老数据库时,就发现老数据库里存储的数据库版本是1,而我们新程序访问它时填的版本号为2,系统就知道数据库需要升级。
61.  android版本适配(如何兼容4.3-2.3版本)   
比如产品设计中想要一些4.3以上的新特效,但是如何去兼容4.3-2.3的用户群体呢,
 前提是我们apk在友盟数据上显示4.3-2.3占有25%的用户群体。
 居于这个的考虑,我们目前的做法就是新设计的页面使用新特效的话需要根据手机版本号判断,
 如果是低版本的手机并且大部分新特效是无法兼容我们展示老页面.
 62. 一个apk如何快速方便的打多个不同包名的产品(多渠道多产品推广)   
 我们市场在推广apk的时候有时候需要根据渠道打不同包名的apk并且这些打出来的apk风格和内容展示以及文字展现略有不同。
   我们现在的做法是,把主工程项目当做libs形式关联到想要打包的工程,这样打不同包名的时候就方便,直接创建一个工程,
   把主工程关联,然后可以在新创建的工程里面略修改一些比如title风格,首页面进入风格
  (因为首页我们做了好几套可以根据类型来判断你走的是哪一个风格),就是一个新的apk出现了。
63. android 适配   
1、不要使用绝对布局

2、尽量使用match_parent 而不是fill_parent 。

3、能够使用权重的地方尽量使用权重(android:layout_weight)

4、如果是纯色背景,尽量使用android的shape 自定义。

5、如果需要在特定分辨率下适配,可以在res目录上新建layout-HxW.xml的文件夹。比如要适配1080*1800的屏幕

(魅族MX3采用此分辨率)则新建layout-1800x1080.xml的文件夹,然后在下面定义布局。Android系统会优先查

找分辨率相同的布局,如果不存在则换使用默认的layout下的布局。
64. ArrayList,Vector,LinkedList的区别   
        ArrayList         Vector          LinkedList   
实现原理 数组               数组             双向链表   
线程安全 否                  是               否
优点     1.数组实现优于遍历  1.数组实现优于遍历  1.节点的增删无需对象的重建
        2.非线程安全,效率较高 2.线程安全      2.空间利用毫无浪费
缺点     1.非线程安全        1.数组中未使用的元素造成空间的浪费   1.遍历效率较低
        2.数组中未使用元素照成了空间的浪费 2.扩容可能引起对象的重建  2.非线程安全
        3.扩容可能引起对象的重建 3.线程安全,效率相对低
        4.增删有可能引起数组元素的移动 4.增删有可能引起数组元素的移动
扩容     0.5倍增量         1倍增量            按需增删
使用场景  1.无线程的要求    1.有线程安全的要求    增删场景较多的时候
          2.遍历较多,增删较少 2.遍历场景较多,增删场景较少   
65. int与Integer的区别   
      int                               Integer
类型    基本类型                          复合类型
默认值     0                                 null
存储      栈(局部变量)堆(成员变量,有待进一步确认)    堆上(只能通过new创建)
方法      基本类型无方法                   有
速度      快(栈上 的操作相对快)            慢
泛型支持    否(java中的泛型不支持,C++中的模板支持)    支持
容器类支持   否(直接使用通常会进行装箱操作)      支持
存在意义      1.历史原因(顺延C/C++中存在)2.方便快速(无需new)   基本类型int的包装类,提供了对泛型,容器类的支持   
66. RuntimeException与普通异常,error的区别。   
  Checked Exception:在编译时就能够被Java编译器所检测到的。   
  UncheckedException:则是编译时,java编译器不能检查到。   
          RuntimeException        普通Exception           Error
受控异常        否                     是                     否
产生原因        开发者的编程错误          由于外界环境所限,本身潜在的一些问题      Java运行时的系统错误,资源耗尽,是一种严重的,程序无法修复的问题  
例子        NullPointerException      ClassNotFoundException        VirtualMachineError
          ArrayOutOfIndexException    IOException                   StackOverflowError
          ClassCastException          FileNotFoundException         OutOfMemoryError
          ArithmeticException
          UnsupportedOperationException
67. final,finalize,finally的区别    
    final:关键字,表不变 方法:方法不可Override  类:不可被继承  基本类型量:常量,值不可变  符合类型量:引用不可变,即引用的值不可变   
    finally:关键字,Java异常处理机制的一部分,在异常发生时,用来提供一个必要的清理的机会。   
    finalize:Object类的方法 意义:Java技术允许使用finalize()方法在垃圾回收器将对象回收之前,做一些必要的清理操作。
    调用前提:这个对象确定没有被引用到。
    工作原理:
        垃圾收集器准备好释放对象占用的空间。
        首先调用其finalize方法。
        下一次垃圾收集过程中,真正回收内存。
    不确定性:
        finalize的执行时间是不缺定的。
        一个对象引用另一个对象,并不能保证finalize的方法按照特定的执行顺序。
68. Override,Overload   
                Override            Overload
    签名+返回值      相同              方法名相同,签名不同
    关系            父子类继承关系       通常是同一类层次中
    识别            运行时多态           编译时多态
                    根据具体的对象       由对象的外观类型(即声明类型)决定
                    查询对象的虚方法表,确定调用关系
    修饰符限制         非private        无特别
                      非staticfinal
   异常关系            子类方法不能抛出被父类方法更多的异常   无特别
   可见性关系        子类不能比父类访问权限更窄(里氏替换原则决定)     无特别
59. Collection Collections   
  Collection:接口,集合类的接口,一个契约,提供了集合基本的大小,添加,清除,遍历方法等。
  Collections:工具类,提供了很多静态方法,给集合提供一些查询,比较,排序,交换,线程安全化等方法。
60. sleep方法和wait方法的区别   
                    wait                        sleep
  所属类               Object                    Thread
  意义                让线程挂起                   让线程休眠指定的时间
  释放锁               是                         否(这个跟锁本来就没有关系)
  恢复            1.有参:wait指定时间2.无参:等待其他线程notify   1.根据参数长度自动恢复。2.异常打断
  使用限制         wait,notify必须持有当前对象锁的情况下调用   无特别
  抛出异常            否                           是
  静态方法           否                           是
61. HashMap和Hashtable的区别。    
    HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。   
    HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。   
    HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。
62. 算法 1.冒泡 2.选择 3.插入 4.并归 5.快速
63. 深入探索Java工作原理:JVM内存回收及其他   
    1.Java虚拟机:   
    Java源程序通过编译器编译成.Class文件,然后java虚拟机中的java 解释器负责将字节码文件解释成为特定的机器码进行运行。
      java是一种半编译半解释型语言。半编译是指:java源代码,会经过javac命令变成 .class文件。半解释是指: .class文件被jvm解释的过程。也就是因为jvm的半解释才有了java的动态语言特性:反射和annotation。
    2.和android区别   
    alvik有自己的libdex库负责对.class进行处理。libdex主要对.class进行处理生成自己的dex文件。主要做的工作是,对虚拟机指令进行转换(dalvik是基于寄存器的,sun虚拟机是基于栈的),对类的静态数据进行归类、压缩。dalvik基于寄存器,而JVM基于stack,Dalvik执行的是特有的DEX文件格式,而JVM运行的是*.class文件格式。
    3.优势   
    1、在编译时提前优化代码而不是等到运行时
    2、 虚拟机很小,使用的空间也小;被设计来满足可高效运行多种虚拟机实例。
    Java虚拟机的建立需要针对不同的软硬件平台来实现,既要考虑处理器的型号,也要考虑操作系统的种类。由此在SPARC结构、X86结构、MIPS和PPC等嵌入式处理芯片上,在UNIX、Linux、Windows和部分实时操作系统上都可实现Java虚拟机。
    4.无用内存自动回收机制
    而在Java运行环境中,始终存在着一个系统级的线程,专门跟踪内存的使用情况, 定期检测出不再使用的内存,并自动进行回收,避免了内存的泄露,也减轻了程序员的工作量。
    5.JVM
    JVM是Java平台的核心,为了让编译产生的字节码能更好地解释与执行,因此把JVM分成了6个部分:JVM解释器、指令系统、寄存器、栈、存储区和碎片回收区。
64. Android框架  http://www.cnblogs.com/forlina/archive/2011/06/29/2093332.html
65. 基于android的Socket通信
    一、Socket通信简介
    Android 与服务器的通信方式主要有两种,一是Http通信,一是Socket通信。两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立 连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据。而Socket通信则是在双方建立起连接后就可以直接进行数据的传输,在连接时可 实现信息的主动推送,而不需要每次由客户端想服务器发送请求。 那么,什么是socket?Socket又称套接字,在程序内部提供了与外界通信的端口,即端口通信。通过建立socket连接,可为通信双方的数据传输 传提供通道。socket的主要特点有数据丢失率低,使用简单且易于移植。
    1.2Socket的分类
     根据不同的的底层协议,Socket的实现是多样化的。本指南中只介绍TCP/IP协议族的内容,在这个协议族当中主要的Socket类型为流套接字 (streamsocket)和数据报套接字(datagramsocket)。流套接字将TCP作为其端对端协议,提供了一个可信赖的字节流服务。数据 报套接字使用UDP协议,提供数据打包发送服务。
    二、Socket 基本通信模型 【http://www.itlanbao.com/ns/news.aspx?s=600031】
    三、Socket基本实现原理
    3.1基于TCP协议的Socket
      服务器端首先声明一个ServerSocket对象并且指定端口号,然后调 用Serversocket的accept()方法接收客户端的数据。accept()方法在没有数据进行接收的处于堵塞状态。 (Socketsocket=serversocket.accept()),一旦接收到数据,通过inputstream读取接收的数据。
        客户端创建一个Socket对象,指定服务器端的ip地址和端口号 (Socketsocket=newSocket("172.168.10.108",8080);),通过inputstream读取数据,获取服务器 发出的数据(OutputStreamoutputstream=socket.getOutputStream()),最后将要发送的数据写入到 outputstream即可进行TCP协议的socket数据传输。
    3.2基于UDP协议的数据传输
    服务器端首先创建一个DatagramSocket对象,并且指点监听的端 口。接下来创建一个空的DatagramSocket对象用于接收数据 (bytedata[]=newbyte[1024;]DatagramSocketpacket=newDatagramSocket(data,data.length)),
    使用DatagramSocket的receive方法接收客户端发送的数据,receive()与serversocket的accepet()类似, 在没有数据进行接收的处于堵塞状态。
    客户端也创建个DatagramSocket对象,并且指点监听的端口。接 下来创建一个InetAddress对象,这个对象类似与一个网络的发送地址
    (InetAddressserveraddress=InetAddress.getByName("172.168.1.120"))
    .定义要发送的 一个字符串,创建一个DatagramPacket对象,并制定要讲这个数据报包发送到网络的那个地址以及端口号,
    最后使用DatagramSocket 的对象的send()发送数据。
    *(Stringstr="hello";bytedata[]=str.getByte(); DatagramPacketpacket=new DatagramPacket(data,data.length,serveraddress,4567);socket.send(packet);)
    四、android 实现socket简单通信
    4.1使用TCP协议通信
      android端实现:
        protected void connectServerWithTCPSocket() {  
            Socket socket;  
            try {// 创建一个Socket对象,并指定服务端的IP及端口号  
                socket = new Socket("192.168.1.32", 1989);  
                // 创建一个InputStream用户读取要发送的文件。  
                InputStream inputStream = new FileInputStream("e://a.txt");  
                // 获取Socket的OutputStream对象用于发送数据。  
                OutputStream outputStream = socket.getOutputStream();  
                // 创建一个byte类型的buffer字节数组,用于存放读取的本地文件  
                byte buffer[] = new byte[4 * 1024];  
                int temp = 0;  
                // 循环读取文件  
                while ((temp = inputStream.read(buffer)) != -1) {  
                    // 把数据写入到OuputStream对象中  
                    outputStream.write(buffer, 0, temp);  
                }  
                // 发送读取的数据到服务端  
                outputStream.flush();  

                /** 或创建一个报文,使用BufferedWriter写入,看你的需求 **/  
    //          String socketData = "[2143213;21343fjks;213]";  
    //          BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(  
    //                  socket.getOutputStream()));  
    //          writer.write(socketData.replace("\n", " ") + "\n");  
    //          writer.flush();  
                /************************************************/  
            } catch (UnknownHostException e) {  
                e.printStackTrace();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    服务器端简单实现:
    public void ServerReceviedByTcp() {  
        // 声明一个ServerSocket对象  
        ServerSocket serverSocket = null;  
        try {  
            // 创建一个ServerSocket对象,并让这个Socket在1989端口监听  
            serverSocket = new ServerSocket(1989);  
            // 调用ServerSocket的accept()方法,接受客户端所发送的请求,  
            // 如果客户端没有发送数据,那么该线程就停滞不继续  
            Socket socket = serverSocket.accept();  
            // 从Socket当中得到InputStream对象  
            InputStream inputStream = socket.getInputStream();  
            byte buffer[] = new byte[1024 * 4];  
            int temp = 0;  
            // 从InputStream当中读取客户端所发送的数据  
            while ((temp = inputStream.read(buffer)) != -1) {  
                System.out.println(new String(buffer, 0, temp));  
            }  
            serverSocket.close();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
    4.2使用UDP协议通信
      客户端发送数据实现:
      protected void connectServerWithUDPSocket() {  
        DatagramSocket socket;  
        try {  
            //创建DatagramSocket对象并指定一个端口号,注意,如果客户端需要接收服务器的返回数据,  
            //还需要使用这个端口号来receive,所以一定要记住  
            socket = new DatagramSocket(1985);  
            //使用InetAddress(Inet4Address).getByName把IP地址转换为网络地址    
            InetAddress serverAddress = InetAddress.getByName("192.168.1.32");  
            //Inet4Address serverAddress = (Inet4Address) Inet4Address.getByName("192.168.1.32");    
            String str = "[2143213;21343fjks;213]";//设置要发送的报文    
            byte data[] = str.getBytes();//把字符串str字符串转换为字节数组    
            //创建一个DatagramPacket对象,用于发送数据。    
            //参数一:要发送的数据  参数二:数据的长度  参数三:服务端的网络地址  参数四:服务器端端口号   
            DatagramPacket packet = new DatagramPacket(data, data.length ,serverAddress ,10025);    
            socket.send(packet);//把数据发送到服务端。    
        } catch (SocketException e) {  
            e.printStackTrace();  
        } catch (UnknownHostException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }    
    }  


    客户端接收服务器返回的数据:
    public void ReceiveServerSocketData() {  
        DatagramSocket socket;  
        try {  
            //实例化的端口号要和发送时的socket一致,否则收不到data  
            socket = new DatagramSocket(1985);  
            byte data[] = new byte[4 * 1024];  
            //参数一:要接受的data 参数二:data的长度  
            DatagramPacket packet = new DatagramPacket(data, data.length);  
            socket.receive(packet);  
            //把接收到的data转换为String字符串  
            String result = new String(packet.getData(), packet.getOffset(),  
                    packet.getLength());  
            socket.close();//不使用了记得要关闭  
            System.out.println("the number of reveived Socket is  :" + flag  
                    + "udpData:" + result);  
        } catch (SocketException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
    服务器接收客户端实现:
    public void ServerReceviedByUdp(){  
        //创建一个DatagramSocket对象,并指定监听端口。(UDP使用DatagramSocket)    
        DatagramSocket socket;  
        try {  
            socket = new DatagramSocket(10025);  
            //创建一个byte类型的数组,用于存放接收到得数据    
            byte data[] = new byte[4*1024];    
            //创建一个DatagramPacket对象,并指定DatagramPacket对象的大小    
            DatagramPacket packet = new DatagramPacket(data,data.length);    
            //读取接收到得数据    
            socket.receive(packet);    
            //把客户端发送的数据转换为字符串。    
            //使用三个参数的String方法。参数一:数据包 参数二:起始位置 参数三:数据包长    
            String result = new String(packet.getData(),packet.getOffset() ,packet.getLength());    
        } catch (SocketException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }    
    }  
    五、总结:
    使用UDP方式android端和服务器端接收可以看出,其实android端和服务器端的发送和接收大庭相径,只要端口号正确了,相互通信就没有问题,TCP使用的是流的方式发送,UDP是以包的形式发送。
    Android操作HTTP实现与服务器通信 【http://www.cnblogs.com/hanyonglu/archive/2012/02/19/2357842.html】
# Android四大组件
  http://www.cnblogs.com/pepcod/archive/2013/02/11/2937403.html
# 三级缓存
  http://blog.saymagic.cn/2015/01/30/android-pic-three-cache.html
# 图片的处理和优化
  http://www.cnblogs.com/elliotta/p/3633752.html
  http://blog.csdn.net/yudajun/article/details/9323941
# Android5.0新特性
  技术方面说明
  http://blog.csdn.net/lwyygydx/article/details/41870377
  功能改进方面说明
  http://digi.tech.qq.com/a/20150121/012030.htm
# 图文混排
  http://blog.csdn.net/fancylovejava/article/details/39927539
# 第三方框架:xUtils,Gson  极光推送 第三方登录
  友盟第三方登录
  http://blog.umeng.com/uncategorized/4160.html
  第三方登录案例
  http://blog.csdn.net/yueqinglkong/article/details/15028041
# 线程池
  http://blog.csdn.net/lyf_007217/article/details/8542238
  http://www.cnblogs.com/devinzhang/p/3856200.html
# lru算法底层
  http://www.360doc.com/content/14/0402/09/10504424_365635496.shtml
  http://blog.csdn.net/androidzhaoxiaogang/article/details/7910364
# ListView的局部刷新
  http://www.2cto.com/kf/201409/335964.html
  http://blog.csdn.net/u200814499/article/details/40391443
# 及时通讯
  http://blog.csdn.net/jiangliloveyou/article/details/9849775
  http://blog.csdn.net/lnb333666/article/details/7471292
  http://skywen.iteye.com/blog/1811310
# GC原理
  http://blog.csdn.net/wuqiong_524itcast/article/details/25378685
  http://blog.csdn.net/wangshione/article/details/8490245
  http://blog.csdn.net/lnb333666/article/details/8031770
  1.垃圾收集算法的核心思想
  Java语言建立了垃圾收集机制,用以跟踪正在使用的对象和发现并回收不再使用(引用)的对象。该机制可以有效防范动态内存分配中因内存垃圾过多而引发的内存耗尽,以及不恰当的内存释放所造成的内存非法引用。
   垃圾收集算法的核心思想是:对虚拟机可用内存空间,即堆空间中的对象进行识别,如果对象正在被引用,那么称其为存活对象,反之,如果对象不再被引用,则 为垃圾对象,可以回收其占据的空间,用于再分配。垃圾收集算法的选择和垃圾收集系统参数的合理调节直接影响着系统性能,因此需要开发人员做比较深入的了解。
      触发主GC(Garbage Collector)的条件 JVM进行次GC的频率很高,但因为这种GC占用时间极短,所以对系统产生的影响不大。更值得关注的是主GC的触发条件,因为它对系统影响很明显。总的来说,有两个条件会触发主GC:
    ①当应用程序空闲时,即没有应用线程在运行时,GC会被调用。因为GC在优先级最低的线程中进行,所以当应用忙时,GC线程就不会被调用,但以下条件除外。
    ②Java堆内存不足时,GC会被调用。当应用线程在运行,并在运行过程中创建新对象,若这时内存空间不足,JVM就会强制地调用GC线程,以 便回收内存用于新的分配。若GC一次之后仍不能满足内存分配的要求,JVM会再进行两次GC作进一步的尝试,若仍无法满足要求,则 JVM将报“out of memory”的错误,Java应用将停止。
  3.减少GC开销的措施
  根据上述GC的机制,程序的运行会直接影响系统环境的变化,从而影响GC的触发。若不针对GC的特点进行设计和编码,就会出现内存驻留等一系列负面影响。为了避免这些影响,基本的原则就是尽可能地减少垃圾和减少GC过程中的开销。具体措施包括以下几个方面:
    (1)不要显式调用System.gc()
    此函数建议JVM进行主GC,虽然只是建议而非一定,但很多情况下它会触发主GC,从而增加主GC的频率,也即增加了间歇性停顿的次数。
    (2)尽量减少临时对象的使用
    临时对象在跳出函数调用后,会成为垃圾,少用临时变量就相当于减少了垃圾的产生,从而延长了出现上述第二个触发条件出现的时间,减少了主GC的机会。
    (3)对象不用时最好显式置为Null
    一般而言,为Null的对象都会被作为垃圾处理,所以将不用的对象显式地设为Null,有利于GC收集器判定垃圾,从而提高了GC的效率。
    (4)尽量使用StringBuffer,而不用String来累加字符串(详见blog另一篇文章JAVA中String与StringBuffer)
    由于String是固定长的字符串对象,累加String对象时,并非在一个String对象中扩增,而是重新创建新的String对象,如 Str5=Str1+Str2+Str3+Str4,这条语句执行过程中会产生多个垃圾对象,因为对次作“+”操作时都必须创建新的String对象,但 这些过渡对象对系统来说是没有实际意义的,只会增加更多的垃圾。避免这种情况可以改用StringBuffer来累加字符串,因StringBuffer 是可变长的,它在原有基础上进行扩增,不会产生中间对象。
    (5)能用基本类型如Int,Long,就不用Integer,Long对象
    基本类型变量占用的内存资源比相应对象占用的少得多,如果没有必要,最好使用基本变量。
    (6)尽量少用静态对象变量
    静态变量属于全局变量,不会被GC回收,它们会一直占用内存。
    (7)分散对象创建或删除的时间
    集中在短时间内大量创建新对象,特别是大对象,会导致突然需要大量内存,JVM在面临这种情况时,只能进行主GC,以回收内存或整合内存碎片, 从而增加主GC的频率。集中删除对象,道理也是一样的。它使得突然出现了大量的垃圾对象,空闲空间必然减少,从而大大增加了下一次创建新对象时强制主GC 的机会。   
  gc()函数的作用只是提醒虚拟机:程序员希望进行一次垃圾回收。但是它不能保证垃圾回收一定会进行,而且具体什么时候进行是取决于具体的虚拟机的,不同的虚拟机有不同的对策。在Davilk中,给程序分配的内存是根据机型厂商的不同而不同(现在大部分为32MB),在VM内部会将内存分为:java使用的内存,Native使用的内存,他们之间不能共享,当某一方面不足的时候必须向VM申请,而不能直接使用另外一个的内存。
  # 出现内存泄漏的可能性:
  出现情况:
  1. 数据库的cursor没有关闭
  2.构造adapter时,没有使用缓存contentview
    衍生listview的优化问题-----减少创建view的对象,充分使用contentview,可以使用一静态类来优化处理getview的过程
  3.Bitmap对象不使用时采用recycle()释放内存
  4.activity中的对象的生命周期大于activity
  调试方法: DDMS==> HEAPSZIE==>dataobject==>[Total Size]
# Android 内存浅析【管理、机制、分析】
  一、 Android的内存机制
    Android的程序由Java语言编写,所以Android的内存管理与Java的内存管理相似。程序员通过new为对象分配内存,所有对象在java 堆内分配空间;然而对象的释放是由垃圾回收器来完成的。C/C++中的内存机制是“谁污染,谁治理”,java的就比较人性化了,给我们请了一个专门的清 洁工(GC)
  二、GC是什么? 为什么要有GC?   
      GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以 自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。
  三、垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?
      对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理堆(heap)中的所有对 象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可达的"。当GC确定一些对象为"不可达"时,GC就有责任回收这些内存空间。可以。程序员可 以手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。间而忘记了释放。如果程序中存在对无用对象的引用,那么这些对象就会驻留内存,消耗内存,因为无法让垃圾回收器GC验证这些对象是否不再需要。如果存在对象的引用,这个对象就被定义为"有效的活动",同时不会被释放。要确定对象所占内存将被回收,我们就要务必确认该对象不再会被使用。典型的做法就是把对象数据成员设为null或者从集合中移除该对象。但当局部变量不需要时,不需明显的设为null,因为一个方法执行完毕时,这些引用会自动被清理。

    Vector v = new Vector(10);  
            for (int i = 1; i < 100; i++) {  
                Object o = new Object();  
                v.add(o);  
                o = null;  
            }// 此时,所有的Object对象都没有被释放,因为变量v引用这些对象。  
    Java 内存泄露的根本原因就是 保存了不可能再被访问的变量类型的引用
  六、Android的内存溢出
  Android的内存溢出是如何发生的?
  Android的虚拟机是基于寄存器的Dalvik,它的最大堆大小一般是16M,有的机器为24M。也就是说我们所能利用的内存空间是有限的。如果我们的内存占用超过了一定的水平就会出现OutOfMemory的错误。
  为什么会出现内存不够用的情况呢?我想原因主要有两个:
  由于我们程序的失误,长期保持某些资源(如Context)的引用,造成内存泄露,资源造成得不到释放。保存了多个耗用内存过大的对象(如Bitmap),造成内存超出限制。
# 在Android适配方案小结
    600dp的含义是:代表这个设备的最短的那一边。
    获取设备的最短边的代码是:Configuration config = getResources().getConfiguration();
    int smallestScreenWidth = config.smallestScreenWidthDp;
    这个时候拿smallestScreenWidth 与600想比较就可以知道该设备能否读取里面的资源了。
    除此之外,为了方便适配,在编码时我们还应该注意什么呢,主要有以下几点:
    除此之外,为了方便适配,在编码时我们还应该注意什么呢,主要有以下几点:

    (1)多使用权重(android:layout_weight)
    尤其是在tab切换布局,listview title及Item布局等情况下;
    (2)设置宽度和高度时,尽量使用match_parent和wrap_content,避免把控件宽高设死;
    (3)父容器布局选用
    多使用RelativeLayout,FrameLayout,GridLayout等,减少布局层次。当然,在使用
    权重时,得采用LinearLayout;
    (4) 在xml里,设置高度、宽度采用dp(dip),设置字体采用sp。
    (应该注意,在代码里面,我们写的setHeight(...)单位是px)
    那么在具体开发中,我们应该注意什么呢。
    首先,我们必须要知道,其实适配的关键在于两点:
    (1)不同分辨率设备的适配,这点在单位的使用上用dp、sp以及图片资源存放于不同的drawable文件夹就可以解决问题;
    (2)不同尺寸的适配,这点主要靠将相关值以及布局文件放置于不同的文件夹中来解决。
    2.1 values文件夹
    可以在工程下创建不同的values文件夹:values-sw480dp, values-sw600dp,
    values-sw720dp-land等。比如一个控件的宽度,在10寸pad上是10dp,在8寸pad
    上是5dp。这时,你可以定义一个变量,button_width,然后在values-sw600dp
    下写5dp,在values-sw720-land下写
    10dp。这样就达到了在不同尺寸pad上,
    相应控件大小不一样的效果。
    2.1 layout文件夹
    如果在不同尺寸设备上展示的布局有明显差别,仅仅用values不同已经难以控制,
    那么就可以考虑写不同的布局文件置于不同的layout文件夹下,android会根据设备
    尺寸去加载相应文件夹下的布局文件。如:layout-sw480dp,layout-sw600dp,
    layout-sw700dp等。
    值得注意的是,如果不是很有必要,尽量采用2.1方案,方便维护。如果尺寸和分辨率都不同,
    那么就要结合(1)、(2)考虑了。
    (补充:其实values文件夹和layout文件夹不仅仅是根据尺寸判断,也和分辨率有关,不过在通常情况下,
    综合计算考虑,仅根据尺寸判断就可以了:
# Java 基础
    1int a = 1;
    int m1 = ++a +3;
    结果 :m1 = 5;a=2;
    ++a表示先赋值
    2:
    int a = 1;
    int m = a+++3;
    结果 m = 4; a= 2;
    a++表示后赋值
    3:
     m<<2 表示 m*2*2
     m<< 3 表示 m*2*2*2
     int result =5<<2 ;//a  20  5*2*2 ;
     int result1 =6<<3 ;//   48  6*2*2*2
     int result2 =7<<4 ;//112  7*2*2*2*2
     4:
    a++ 表示a+1
    int a = 2;
    int result = (a++ > 2)?(++a):(a+=3);
    结果是//6
    5. 下面程序的运行结果是()
    String str1 = "hello";String str2 = "he" + new String("llo");System.err.println(str1 == str2);
    答案:false
    解析:因为str2中的llo是新申请的内存块,而==判断的是对象的地址而非值,所以不一样。如果是String str2 .equals(str1),那么就是true了。
    4. 下列说法正确的有()
    A. class中的constructor不可省略
    B. constructor必须与class同名,但方法不能与class同名
    C. constructor在一个对象被new时执行
    D.一个class只能定义一个constructor
    答案:C
    解析:这里可能会有误区,其实普通的类方法是可以和类名同名的,和构造方法唯一的区分就是,构造方法没有返回值。

    下面程序的运行结果:()
    public static void main(String args[]) {        Thread t = new Thread() {             public void run() {                pong();            }        };       
      t.run();        System.out.print("ping");     }     static void pong() {         System.out.print("pong");     }
    A pingpong        B pongping       C pingpong和pongping都有可能       D 都不输出
    答案:B
    解 析:这里考的是Thread类中start()和run()方法的区别了。start()用来启动一个线程,当调用start方法后,系统才会开启一个新 的线程,进而调用run()方法来执行任务,
    而单独的调用run()就跟调用普通方法是一样的,已经失去线程的特性了。因此在启动一个线程的时候一定要使 用start()而不是run()。
    7. 下列属于关系型数据库的是()
    A. Oracle    B MySql    C IMS     D MongoDB
    答案:AB
    解答:IMS(Information Management System )数据库是IBM公司开发的两种数据库类型之一;
    一种是关系数据库,典型代表产品:DB2;
    另一种则是层次数据库,代表产品:IMS层次数据库。
    非关系型数据库有MongoDB、memcachedb、Redis等。
    8. GC线程是否为守护线程?()
    答案:是
    解析:线程分为守护线程和非守护线程(即用户线程)。
    只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作。
    守护线程最典型的应用就是 GC (垃圾回收器)
    9. volatile关键字是否能保证线程安全?()
    答案:不能
    解析:volatile关键字用在多线程同步中,可保证读取的可见性,JVM只是保证从主内存加载到线程工作内存的值是最新的读取值,而非cache中。但多个线程对
    volatile的写操作,无法保证线程安全。例 如假如线程1,线程2 在进行read,load 操作中,发现主内存中count的值都是5,那么都会加载这个最新的值,在线程1堆count进行修改之后,
    会write到主内存中,主内存中的 count变量就会变为6;线程2由于已经进行read,load操作,在进行运算之后,也会更新主内存count的变量值为6;导致两个线程及时用 volatile关键字修改之后,还是会存在并发的情况。
    10. 下列说法正确的是(AC)
    A LinkedList继承自List
    B AbstractSet继承自Set
    C HashSet继承自AbstractSet
    D WeakMap继承自HashMap
    解析:下面是一张下载的Java中的集合类型的继承关系图,一目了然。 http://www.itlanbao.com/ns/news.aspx?s=600034
    11. 存在使i + 1 < i的数吗()
      答案:存在
      解析:如果i为int型,那么当i为int能表示的最大整数时,i+1就溢出变成负数了,此时不就<i了吗。
      扩展:存在使i > j || i <= j不成立的数吗()
      答案:存在
      解析:比如Double.NaN或Float.NaN,
      12. 0.6332的数据类型是()
      A float     B double     C Float      D Double
      答案:B
      解析:默认为double型,如果为float型需要加上f显示说明,即0.6332f、
      13. 下面哪个流类属于面向字符的输入流(  )
      A  BufferedWriter           B  FileInputStream          C  ObjectInputStream          D  InputStreamReader
       答案:D
       解析:Java的IO操作中有面向字节(Byte)和面向字符(Character)两种方式。
      面向字节的操作为以8位为单位对二进制的数据进行操作,对数据不进行转换,这些类都是InputStream和OutputStream的子类。
      面向字符的操作为以字符为单位对数据进行操作,在读的时候将二进制数据转为字符,在写的时候将字符转为二进制数据,这些类都是Reader和Writer的子类。
      总结:以InputStream(输入)/OutputStream(输出)为后缀的是字节流;
      以Reader(输入)/Writer(输出)为后缀的是字符流。

    下面程序能正常运行吗()
    public class NULL {     public static void haha(){        System.out.println("haha");    }    public static void main(String[] args) {        ((NULL)null).haha();    } }
    答案:能正常运行
    解析:输出为haha,因为null值可以强制转 换为任何java类类型,(String)null也是合法的。但null强制转换后是无效对象,其返回值还是为null,而static方法的调用是和 类名绑定的,
    不借助对象进行访问所以能正确输出。反过来,没有static修饰就只能用对象进行访问,使用null调用对象肯定会报空指针错了。这里和 C++很类似。

    下面程序的运行结果是什么()  
     class HelloA {     public HelloA() {        System.out.println("HelloA");    }        { System.out.println("I'm A class"); }     
    static { System.out.println("static A"); } }public class HelloB extends HelloA {    public HelloB() {        System.out.println("HelloB");    }
    { System.out.println("I'm B class"); }  
    static { System.out.println("static B"); }        public static void main(String[] args) {      new HelloB();    } }
    答案:
    static Astatic BI'm A classHelloAI'm B classHelloB
    解析:说实话我觉得这题很好,考查静态语句块、构造语句块(就是只有大括号的那块)以及构造函数的执行顺序。
    对象的初始化顺序:(1)类加载之后,按从上到下(从父类到子类)执行被static修饰的语句;(2)当static语句执行完之后,再执行main方法;
    (3)如果有语句new了自身的对象,将从上到下执行构造代码块、构造器(两者可以说绑定在一起)。
    下面稍微修改下上面的代码,以便更清晰的说明情况:
    class HelloA {     public HelloA() {        System.out.println("HelloA");    }        { System.out.println("I'm A class"); }  
    static { System.out.println("static A"); } }public class HelloB extends HelloA {    public HelloB() {        System.out.println("HelloB");    }      
     { System.out.println("I'm B class"); }        static { System.out.println("static B"); }        public static void main(String[] args) {         System.out.println("-------main start-------");       
     new HelloB();        new HelloB();        System.out.println("-------main end-------");    }}
    static Astatic B-------main start-------I'm A classHelloAI'm B classHelloBI'm A classHelloAI'm B classHelloB-------main end-------


    Java7中的switch支持String的实现细节
    在Java7之前,switch只能支持 byteshortcharint或者其对应的封装类以及Enum类型。在Java7中,呼吁很久的String支持也终于被加上了。
    public class Test {     public void test(String str) {        switch(str) {        case "abc":            System.out.println("abc");            break;        case "def":     
    System.out.println("def");            break;        default:            System.out.println("default");        }    } }

    516进制数必须以 0x开头
    &是位操作符,“按位与”
    1转成二进制 01
    2转成二进制 10  
    与运算符
    与运算符用符号“&”表示,其使用规律如下:
    两个操作数中位都为1,结果才为1,否则结果为0,例如下面的程序段。
    public class data13
    {
    public static void main(String[] args)
    {
    int a=129;
    int b=128;
    System.out.println("a 和b 与的结果是:"+(a&b));
    }
    }
    运行结果
    a 和b 与的结果是:128
    下面分析这个程序:
    “a”的值是129,转换成二进制就是10000001,而“b”的值是128,转换成二进制就是10000000。根据与运算符的运算规律,只有两个位都是1,结果才是1,可以知道结果就是10000000,即1282*2*2*2*2*2*2    
    int a = 1234566;
    查询a的二进制Integer.toBinaryString(a);

# 学生面试被问到的问题总结
  ## 1. 网络传输数据如何加密,比如账户密码,视频?
  可以这么回答:
  进行安全保证的方式有很多种,如果进行简单的加密可以使用MD5或者DES,但是这些都是相对的,
  如果在开发安全性较高的应用时,可以考虑模仿HTTP协议那样,自定义一个协议,
  然后封装一下,在协议里使用时间戳+算法加密技术提高安全系数.
  Android网络传输中必用的两个加密算法:MD5 和 RSA
  答案参考:http://blog.csdn.net/yanzi1225627/article/details/26508035
  ## 2. 支付功能如何实现?
  回答:
    目前主流的支付有三大,微信支付,支付宝支付,第三方银联支付。
   如果是我,我的回答是,我做android的目前只是用到第三方开放平台来实现接入这些支付功能,
   但是我不知道这些第三方支付功能具体怎么实现的,这个我真不知道,没研究。
   如果是接入第三方支付功能的话就比较简单了:参考文章http://blog.163.com/benben_long/blog/static/19945824320142279427395/
  支付宝集成:
    注意事项
    1.添加android.permission.INTERNET权限和android.permission.ACCESS_NETWORK_STATE权限
    2.代码中出现注释的地方重点看,没注释的地方可以不看
    3.想获取支付宝合作商户ID,及支付宝公钥请点击支付宝链接,生成密钥及PKCS8转码工具在文档中
      微信支付集成注意:参考:http://blog.csdn.net/jdsjlzx/article/details/47422279
        1.在你的项目测试微信的组件(分享、支付等)的时候,一定要用你自己的keystore签名出来测试,
          如果用debug.keystore肯定是不成功的,
        2.支付成功通知:在WXPayEntryActivity的OnResp中处理,不能以微信返回的通知界面为准
         (我遇到的情况,网络不稳定的时候,微信返回界面提示支付失败,但是收到微信通知其实已经支付成功了),
          必须要去自己的服务器查询支付状态,这里微信建议用轮循机制去查询
    @Override
    public void onResp(BaseResp resp) {
        Log.d(TAG, "onPayFinish, errCode = " + resp.errCode);
        if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle(R.string.app_tip);
            builder.setMessage(getString(R.string.pay_result_callback_msg, resp.errStr +";code=" + String.valueOf(resp.errCode)));
            builder.show();
        }
    }
    ## 3. 在开发中你都遇到了哪些难题,如何解决的?
    如何降低apk包的大小,
    apk大小,跟你工程文件大小有直接关系,其中关系最为密切的还是你的图片多少,图片上能用.9处理的图片尽量用。
    如果你一个apk需要适配多种手机,那么你最好只搞一套图片,另外图片的大小也应该做适当压缩,
    保证图片显示质量的前提下,尽量优化图片的存储空间 。
     1 删除项目中没有到的文件,包括资源文件,java代码等等
     2 避免jar包的重复引用
     3 可以考虑压缩一下图片,前提是尽量保持图片别失真。

     ## 4.android 适配
     适配也是一个头疼的事,去年年底我们就开始正对720为主流做适配了,详细适配 百度
  还有有的面试官会问你,你们设计师出的图时根据ios的出还是android的出图
  有几种回答,
 (1)直接根据android的出图直接做一套720*12802)根据ios出图
    众所周知iOS设计的像素尺寸是640*960/1136,Android主流的hdpi模式下的像素尺寸是480*800。如图,
   他们的换算关系是,iOS像素尺寸的75%是Android的像素尺寸

    大概算法,大家可以看看:
  其实经过以上整个过程之后,我们已经得出了一个更简单的换算关系:iOS像素尺寸*75%=Android像素尺寸,
    Android像素尺寸*2/3=Android的dp尺寸。进而得出:iOS像素尺寸*75%*2/3=Android的dp尺寸。
    所以,iOS里一个宽600px的东西,在Android的hdpi模式下,正好300dp,正好是50%,很容易算是吧?

     简单说一下:
    一、关于布局适配
    1、不要使用绝对布局
    2、尽量使用match_parent 而不是fill_parent 。
    3、能够使用权重的地方尽量使用权重(android:layout_weight)
    4、如果是纯色背景,尽量使用android的shape 自定义。
    5、如果需要在特定分辨率下适配,可以在res目录上新建layout-HxW.xml的文件夹。比如要适配1080*1800的屏幕
    (魅族MX3采用此分辨率)则新建layout-1800x1080.xml的文件夹,然后在下面定义布局。Android系统会优先查找分
    辨率相同的布局,如果不存在则换使用默认的layout下的布局。

    ## 5.一个apk如何快速方便的打多个不同包名的产品(多渠道多产品推广)
    我们市场在推广apk的时候有时候需要根据渠道打不同包名的apk并且这些打出来的apk风格和内容展示以及文字展现略有不同。
  我们现在的做法是,把主工程项目当做libs形式关联到想要打包的工程,这样打不同包名的时候就方便,直接创建一个工程,
  把主工程关联,然后可以在新创建的工程里面略修改一些比如title风格,首页面进入风格
 (因为首页我们做了好几套可以根据类型来判断你走的是哪一个风格),就是一个新的apk出现了。
  ##  6.如何在webview中实现点击事件的监听处理?
  http://blog.csdn.net/zzf112/article/details/19618101
  ## 1、联网请求的时候HTTP协议的哪个部分耗时比较多,导致APP运行缓慢,该怎么优化
      这个问题问得应该有问题,个人觉得你需要把http协议原理给他理清楚,这个问题都是与网络快慢有关的,在与服务器交互的时候尽量减少数据量,
    这篇文章不错:blog.csdn.net/lmh12506/article/details/7794512
    http://www.cnblogs.com/jdsjlzx/archive/2011/07/25/2116351.html
## 2、集成环信的及时通讯SDK如果遇到消息遗漏或者消息重复该怎么解决
## 3、如何实现上传和离线上传
    Android离线数据同步方案
    参考文章:
    http://wenku.baidu.com/link?url=3SvxuKV03wXR6LbjJYmXtrtiX7jPehmDTQRklcf_oXRX2FKoP2RzZVFp0Obl8cjZQED3en8orizKI9wFrYkdx3-izxjN8H2gjcpsiUXa98G
    略熟悉第三方sdk: Android 版 SugarSync 加入更多离线功能
    WebView实现离线缓存阅读
    参考文章:http://blog.csdn.net/wwj_748/article/details/44835865
    ArcGIS for Android离线数据编辑实现原理
    http://blog.csdn.net/arcgis_mobile/article/details/7565877
    ## 4、文件的加密
    文件加密AES加密算法
    AES加密算法是目前比较流行加密方式,目前还没有针对AES有效的破解方式,比较靠谱。
    AES加密数据块和密钥长度可以是128比特、192比特、256比特中的任意一个。
    AES加密有很多轮的重复和变换。大致步骤如下:
    1、密钥扩展(KeyExpansion),
    2、初始轮(Initial Round),
    3、重复轮(Rounds),每一轮又包括:SubBytes、ShiftRows、MixColumns、AddRoundKey,
    4、最终轮(Final Round),最终轮没有MixColumns。
    我以前对文件加密的时候就是参考如下文章
    请参考:http://blog.csdn.net/yudajun/article/details/40481135
    http://blog.csdn.net/dalancon/article/details/20924823
  ## (一):Android卸载程序之后如何跳转到指定的反馈页面
      比如:360被卸载之后会跳转到指定的反馈页面如何实现?
    本题解析:本题目的回答需要从C层出发,不过java层也需要接受一些android BroadcastReceiver机制,
              以及BroadcastReceiver无法实现原因,
    回答: 参考文章http://blog.csdn.net/jiangwei0910410003/article/details/42177117

## (二):FragmentManager内部如何维护fragment队列,以及fragment事务的回退栈实现原理
    本题解析:回答本题需要从以下几点去出发
    1,fragment的生命周期
    2,FragmentManager的作用,以及如何维护fragment队列
    3,如何管理Fragment回退栈和回退栈实现原理
    回答:
    fragment的生命周期 参考:http://blog.csdn.net/t12x3456/article/details/8104531
    FragmentManager的作用,以及如何维护fragment队列
    参考:http://longshuai2007.blog.163.com/blog/static/142094414201362631129902/
    http://www.cnblogs.com/mybkn/articles/2455138.html
    http://www.mamicode.com/info-detail-612467.html

    ## (三):如何保证后台Service不被杀掉
        本题解析:先大体介绍一下android的Service以及他的生命周期,其二 介绍出现哪些手机出现service被杀掉的问题,
    比如红米手机,service运行一段时间后很容易就被杀掉问题,然后你如何解决Service不被杀掉的方法。
    回答:参考 http://blog.csdn.net/mad1989/article/details/22492519
------


国内一线互联网公司内部面试题库,从一个老码农转载的

以下面试题来自于百度、小米、乐视、美团、58、猎豹、360、新浪、搜狐内部题库

熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。

欢迎一线公司员工提交内部面试题库,欢迎star。

一、java基础

1.接口的意义(百度)

规范、扩展、回调

2.抽象类的意义(乐视)

为其子类提供一个公共的类型 封装子类中得重复内容 定义抽象方法,子类虽然有不同的实现 但是定义是一致的

3.内部类的作用(百度,乐视)

内部类可以用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立。
在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类。
创建内部类对象的时刻并不依赖于外围类对象的创建。
内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。
内部类提供了更好的封装,除了该外围类,其他类都不能访问
4.父类的静态方法能否被子类重写,为什么?(猎豹)

不能

子类继承父类后,用相同的静态方法和非静态方法,这时非静态方法覆盖父类中的方法(即方法重写),父类的该静态方法被隐藏(如果对象是父类则调用该隐藏的方法),另外子类可继承父类的静态与非静态方法,至于方法重载我觉得它其中一要素就是在同一类中,不能说父类中的什么方法与子类里的什么方法是方法重载的体现

5.1-2个排序算法,并使用java代码实现(美团)

http://blog.csdn.net/qy1387/article/details/7752973

6.列举java的集合和继承关系(百度、美团)

http://blog.csdn.net/sdhgood/article/details/38849477

7.java虚拟机的特性(百度、乐视)

Java语言的一个非常重要的特点就是与平台的无关性。而使用Java虚拟机是实现这一特点的关键。一般的高级语言如果要在不同的平台上运行,至少需要编译成不同的目标代码。而引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用模式Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。

8.哪些情况下的对象会被垃圾回收机制处理掉(乐视、美团、小米)

Java 垃圾回收机制最基本的做法是分代回收。内存中的区域被划分成不同的世代,对象根据其存活的时间被保存在对应世代的区域中。一般的实现是划分成3个世代:年轻、年老和永久。内存的分配是发生在年轻世代中的。当一个对象存活时间足够长的时候,它就会被复制到年老世代中。对于不同的世代可以使用不同的垃圾回收算法。进行世代划分的出发点是对应用中对象存活时间进行研究之后得出的统计规律。一般来说,一个应用中的大部分对象的存活时间都很短。比如局部变量的存活时间就只在方法的执行过程中。基于这一点,对于年轻世代的垃圾回收算法就可以很有针对性。

9.进程和线程的区别(猎豹)

简而言之,一个程序至少有一个进程,一个进程至少有一个线程。

线程的划分尺度小于进程,使得多线程程序的并发性高。

另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。

线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.

线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.

一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.

进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。如果有兴趣深入的话,我建议你们看看《现代操作系统》或者《操作系统的设计与实现》。对就个问题说得比较清楚。

10.Java中==和equals的区别,equals和hashCode的区别(乐视)

http://blog.csdn.net/tiantiandjava/article/details/46988461

11.常见的排序算法时间复杂度(小米)



12.HashMap的实现原理(美团)

HashMap概述:    HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
HashMap的数据结构: 在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。


从上图中可以看出,HashMap底层就是一个数组结构,数组中的每一项又是一个链表。当新建一个HashMap的时候,就会初始化一个数组。

13.java 状态机

http://www.jdon.com/designpatterns/designpattern_State.htm

14.java中int char long各占多少字节数

byte 位数 8 字节数 1

short 16 2

int 32 4

long 64 8

float 32 4

double 64 8

char 16 2

15.java int与integer的区别

http://www.cnblogs.com/shenliang123/archive/2011/10/27/2226903.html

16.string stringbuffer stringbuilder 区别(小米、乐视、百度)

String 字符串常量

StringBuffer 字符串变量(线程安全)

StringBuilder 字符串变量(非线程安全)

简要的说, String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象, 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后,JVM 的 GC 就会开始工作,那速度是一定会相当慢的。

而如果是使用 StringBuffer 类则结果就不一样了,每次结果都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,再改变对象引用。所以在一般情况下我们推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。而在某些特别情况下, String 对象的字符串拼接其实是被 JVM 解释成了 StringBuffer 对象的拼接,所以这些时候 String 对象的速度并不会比 StringBuffer 对象慢,而特别是以下的字符串对象生成中, String 效率是远要比 StringBuffer 快的:

String S1 = “This is only a” + “ simple” + “ test”;

StringBuffer Sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”); 你会很惊讶的发现,生成 String S1 对象的速度简直太快了,而这个时候 StringBuffer 居然速度上根本一点都不占优势。其实这是 JVM 的一个把戏,在 JVM 眼里,这个  String S1 = “This is only a” + “ simple” + “test”; 其实就是:  String S1 = “This is only a simple test”; 所以当然不需要太多的时间了。但大家这里要注意的是,如果你的字符串是来自另外的 String 对象的话,速度就没那么快了,譬如:  String S2 = “This is only a”; String S3 = “ simple”; String S4 = “ test”; String S1 = S2 +S3 + S4; 这时候 JVM 会规规矩矩的按照原来的方式去做

在大部分情况下 StringBuffer > String

StringBuffer

Java.lang.StringBuffer线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。

可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。

StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。

例如,如果 z 引用一个当前内容是“start”的字符串缓冲区对象,则此方法调用 z.append("le") 会使字符串缓冲区包含“startle”,而 z.insert(4, "le") 将更改字符串缓冲区,使之包含“starlet”。

在大部分情况下 StringBuilder > StringBuffer

java.lang.StringBuilder

java.lang.StringBuilder一个可变的字符序列是5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。两者的方法基本相同

17.Java多态(乐视)

Java多态性理解

Java中多态性的实现

什么是多态

面向对象的三大特性:封装、继承、多态。从一定角度来看,封装和继承几乎都是为多态而准备的。这是我们最后一个概念,也是最重要的知识点。

多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)

实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实 际类型,根据其实际的类型调用其相应的方法。

多态的作用:消除类型之间的耦合关系。

现实中,关于多态的例子不胜枚举。比方说按下 F1 键这个动作,如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;如果当前在 Word 下弹出的就是 Word 帮助;在 Windows 下弹出的就是 Windows 帮助和支持。同一个事件发生在不同的对象上会产生不同的结果。 下面是多态存在的三个必要条件,要求大家做梦时都能背出来!

多态存在的三个必要条件 一、要有继承; 二、要有重写; 三、父类引用指向子类对象。

 多态的好处:

1.可替换性(substitutability)。多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。

2.可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。

3.接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。如图8.3 所示。图中超类Shape规定了两个实现多态的接口方法,computeArea()以及computeVolume()。子类,如Circle和Sphere为了实现多态,完善或者覆盖这两个接口方法。

4.灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。

5.简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。

Java中多态的实现方式:接口实现,继承父类进行方法重写,同一个类中进行方法重载。

18.什么导致线程阻塞(58、美团)

线程的阻塞

为了解决对共享存储区的访问冲突,Java 引入了同步机制,现在让我们来考察多个线程对共享资源的访问,显然同步机制已经不够了,因为在任意时刻所要求的资源不一定已经准备好了被访问,反过来,同一时刻准备好了的资源也可能不止一个。为了解决这种情况下的访问控制问题,Java 引入了对阻塞机制的支持.

阻塞指的是暂停一个线程的执行以等待某个条件发生(如某资源就绪),学过操作系统的同学对它一定已经很熟悉了。Java 提供了大量方法来支持阻塞,下面让我们逐一分析。

sleep() 方法:sleep() 允许 指定以毫秒为单位的一段时间作为参数,它使得线程在指定的时间内进入阻塞状态,不能得到CPU 时间,指定的时间一过,线程重新进入可执行状态。 典型地,sleep() 被用在等待某个资源就绪的情形:测试发现条件不满足后,让线程阻塞一段时间后重新测试,直到条件满足为止。
suspend() 和 resume() 方法:两个方法配套使用,suspend()使得线程进入阻塞状态,并且不会自动恢复,必须其对应的resume() 被调用,才能使得线程重新进入可执行状态。典型地,suspend() 和 resume() 被用在等待另一个线程产生的结果的情形:测试发现结果还没有产生后,让线程阻塞,另一个线程产生了结果后,调用 resume() 使其恢复。
yield() 方法:yield() 使得线程放弃当前分得的 CPU 时间,但是不使线程阻塞,即线程仍处于可执行状态,随时可能再次分得 CPU 时间。调用 yield() 的效果等价于调度程序认为该线程已执行了足够的时间从而转到另一个线程.
wait() 和 notify() 方法:两个方法配套使用,wait() 使得线程进入阻塞状态,它有两种形式,一种允许 指定以毫秒为单位的一段时间作为参数,另一种没有参数,前者当对应的 notify() 被调用或者超出指定时间时线程重新进入可执行状态,后者则必须对应的 notify() 被调用.
初看起来它们与 suspend() 和 resume() 方法对没有什么分别,但是事实上它们是截然不同的。区别的核心在于,前面叙述的所有方法,阻塞时都不会释放占用的锁(如果占用了的话),而这一对方法则相反。

上述的核心区别导致了一系列的细节上的区别。

首先,前面叙述的所有方法都隶属于 Thread 类,但是这一对却直接隶属于 Object 类,也就是说,所有对象都拥有这一对方法。初看起来这十分不可思议,但是实际上却是很自然的,因为这一对方法阻塞时要释放占用的锁,而锁是任何对象都具有的,调用任意对象的 wait() 方法导致线程阻塞,并且该对象上的锁被释放。而调用 任意对象的notify()方法则导致因调用该对象的 wait() 方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。

其次,前面叙述的所有方法都可在任何位置调用,但是这一对方法却必须在 synchronized 方法或块中调用,理由也很简单,只有在synchronized 方法或块中当前线程才占有锁,才有锁可以释放。同样的道理,调用这一对方法的对象上的锁必须为当前线程所拥有,这样才有锁可以释放。因此,这一对方法调用必须放置在这样的 synchronized 方法或块中,该方法或块的上锁对象就是调用这一对方法的对象。若不满足这一条件,则程序虽然仍能编译,但在运行时会出现IllegalMonitorStateException 异常。

wait() 和 notify() 方法的上述特性决定了它们经常和synchronized 方法或块一起使用,将它们和操作系统的进程间通信机制作一个比较就会发现它们的相似性:synchronized方法或块提供了类似于操作系统原语的功能,它们的执行不会受到多线程机制的干扰,而这一对方法则相当于 block 和wakeup 原语(这一对方法均声明为 synchronized)。它们的结合使得我们可以实现操作系统上一系列精妙的进程间通信的算法(如信号量算法),并用于解决各种复杂的线程间通信问题。

关于 wait() 和 notify() 方法最后再说明两点:

第一:调用 notify() 方法导致解除阻塞的线程是从因调用该对象的 wait() 方法而阻塞的线程中随机选取的,我们无法预料哪一个线程将会被选择,所以编程时要特别小心,避免因这种不确定性而产生问题。

第二:除了 notify(),还有一个方法 notifyAll() 也可起到类似作用,唯一的区别在于,调用 notifyAll() 方法将把因调用该对象的 wait() 方法而阻塞的所有线程一次性全部解除阻塞。当然,只有获得锁的那一个线程才能进入可执行状态。

谈到阻塞,就不能不谈一谈死锁,略一分析就能发现,suspend() 方法和不指定超时期限的 wait() 方法的调用都可能产生死锁。遗憾的是,Java 并不在语言级别上支持死锁的避免,我们在编程中必须小心地避免死锁。

以上我们对 Java 中实现线程阻塞的各种方法作了一番分析,我们重点分析了 wait() 和 notify() 方法,因为它们的功能最强大,使用也最灵活,但是这也导致了它们的效率较低,较容易出错。实际使用中我们应该灵活使用各种方法,以便更好地达到我们的目的。

19.抽象类接口区别(360)

默认的方法实现 抽象类可以有默认的方法实现完全是抽象的。接口根本不存在方法的实现

实现 子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现。
子类使用关键字implements来实现接口。它需要提供接口中所有声明的方法的实现

构造器
抽象类可以有构造器 接口不能有构造器

与正常Java类的区别
除了你不能实例化抽象类之外,它和普通Java类没有任何区 接口是完全不同的类型

访问修饰符
抽象方法可以有publicprotecteddefault这些修饰符 接口方法默认修饰符是public。你不可以使用其它修饰符。

main方法
抽象方法可以有main方法并且我们可以运行它
接口没有main方法,因此我们不能运行它。

多继承
抽象类在java语言中所表示的是一种继承关系,一个子类只能存在一个父类,但是可以存在多个接口。

速度
它比接口速度要快
接口是稍微有点慢的,因为它需要时间去寻找在类中实现的方法。

添加新方法
如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。
如果你往接口中添加方法,那么你必须改变实现该接口的类。

20.容器类之间的区别(乐视、美团)

http://www.cnblogs.com/yuanermen/archive/2009/08/05/1539917.html http://alexyyek.github.io/2015/04/06/Collection/ http://tianmaying.com/tutorial/java_collection

21.java 内部类(小米)

http://www.cnblogs.com/chenssy/p/3388487.html

22.Java中hashmap和hashtable的区别(乐视、小米)

http://www.233.com/ncre2/JAVA/jichu/20100717/084230917.html

23.ArrayMap VS HashMap

http://lvable.com/?p=217

二、android基础

1.数据库的操作类型有哪些,如何导入外部数据库?

把原数据库包括在项目源码的 res/raw

android系统下数据库应该存放在 /data/data/com..(package name)/ 目录下,所以我们需要做的是把已有的数据库传入那个目录下.操作方法是用FileInputStream读取原数据库,再用FileOutputStream把读取到的东西写入到那个目录.

2.是否使用过本地广播,和全局广播有什么差别?

因广播数据在本应用范围内传播,不用担心隐私数据泄露的问题。 不用担心别的应用伪造广播,造成安全隐患。 相比在系统内发送全局广播,它更高效。

3.是否使用过intentServer,作用是什么,AIDL解决了什么问题?(小米)

生成一个默认的且与主线程互相独立的工作者线程来执行所有传送至onStartCommand() 方法的Intetnt。

生成一个工作队列来传送Intent对象给你的onHandleIntent()方法,同一时刻只传送一个Intent对象,这样一来,你就不必担心多线程的问题。在所有的请求(Intent)都被执行完以后会自动停止服务,所以,你不需要自己去调用stopSelf()方法来停止。

该服务提供了一个onBind()方法的默认实现,它返回null

提供了一个onStartCommand()方法的默认实现,它将Intent先传送至工作队列,然后从工作队列中每次取出一个传送至onHandleIntent()方法,在该方法中对Intent对相应的处理。

AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。 AIDL IPC机制是面向接口的,像COM或Corba一样,但是更加轻量级。它是使用代理类在客户端和实现端传递数据。

4.Activity、Window、View三者的差别,fragment的特点?(360)

Activity像一个工匠(控制单元),Window像窗户(承载模型),View像窗花(显示视图) LayoutInflater像剪刀,Xml配置像窗花图纸。

在Activity中调用attach,创建了一个Window
创建的window是其子类PhoneWindow,在attach中创建PhoneWindow
在Activity中调用setContentView(R.layout.xxx)
其中实际上是调用的getWindow().setContentView()
调用PhoneWindow中的setContentView方法
创建ParentView:作为ViewGroup的子类,实际是创建的DecorView(作为FramLayout的子类)
将指定的R.layout.xxx 通过布局填充器进行填充[其中的parent指的就是DecorView]
调用到ViewGroup
调用ViewGroup的removeAllView(),先将所有的view移除掉
添加新的view:addView()
fragment 特点


Fragment可以作为Activity界面的一部分组成出现;
可以在一个Activity中同时出现多个Fragment,并且一个Fragment也可以在多个Activity中使用;
在Activity运行过程中,可以添加、移除或者替换Fragment;
Fragment可以响应自己的输入事件,并且有自己的生命周期,它们的生命周期会受宿主Activity的生命周期影响。
5.描述一次网络请求的流程(新浪)



6.Handler、Thread和HandlerThread的差别(小米)

http://blog.csdn.net/guolin_blog/article/details/9991569

http://droidyue.com/blog/2015/11/08/make-use-of-handlerthread/

从Android中Thread(java.lang.Thread -> java.lang.Object)描述可以看出,Android的Thread没有对Java的Thread做任何封装,但是Android提供了一个继承自Thread的类HandlerThread(android.os.HandlerThread -> java.lang.Thread),这个类对Java的Thread做了很多便利Android系统的封装。

android.os.Handler可以通过Looper对象实例化,并运行于另外的线程中,Android提供了让Handler运行于其它线程的线程实现,也是就HandlerThread。HandlerThread对象start后可以获得其Looper对象,并且使用这个Looper对象实例Handler。

7.低版本SDK实现高版本api(小米)

自己实现或@TargetApi annotation

8.Ubuntu编译安卓系统(百度)

进入源码根目录
. build/envsetup.sh
lunch
full(编译全部)
userdebug(选择编译版本)
make -j8(开启8个线程编译)
9.launch mode应用场景(百度、小米、乐视)

standard,创建一个新的Activity。

singleTop,栈顶不是该类型的Activity,创建一个新的Activity。否则,onNewIntent。

singleTask,回退栈中没有该类型的Activity,创建Activity,否则,onNewIntent+ClearTop。

注意:

设置了"singleTask"启动模式的Activity,它在启动的时候,会先在系统中查找属性值affinity等于它的属性值taskAffinity的Task存在; 如果存在这样的Task,它就会在这个Task中启动,否则就会在新的任务栈中启动。因此, 如果我们想要设置了"singleTask"启动模式的Activity在新的任务中启动,就要为它设置一个独立的taskAffinity属性值。
如果设置了"singleTask"启动模式的Activity不是在新的任务中启动时,它会在已有的任务中查看是否已经存在相应的Activity实例, 如果存在,就会把位于这个Activity实例上面的Activity全部结束掉,即最终这个Activity 实例会位于任务的Stack顶端中。
在一个任务栈中只有一个”singleTask”启动模式的Activity存在。他的上面可以有其他的Activity。这点与singleInstance是有区别的。
singleInstance,回退栈中,只有这一个Activity,没有其他Activity。

singleTop适合接收通知启动的内容显示页面。

例如,某个新闻客户端的新闻内容页面,如果收到10个新闻推送,每次都打开一个新闻内容页面是很烦人的。

singleTask适合作为程序入口点。

例如浏览器的主界面。不管从多少个应用启动浏览器,只会启动主界面一次,其余情况都会走onNewIntent,并且会清空主界面上面的其他页面。

singleInstance应用场景:

闹铃的响铃界面。 你以前设置了一个闹铃:上午6点。在上午558分,你启动了闹铃设置界面,并按 Home 键回桌面;在上午559分时,你在微信和朋友聊天;在6点时,闹铃响了,并且弹出了一个对话框形式的 Activity(名为 AlarmAlertActivity) 提示你到6点了(这个 Activity 就是以 SingleInstance 加载模式打开的),你按返回键,回到的是微信的聊天界面,这是因为 AlarmAlertActivity 所在的 Task 的栈只有他一个元素, 因此退出之后这个 Task 的栈空了。如果是以 SingleTask 打开 AlarmAlertActivity,那么当闹铃响了的时候,按返回键应该进入闹铃设置界面。

10.touch 事件传递流程(小米)

http://hanhailong.com/2015/09/24/Android-%E4%B8%89%E5%BC%A0%E5%9B%BE%E6%90%9E%E5%AE%9ATouch%E4%BA%8B%E4%BB%B6%E4%BC%A0%E9%80%92%E6%9C%BA%E5%88%B6/

11.view绘制流程(百度)

http://www.codekk.com/blogs/detail/54cfab086c4761e5001b253f

12.多线程(360)

Activity.runOnUiThread(Runnable)
View.post(Runnable),View.postDelay(Runnable,long)
Handler
AsyncTask
13.线程同步(百度)

http://www.itzhai.com/java-based-notebook-thread-synchronization-problem-solving-synchronization-problems-synchronized-block-synchronized-methods.html#read-more

http://www.juwends.com/tech/android/android-inter-thread-comm.html

单例

public class Singleton{
private volatile static Singleton mSingleton;
private Singleton(){
}
public static Singleton getInstance(){
  if(mSingleton == null){\\A
    synchronized(Singleton.class){\\C
     if(mSingleton == null)
      mSingleton = new Singleton();\\B
      }
    }
    return mSingleton;
  }
}
14.什么情况导致内存泄漏(美团)

1.资源对象没关闭造成的内存泄漏

描述: 资源性对象比如(Cursor,File文件等)往往都用了一些缓冲,我们在不使用的时候,应该及时关闭它们,以便它们的缓冲及时回收内存。它们的缓冲不仅存在于 java虚拟机内,还存在于java虚拟机外。如果我们仅仅是把它的引用设置为null,而不关闭它们,往往会造成内存泄漏。因为有些资源性对象,比如 SQLiteCursor(在析构函数finalize(),如果我们没有关闭它,它自己会调close()关闭),如果我们没有关闭它,系统在回收它时也会关闭它,但是这样的效率太低了。因此对于资源性对象在不使用的时候,应该调用它的close()函数,将其关闭掉,然后才置为null.在我们的程序退出时一定要确保我们的资源性对象已经关闭。 程序中经常会进行查询数据库的操作,但是经常会有使用完毕Cursor后没有关闭的情况。如果我们的查询结果集比较小,对内存的消耗不容易被发现,只有在常时间大量操作的情况下才会复现内存问题,这样就会给以后的测试和问题排查带来困难和风险。

2.构造Adapter时,没有使用缓存的convertView

描述: 以构造ListView的BaseAdapter为例,在BaseAdapter中提供了方法: public View getView(int position, ViewconvertView, ViewGroup parent) 来向ListView提供每一个item所需要的view对象。初始时ListView会从BaseAdapter中根据当前的屏幕布局实例化一定数量的 view对象,同时ListView会将这些view对象缓存起来。当向上滚动ListView时,原先位于最上面的list item的view对象会被回收,然后被用来构造新出现的最下面的list item。这个构造过程就是由getView()方法完成的,getView()的第二个形参View convertView就是被缓存起来的list item的view对象(初始化时缓存中没有view对象则convertView是null)。由此可以看出,如果我们不去使用 convertView,而是每次都在getView()中重新实例化一个View对象的话,即浪费资源也浪费时间,也会使得内存占用越来越大。 ListView回收list item的view对象的过程可以查看: android.widget.AbsListView.java --> voidaddScrapView(View scrap) 方法。 示例代码:

public View getView(int position, ViewconvertView, ViewGroup parent) {
View view = new Xxx(...); 
... ... 
return view; 
} 
修正示例代码:

public View getView(int position, ViewconvertView, ViewGroup parent) {
View view = null; 
if (convertView != null) { 
view = convertView; 
populate(view, getItem(position)); 
... 
} else { 
view = new Xxx(...); 
... 
} 
return view; 
} 
3.Bitmap对象不在使用时调用recycle()释放内存

描述: 有时我们会手工的操作Bitmap对象,如果一个Bitmap对象比较占内存,当它不在被使用的时候,可以调用Bitmap.recycle()方法回收此对象的像素所占用的内存,但这不是必须的,视情况而定。可以看一下代码中的注释:

/**  •Free up the memory associated with thisbitmap's pixels, and mark the  •bitmap as "dead", meaning itwill throw an exception if getPixels() or  •setPixels() is called, and will drawnothing. This operation cannot be  •reversed, so it should only be called ifyou are sure there are no  •further uses for the bitmap. This is anadvanced call, and normally need  •not be called, since the normal GCprocess will free up this memory when  •there are no more references to thisbitmap.  */ 

4.试着使用关于application的context来替代和activity相关的context

这是一个很隐晦的内存泄漏的情况。有一种简单的方法来避免context相关的内存泄漏。最显著地一个是避免context逃出他自己的范围之外。使用Application context。这个context的生存周期和你的应用的生存周期一样长,而不是取决于activity的生存周期。如果你想保持一个长期生存的对象,并且这个对象需要一个context,记得使用application对象。你可以通过调用 Context.getApplicationContext() or Activity.getApplication()来获得。更多的请看这篇文章如何避免 Android内存泄漏。

5.注册没取消造成的内存泄漏

一些Android程序可能引用我们的Anroid程序的对象(比如注册机制)。即使我们的Android程序已经结束了,但是别的引用程序仍然还有对我们的Android程序的某个对象的引用,泄漏的内存依然不能被垃圾回收。调用registerReceiver后未调用unregisterReceiver。 比如:假设我们希望在锁屏界面(LockScreen)中,监听系统中的电话服务以获取一些信息(如信号强度等),则可以在LockScreen中定义一个 PhoneStateListener的对象,同时将它注册到TelephonyManager服务中。对于LockScreen对象,当需要显示锁屏界面的时候就会创建一个LockScreen对象,而当锁屏界面消失的时候LockScreen对象就会被释放掉。 但是如果在释放 LockScreen对象的时候忘记取消我们之前注册的PhoneStateListener对象,则会导致LockScreen无法被垃圾回收。如果不断的使锁屏界面显示和消失,则最终会由于大量的LockScreen对象没有办法被回收而引起OutOfMemory,使得system_process 进程挂掉。 虽然有些系统程序,它本身好像是可以自动取消注册的(当然不及时),但是我们还是应该在我们的程序中明确的取消注册,程序结束时应该把所有的注册都取消掉。

6.集合中对象没清理造成的内存泄漏

我们通常把一些对象的引用加入到了集合中,当我们不需要该对象时,并没有把它的引用从集合中清理掉,这样这个集合就会越来越大。如果这个集合是static的话,那情况就更严重了。

15.ANR定位和修正

如果开发机器上出现问题,我们可以通过查看/data/anr/traces.txt即可,最新的ANR信息在最开始部分。

主线程被IO操作(从4.0之后网络IO不允许在主线程中)阻塞。
主线程中存在耗时的计算
主线程中错误的操作,比如Thread.wait或者Thread.sleep等 Android系统会监控程序的响应状况,一旦出现下面两种情况,则弹出ANR对话框
应用在5秒内未响应用户的输入事件(如按键或者触摸)
BroadcastReceiver未在10秒内完成相关的处理
Service在特定的时间内无法处理完成 20秒

使用AsyncTask处理耗时IO操作。

使用Thread或者HandlerThread时,调用Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)设置优先级,否则仍然会降低程序响应,因为默认Thread的优先级和主线程相同。
使用Handler处理工作线程结果,而不是使用Thread.wait()或者Thread.sleep()来阻塞主线程。
Activity的onCreate和onResume回调中尽量避免耗时的代码
BroadcastReceiver中onReceive代码也要尽量减少耗时,建议使用IntentService处理。
16.什么情况导致oom(乐视、美团)

http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0920/3478.html

1)使用更加轻量的数据结构 2)Android里面使用Enum 3)Bitmap对象的内存占用 4)更大的图片 5)onDraw方法里面执行对象的创建 6)StringBuilder

17.Android Service与Activity之间通信的几种方式

通过Binder对象
通过broadcast(广播)的形式
18.Android各个版本API的区别

http://blog.csdn.net/lijun952048910/article/details/7980562

19. Android代码中实现WAP方式联网(360)

http://blog.csdn.net/asce1885/article/details/7844159

20.如何保证service在后台不被kill

一、onStartCommand方法,返回START_STICKY

START_STICKY 在运行onStartCommand后service进程被kill后,那将保留在开始状态,但是不保留那些传入的intent。不久后service就会再次尝试重新创建,因为保留在开始状态,在创建     service后将保证调用onstartCommand。如果没有传递任何开始命令给service,那将获取到null的intent。

START_NOT_STICKY 在运行onStartCommand后service进程被kill后,并且没有新的intent传递给它。Service将移出开始状态,并且直到新的明显的方法(startService)调用才重新创建。因为如果没有传递任何未决定的intent那么service是不会启动,也就是期间onstartCommand不会接收到任何null的intent。

START_REDELIVER_INTENT 在运行onStartCommand后service进程被kill后,系统将会再次启动service,并传入最后一个intent给onstartCommand。直到调用stopSelf(int)才停止传递intent。如果在被kill后还有未处理好的intent,那被kill后服务还是会自动启动。因此onstartCommand不会接收到任何null的intent。

二、提升service优先级

在AndroidManifest.xml文件中对于intent-filter可以通过android:priority = "1000"这个属性设置最高优先级,1000是最高值,如果数字越小则优先级越低,同时适用于广播。

三、提升service进程优先级

Android中的进程是托管的,当系统进程空间紧张的时候,会依照优先级自动进行进程的回收。Android将进程分为6个等级,它们按优先级顺序由高到低依次是:

前台进程( FOREGROUND_APP)
可视进程(VISIBLE_APP )
次要服务进程(SECONDARY_SERVER )
后台进程 (HIDDEN_APP)
内容供应节点(CONTENT_PROVIDER)
空进程(EMPTY_APP)
当service运行在低内存的环境时,将会kill掉一些存在的进程。因此进程的优先级将会很重要,可以使用startForeground 将service放到前台状态。这样在低内存时被kill的几率会低一些。

四、onDestroy方法里重启service

service +broadcast  方式,就是当service走ondestory的时候,发送一个自定义的广播,当收到广播的时候,重新启动service;

五、Application加上Persistent属性

六、监听系统广播判断Service状态

通过系统的一些广播,比如:手机重启、界面唤醒、应用状态改变等等监听并捕获到,然后判断我们的Service是否还存活,别忘记加权限啊。

21.Requestlayout,onlayout,onDraw,DrawChild区别与联系(猎豹)

requestLayout()方法 :会导致调用measure()过程 和 layout()过程 。 说明:只是对View树重新布局layout过程包括measure()和layout()过程,不会调用draw()过程,但不会重新绘制 任何视图包括该调用者本身。

onLayout()方法(如果该View是ViewGroup对象,需要实现该方法,对每个子视图进行布局)

调用onDraw()方法绘制视图本身   (每个View都需要重载该方法,ViewGroup不需要实现该方法)

drawChild()去重新回调每个子视图的draw()方法

22.invalidate()和postInvalidate() 的区别及使用(百度)

http://blog.csdn.net/mars2639/article/details/6650876

23.Android动画框架实现原理

Animation框架定义了透明度,旋转,缩放和位移几种常见的动画,而且控制的是整个View,实现原理是每次绘制视图时View所在的ViewGroup中的drawChild函数获取该View的Animation的Transformation值,然后调用canvas.concat(transformToApply.getMatrix()),通过矩阵运算完成动画帧,如果动画没有完成,继续调用invalidate()函数,启动下次绘制来驱动动画,动画过程中的帧之间间隙时间是绘制函数所消耗的时间,可能会导致动画消耗比较多的CPU资源,最重要的是,动画改变的只是显示,并不能相应事件。

24.Android为每个应用程序分配的内存大小是多少?(美团)

android程序内存一般限制在16M,也有的是24M

25.Android View刷新机制(百度、美团)

由ViewRoot对象的performTraversals()方法调用draw()方法发起绘制该View树,值得注意的是每次发起绘图时,并不会重新绘制每个View树的视图,而只会重新绘制那些“需要重绘”的视图,View类内部变量包含了一个标志位DRAWN,当该视图需要重绘时,就会为该View添加该标志位。

调用流程 :

mView.draw()开始绘制,draw()方法实现的功能如下:

绘制该View的背景
为显示渐变框做一些准备操作(见5,大多数情况下,不需要改渐变框)          
调用onDraw()方法绘制视图本身   (每个View都需要重载该方法,ViewGroup不需要实现该方法)
调用dispatchDraw ()方法绘制子视图(如果该View类型不为ViewGroup,即不包含子视图,不需要重载该方法)值得说明的是,ViewGroup类已经为我们重写了dispatchDraw ()的功能实现,应用程序一般不需要重写该方法,但可以重载父类函数实现具体的功能。
26.LinearLayout对比RelativeLayout(百度)

RelativeLayout会让子View调用2次onMeasure,LinearLayout 在有weight时,也会调用子View2次onMeasure
RelativeLayout的子View如果高度和RelativeLayout不同,则会引发效率问题,当子View很复杂时,这个问题会更加严重。如果可以,尽量使用padding代替margin。
在不影响层级深度的情况下,使用LinearLayout和FrameLayout而不是RelativeLayout。
最后再思考一下文章开头那个矛盾的问题,为什么Google给开发者默认新建了个RelativeLayout,而自己却在DecorView中用了个LinearLayout。因为DecorView的层级深度是已知而且固定的,上面一个标题栏,下面一个内容栏。采用RelativeLayout并不会降低层级深度,所以此时在根节点上用LinearLayout是效率最高的。而之所以给开发者默认新建了个RelativeLayout是希望开发者能采用尽量少的View层级来表达布局以实现性能最优,因为复杂的View嵌套对性能的影响会更大一些。

27.优化自定义view(百度、乐视、小米)

为了加速你的view,对于频繁调用的方法,需要尽量减少不必要的代码。先从onDraw开始,需要特别注意不应该在这里做内存分配的事情,因为它会导致GC,从而导致卡顿。在初始化或者动画间隙期间做分配内存的动作。不要在动画正在执行的时候做内存分配的事情。

你还需要尽可能的减少onDraw被调用的次数,大多数时候导致onDraw都是因为调用了invalidate().因此请尽量减少调用invaildate()的次数。如果可能的话,尽量调用含有4个参数的invalidate()方法而不是没有参数的invalidate()。没有参数的invalidate会强制重绘整个view。

另外一个非常耗时的操作是请求layout。任何时候执行requestLayout(),会使得Android UI系统去遍历整个View的层级来计算出每一个view的大小。如果找到有冲突的值,它会需要重新计算好几次。另外需要尽量保持View的层级是扁平化的,这样对提高效率很有帮助。

如果你有一个复杂的UI,你应该考虑写一个自定义的ViewGroup来执行他的layout操作。与内置的view不同,自定义的view可以使得程序仅仅测量这一部分,这避免了遍历整个view的层级结构来计算大小。这个PieChart 例子展示了如何继承ViewGroup作为自定义view的一部分。PieChart 有子views,但是它从来不测量它们。而是根据他自身的layout法则,直接设置它们的大小。

28.ContentProvider(乐视)

http://blog.csdn.net/coder_pig/article/details/47858489

29.fragment生命周期



30.volley解析(美团、乐视)

http://a.codekk.com/detail/Android/grumoon/Volley%20%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90

31.Android Glide源码解析

http://www.lightskystreet.com/2015/10/12/glide_source_analysis/ http://frodoking.github.io/2015/10/10/android-glide/

32.Android 设计模式

http://blog.csdn.net/bboyfeiyu/article/details/44563871

33.架构设计(搜狐)



http://www.tianmaying.com/tutorial/AndroidMVC

34.Android属性动画特性(乐视、小米)

如果你的需求中只需要对View进行移动、缩放、旋转和淡入淡出操作,那么补间动画确实已经足够健全了。但是很显然,这些功能是不足以覆盖所有的场景的,一旦我们的需求超出了移动、缩放、旋转和淡入淡出这四种对View的操作,那么补间动画就不能再帮我们忙了,也就是说它在功能和可扩展方面都有相当大的局限性,那么下面我们就来看看补间动画所不能胜任的场景。

注意上面我在介绍补间动画的时候都有使用“对View进行操作”这样的描述,没错,补间动画是只能够作用在View上的。也就是说,我们可以对一个Button、TextView、甚至是LinearLayout、或者其它任何继承自View的组件进行动画操作,但是如果我们想要对一个非View的对象进行动画操作,抱歉,补间动画就帮不上忙了。可能有的朋友会感到不能理解,我怎么会需要对一个非View的对象进行动画操作呢?这里我举一个简单的例子,比如说我们有一个自定义的View,在这个View当中有一个Point对象用于管理坐标,然后在onDraw()方法当中就是根据这个Point对象的坐标值来进行绘制的。也就是说,如果我们可以对Point对象进行动画操作,那么整个自定义View的动画效果就有了。显然,补间动画是不具备这个功能的,这是它的第一个缺陷。

然后补间动画还有一个缺陷,就是它只能够实现移动、缩放、旋转和淡入淡出这四种动画操作,那如果我们希望可以对View的背景色进行动态地改变呢?很遗憾,我们只能靠自己去实现了。说白了,之前的补间动画机制就是使用硬编码的方式来完成的,功能限定死就是这些,基本上没有任何扩展性可言。

最后,补间动画还有一个致命的缺陷,就是它只是改变了View的显示效果而已,而不会真正去改变View的属性。什么意思呢?比如说,现在屏幕的左上角有一个按钮,然后我们通过补间动画将它移动到了屏幕的右下角,现在你可以去尝试点击一下这个按钮,点击事件是绝对不会触发的,因为实际上这个按钮还是停留在屏幕的左上角,只不过补间动画将这个按钮绘制到了屏幕的右下角而已。

# 笔试题


android中常用的四个布局是_____,_____,_____和_____。

答案:framlayout,linenarlayout,relativelayout和tablelayout

------

下列哪些语句关于内存回收的说明是正确的? ()
```  
A、程序员必须创建一个线程来释放内存
B、内存回收程序负责释放无用内存
C、内存回收程序允许程序员直接释放内存
D、内存回收程序可以在指定的时间释放内存对象

答案:B


请谈一下Android系统的架构。

答:Android系统采用了分层架构,从高层到低层分别是应用程序层、应用程序框架层、系统运行库层和linux核心层。


在android中使用Menu时可能需要重写的方法有()。(多选)

AonCreateOptionsMenu()
BonCreateMenu()
ConOptionsItemSelected()
DonItemSelected()

答案:AC


sim卡的EF文件有何作用?

答:sim卡的文件系统有自己规范,主要是为了和手机通讯,sim本身可以有自己的操作系统,EF就是作存储并和手机通讯用的。


在SQL Server Management Studio 中运行下列T-SQL语句,其输出值()。

SELECT @@IDENTITY  
A、可能为0.1
B、可能为3
C、不可能为-100
D、肯定为0

答案:C


嵌入式操作系统内存管理有哪几种,各有何特性?

答:页式,段式,段页,用到了MMU,虚拟空间等技术。


在SQL Server 2005中运行如下T-SQL语句,假定SALES表中有多行数据,执行查询之后的结果是()。

BEGIN TRANSACTION A
	Update SALES Set qty=30 WHERE qty<30
	BEGIN TRANSACTION B
		Update SALES Set qty=40 WHERE qty<40
		Update SALES Set qty=50 WHERE qty<50
		Update SALES Set qty=60 WHERE qty<60
	COMMIT TRANSACTION B
COMMIT TRANSACTION A
A、SALES表中qty列最小值大于等于30
B、SALES表中qty列最小值大于等于40
C、SALES表中qty列的数据全部为50
D、SALES表中qty列最小值大于等于60

答案:D


什么是嵌入式实时操作系统, Android 操作系统属于实时操作系统吗?

答:嵌入式实时操作系统是指当外界事件或数据产生时,能够接受并以足够快的速度予以处理,其处理的结果又能在规定的时间之内来控制生产过程或对处理系统作出快速响应,并控制所有实时任务协调一致运行的嵌入式操作系统。主要用于工业控制、军事设备、航空航天等领域对系统的响应时间有苛刻的要求,这就需要使用实时系统。又可分为软实时和硬实时两种,而android是基于linux内核的,因此属于软实时。


在android中使用SQLiteOpenHelper这个辅助类时,可以生成一个数据库,并可以对数据库版本进行管理的方法可以是()

AgetWriteableDatabase()
BgetReadableDatabase()
CgetDatabase()
DgetAbleDatabase()

答案:AB


一条最长的短信息约占多少byte?

答:中文70(包括标点),英文160,160个字节。


android 关于service生命周期的onCreate()和onStart()说法正确的是()(多选题)

A、当第一次启动的时候先后调用onCreate()和onStart()方法
B、当第一次启动的时候只会调用onCreate()方法
C、如果service已经启动,将先后调用onCreate()和onStart()方法
D、如果service已经启动,只会执行onStart()方法,不在执行onCreate()方法

答案:AD


android中的动画有哪几类,它们的特点和区别是什么?

答:两种,一种是Tween动画、还有一种是Frame动画。Tween动画,这种实现方式可以使视图组件移动、放大、缩小以及产生透明度的变化;另一种Frame动画,传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影。


下面是属于GLSurFaceView特性的是()(多选)

A、管理一个surface,这个surface就是一块特殊的内存,能直接排版到android的视图view上。
B、管理一个EGL display,它能让opengl把内容渲染到上述的surface上。
C、让渲染器在独立的线程里运作,和UI线程分离。
D、可以直接从内存或者DMA等硬件接口取得图像数据

答案:ABC


handler机制的原理。

答:andriod提供了Handler和Looper来满足线程间的通信。Handler先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(Message Exchange)。
1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)。
2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper从Message Queue取出)所送来的消息。
3)Message Queue(消息队列):用来存放线程放入的消息。
4)线程:UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。


下面在AndroidManifest.xml文件中注册BroadcastReceiver方式正确的()

A、
<receiver android:name="NewBroad">
	<intent-filter>
		<action
		   android:name="android.provider.action.NewBroad"/>
		<action>
	</intent-filter>
</receiver>
B、
<receiver android:name="NewBroad">
	<intent-filter>
		   android:name="android.provider.action.NewBroad"/>
	</intent-filter>
</receiver>
C、
<receiver android:name="NewBroad">
	<action
		  android:name="android.provider.action.NewBroad"/>
	 <action>
</receiver>
D、
<intent-filter>
	<receiver android:name="NewBroad">
		<action>
		   android:name="android.provider.action.NewBroad"/>
		<action>
	</receiver>
</intent-filter>

答案:A


说说mvc模式的原理,它在android中的运用,android的官方建议应用程序的开发采用mvc模式。何谓mvc?

答:mvc是model,view,controller的缩写,mvc包含三个部分:
1、模型(model)对象:是应用程序的主体部分,所有的业务逻辑都应该写在该层。
2、视图(view)对象:是应用程序中负责生成用户界面的部分。也是在整个mvc架构中用户唯一可以看到的一层,接收用户的输入,显示处理结果。
3、控制器(control)对象:是根据用户的输入,控制用户界面数据显示及更新model对象状态的部分,控制器更重要的一种导航功能,响应用户出发的相关事件,交给m层处理。
android鼓励弱耦合和组件的重用,在android中mvc的具体体现如下:
1)视图层(view):一般采用xml文件进行界面的描述,使用的时候可以非常方便的引入,当然,如果你对android了解的比较的多了话,就一定可以想到在android中也可以使用javascript+html等的方式作为view层,当然这里需要进行java和javascript之间的通信,幸运的是,android提供了它们之间非常方便的通信实现。
2)控制层(controller):android的控制层的重任通常落在了众多的acitvity的肩上,这句话也就暗含了不要在acitivity中写代码,要通过activity交割model业务逻辑层处理,这样做的另外一个原因是android中的acitivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。
3)模型层(model):对数据库的操作、对网络等的操作都应该在model里面处理,当然对业务计算等操作也是必须放在的该层的。


关于ContenValues类说法正确的是()

A、他和Hashtable比较类似,也是负责存储一些名值对,但是他存储的名值对当中的名是String类型,而值都是基本类型
B、他和Hashtable比较类似,也是负责存储一些名值对,但是他存储的名值对当中的名是任意类型,而值都是基本类型
C、他和Hashtable比较类似,也是负责存储一些名值对,但是他存储的名值对当中的名,可以为空,而值都是String类型      
D、他和Hashtable比较类似,也是负责存储一些名值对,但是他存储的名值对当中的名是String类型,而值也是String类型

答案:A


Activity的生命周期?

答:和其他手机平台的应用程序一样,Android的应用程序的生命周期是被统一掌控的,也就是说我们写的应用程序命运掌握在别人(系统)的手里,我们不能改变它,只能学习并适应它。
简单地说一下为什么是这样:我们手机在运行一个应用程序的时候,有可能打进来电话发进来短信,或者没有电了,这时候程序都会被中断,优先去服务电话的基本功能 ,另 外系统也不允许你占用太多资源 ,至少要保证电话功能吧,所以资源不足的时候也就有可 能被干掉。
言归正传,Activity的基本生命周期如下代码 所示:
Java代码

public class MyActivity extends Activity {
	protected void onCreate(Bundle savedInstanceState);
	protected void onStart();
	protected void onResume();
	protected void onPause();
	protected void onStop();
	protected void onDestroy();
}
public class MyActivity extends Activity {
	protected void onCreate(Bundle savedInstanceState);
	protected void onStart();
	protected void onResume();
	protected void onPause();
	protected void onStop();
	protected void onDestroy();
}

你自己写的Activity会按需要 重载这些方法,onCreate是免不了的,在一个Activity正常启动的过程中,他们被调用的顺序是 onCreate -> onStart -> onResume, 在Activity被干掉的时候顺序是onPause -> onStop -> onDestroy ,这样就是一个完整的生命周期,但是有人问了 ,程序正运行着呢来电话了,这个程序咋办?中止了呗,如果中止的时候新出的一个Activity是全屏的那么:onPause->onStop ,恢复的时候onStart->onResume ,如果打断 这个应用程序的是一个Theme为Translucent 或者Dialog 的Activity那么只是onPause ,恢复 的时候onResume 。
详细介绍一下这几个方法中系统在做什么以及我们应该做什么:

onCreate: 在这里创建界面 ,做一些数据 的初始化工作
onStart: 到这一步变成用户可见不可交互 的
onResume: 变成和用户可交互 的,(在activity 栈系统通过栈的方式管理这些个 Activity的最上面,运行完弹出栈,则回到上一个Activity)
onPause:到这一步是可见但不可交互的,系统会停止动画等消耗CPU的事情从上文的描述已经知道,应该在这里保存你的一些数据,因为这个时候你的程序的优先级降低,有可能被系统收回。在这里保存的数据,应该在onResume里读出来,注意:这个方法里做的事情时间要短,因为下一个activity不会等到这个方法完成才启动
onstop: 变得不可见 ,被下一个activity覆盖了
onDestroy:这是activity被干掉前最后一个被调用方法了,可能是外面类调用finish方法或者是系统为了节省空间将它暂时性的干掉,可以用isFinishing()来判断它,如果你有一个ProgressDialog在线程中转动,请在onDestroy里把他cancel掉,不然等线程结束的时候,调用Dialog的cancel方法会抛 异常的。

onPause,onstop,onDestroy三种状态下activity都有可能被系统干掉
为了保证程序的正确性,你要在onPause()里写上持久层操作的代码,将用户编辑的内容都保存到存储介质上(一般都是数据库)。实际工作中因为生命周期的变化而带来的问题也很多,比如你的应用程序起了新的线程在跑,这时候中断了,你还要去维护那个线程,是暂停还是杀掉还是数据回滚,是吧?因为Activity可能被杀掉,所以线程中使用的变量和一些界面元素就千万要注意了,一般我都是采用Android的消息机制[Handler,Message]来处理多线程和界面交互的问题。这个我后面会讲一些,最近因为这些东西头已经很大了,等我理清思绪再跟大家分享。


我们都知道Hanlder是线程与Activity通信的桥梁,如果线程处理不当,你的机器就会变得越慢,那么线程销毁的方法是()

AonDestroy()
BonClear()
ConFinish()
DonStop()

答案:A


你后台的Activity被系统回收怎么办:onSaveInstanceState

答:当你的程序中某一个Activity A 在运行时中,主动或被动地运行另一个新的Activity B这个时候A会执行

public void onSaveInstanceState(Bundle outState) {
	super.onSaveInstanceState(outState);
	outState.putLong("id", 1234567890);
}
public void onSaveInstanceState(Bundle outState) {
	super.onSaveInstanceState(outState);
	outState.putLong("id", 1234567890);
}

B完成以后又会来找A,这个时候就有两种情况,一种是A被回收,一种是没有被回收,被回收的A就要重新调用onCreate()方法,不同于直接启动的是这回onCreate()里是带上参数 savedInstanceState,没被收回的就还是onResume就好了。
savedInstanceState是一个Bundle对象,你基本上可以把他理解为系统帮你维护的一个Map对象。在onCreate()里你可能会用到它,如果正常启动onCreate就不会有它,所以用的时候要判断一下是否为空。

if (savedInstanceState != null) {
	long id = savedInstanceState.getLong("id");
}
if (savedInstanceState != null) {
	long id = savedInstanceState.getLong("id");
}

就像官方的Notepad教程里的情况,你正在编辑某一个note,突然被中断,那么就把这个note的id记住,再起来的时候就可以根据这个id去把那个note取出来,程序就完整一些。这也是看你的应用需不需要保存什么,比如你的界面就是读取一个列表,那就不需要特殊记住什么,哦,没准你需要记住滚动条的位置…


下面退出Activity错误的方法是()

A、finish()
B、抛异常强制退出
C、System.exit()
D、onStop()

答案:C


调用与被调用:我们的通信使者Intent

答:要说Intent了,Intent就是这个这个意图 ,应用程序间Intent进行交流,打个电话啦,来个 电话啦都会发Intent, 这个是Android架构的松耦合的精髓部分,大大提高了组件的复用性,比如你要在你的应用程序中点击按钮,给某人打电话,很简单啊,看下代码先:

Intent intent = new Intent();
intent.setAction(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:" + number));
startActivity(intent);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:" + number));
startActivity(intent);

扔出这样一个意图,系统看到了你的意图就唤醒了电话拨号程序,打出来电话。什么读联系人,发短信啊,邮件啊,统统只需要扔出intent就好了,这个部分设计 地确实很好啊。
那Intent通过什么来告诉系统需要谁来接受他呢?
通常使用Intent有两种方法,第一种是直接说明需要哪一个类来接收代码如下:

Intent intent = new Intent(this, MyActivity.class);
intent.getExtras().putString("id", "1");
StartActivity(intent);
Intent intent = new Intent(this, MyActivity.class);
intent.getExtras().putString("id", "1");
StartActivity(intent);

第一种方式很明显,直接指定了MyActivity为接受者,并且传了一些数据给MyActivity,在MyActivity里可以用getIntent()来的到这个intent和数据。
第二种就需要先看一下AndroidMenifest中的intentfilter的配置了
Xml代码

<intent-filter>
	<action android:name="android.intent.action.VIEW" />
	<action android:value="android.intent.action.EDIT" />
	<action android:value="android.intent.action.PICK" />
	<category android:name="android.intent.category.DEFAULT" />
	<data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
</intent-filter>

这里面配置用到了action, data, category这些东西,那么聪明的你一定想到intent里也会有这些东西,然后一匹配不就找到接收者了吗?
action其实就是一个意图的字符串名称。
上面这段intent-filter的配置文件说明了这个Activity可以接受不同的Action,当然相应的程序逻辑也不一样咯,提一下那个mimeType,他是在ContentProvider里定义的,你要是自己实现一个ContentProvider就知道了,必须指定 mimeType才能让数据被别人使用。
不知道原理说明白没,总结一句,就是你调用别的界面不是直接new那个界面,而是通过扔出一个intent,让系统帮你去调用那个界面,这样就多么松藕合啊,而且符合了生命周期被系统管理的原则。
想知道category都有啥,Android为你预先定制好的action都有啥等等,请亲自访问官方链接Intent
ps:想知道怎么调用系统应用程序的同学,可以仔细看一下你的logcat,每次运行一个程序的时候是不是有一些信息比如:

Starting activity: Intent { action=android.intent.action.MAINcategories={android.intent.category.LAUNCHER} flags=0x10200000comp={com.android.camera/com.android.camera.GalleryPicker} }

android 的四大组件是

答案:activiey,service,broadcast和contentprovide


下面异常是属于Runtime Exception 的是()(多选)

A、ArithmeticException
B、IllegalArgumentException
C、NullPointerException
D、BufferUnderflowException

答案:ABCD


谈谈android大众常用的五种布局。

答:在Android中,共有五种布局方式,分别是:FrameLayout(框架布局),LinearLayout(线性布局),AbsoluteLayout(绝对布局),RelativeLayout(相对布局),TableLayout(表格布局)。

(1)FrameLayout

框架布局,放入其中的所有元素都被放置在最左上的区域,而且无法为这些元素指定一个确切的位置,下一个子元素会重叠覆盖上一个子元素,适合浏览单张图片。

(2)LinearLayout

线性布局,是应用程序中最常用的布局方式,主要提供控件水平或者垂直排列的模型,每个子组件都是以垂直或水平的方式来定位.(默认是垂直)

(3)AbsoluteLayout

绝对定位布局,采用坐标轴的方式定位组件,左上角是(0,0)点,往右x轴递增,往下Y轴递增,组件定位属性为android:layout_x和android:layout_y来确定坐标。

(4)RelativeLayout

相对布局,根据另外一个组件或是顶层父组件来确定下一个组件的位置。和CSS里面的类似。

(5)TableLayout

表格布局,类似Html里的Table.使用TableRow来布局,其中TableRow代表一行,TableRow的每一个视图组件代表一个单元格。


下面属于android的动画分类的有()(多项)

A、Tween  
B、Frame
C、Draw
D、Animation

答案:AB


什么是ANR如何避免它?

答:ANR:Application Not Responding,五秒在Android中,活动管理器和窗口管理器这两个系统服务负责监视应用程序的响应。当出现下列情况时,Android就会显示ANR对话框了:
对输入事件(如按键、触摸屏事件)的响应超过5秒
意向接受器(intentReceiver)超过10秒钟仍未执行完毕
Android应用程序完全运行在一个独立的线程中(例如main)。这就意味着,任何在主线程中运行的,需要消耗大量时间的操作都会引发ANR。因为此时,你的应用程序已经没有机会去响应输入事件和意向广播(Intent broadcast)。
因此,任何运行在主线程中的方法,都要尽可能的只做少量的工作。特别是活动生命周期中的重要方法如onCreate()和onResume()等更应如此。潜在的比较耗时的操作,如访问网络和数据库;或者是开销很大的计算,比如改变位图的大小,需要在一个单独的子线程中完成(或者是使用异步请求,如数据库操作)。但这并不意味着你的主线程需要进入阻塞状态已等待子线程结束–也不需要调用Therad.wait()或者Thread.sleep()方法。取而代之的是,主线程为子线程提供一个句柄(Handler),让子线程在即将结束的时候调用它(xing:可以参看Snake的例子,这种方法与以前我们所接触的有所不同)。使用这种方法涉及你的应用程序,能够保证你的程序对输入保持良好的响应,从而避免因为输入事件超过5秒钟不被处理而产生的ANR。这种实践需要应用到所有显示用户界面的线程,因为他们都面临着同样的超时问题。

  


下面关于Android dvm的进程和Linux的进程,应用程序的进程说法正确的是()

A、DVM指dalivk的虚拟机.每一个Android应用程序都在它自己的进程中运行,不一定拥有一个独立的Dalvik虚拟机实例.而每一个DVM都是在Linux中的一个进程,所以说可以认为是同一个概念.
B、DVM指dalivk的虚拟机.每一个Android应用程序都在它自己的进程中运行,不一定拥有一个独立的Dalvik虚拟机实例.而每一个DVM不一定都是在Linux 中的一个进程,所以说不是一个概念.
C、DVM指dalivk的虚拟机.每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例.而每一个DVM不一定都是在Linux中的一个进程,所以说不是一个概念.
D、DVM指dalivk的虚拟机.每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例.而每一个DVM都是在Linux中的一个进程,所以说可以认为是同一个概念.

答案:D


什么情况会导致Force Close ?如何避免?能否捕获导致其的异常?

答:一般像空指针啊,可以看起logcat,然后对应到程序中来解决错误

  


Android项目工程下面的assets目录的作用是什么?

A、放置应用到的图片资源。
B、主要放置多媒体等数据文件
C、放置字符串,颜色,数组等常量数据
D、放置一些与UI相应的布局文件,都是xml文件

答案:B


简要解释一下activity、 intent 、intent filter、service、Broadcase、BroadcaseReceiver

答:一个activity呈现了一个用户可以操作的可视化用户界面
一个service不包含可见的用户界面,而是在后台无限地运行
可以连接到一个正在运行的服务中,连接后,可以通过服务中暴露出来的借口与其进行通信
一个broadcast receiver是一个接收广播消息并作出回应的component,broadcast receiver没有界面
intent:content provider在接收到ContentResolver的请求时被激活。
activity, service和broadcast receiver是被称为intents的异步消息激活的。
一个intent是一个Intent对象,它保存了消息的内容。对于activity和service来说,它指定了请求的操作名称和待操作数据的URI
Intent对象可以显式的指定一个目标component。如果这样的话,android会找到这个component(基于manifest文件中的声明)并激活它。但如果一个目标不是显式指定的,android必须找到响应intent的最佳component。
它是通过将Intent对象和目标的intent filter相比较来完成这一工作的。一个component的intent filter告诉android该component能处理的intent。intent filter也是在manifest文件中声明的。

  


关于res/raw目录说法正确的是()

A、这里的文件是原封不动的存储到设备上不会转换为二进制的格式
B、这里的文件是原封不动的存储到设备上会转换为二进制的格式
C、这里的文件最终以二进制的格式存储到指定的包中
D、这里的文件最终不会以二进制的格式存储到指定的包中

答案:A


IntentService有何优点?

答:IntentService 的好处

* Acitivity的进程,当处理Intent的时候,会产生一个对应的Service
* Android的进程处理器现在会尽可能的不kill掉你
* 非常容易使用

  


下列对android NDK的理解正确的是()

A、NDK是一系列工具的集合
B、NDK 提供了一份稳定、功能有限的 API 头文件声明。
C、使 “Java+C” 的开发方式终于转正,成为官方支持的开发方式
D、NDK 将是 Android 平台支持 C 开发的开端

答案:ABCD


横竖屏切换时候activity的生命周期?

1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
2、设置Activity的android:configChanges=”orientation”时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
3、设置Activity的android:configChanges=”orientation|keyboardHidden”时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法


java.io包中定义了多个流类型来实现输入和输出功能,可以从不同的角度对其进行分类,按功能分为:(),如果为读取的内容进行处理后再输出,需要使用下列哪种流?()

A、输入流和输出流  
B、字节流和字符流  
C、节点流和处理流  
D、File stream  
E、Pipe stream  
F、Random stream  
G、Filter stream

答案:C,G


如何将SQLite数据库(dictionary.db文件)与apk文件一起发布?

解答:可以将dictionary.db文件复制到Eclipse Android工程中的res raw目录中。所有在res raw目录中的文件不会被压缩,这样可以直接提取该目录中的文件。可以将dictionary.db文件复制到res raw目录中

  


下列代码的执行结果是:()

public class Test3 {
	public static void main(String args[]) {
		System.out.print(100 % 3);
		System.out.print(",");
		System.out.println(100 % 3.0);
	}
}
A、1,1
B、1,1.0
C、1.0,1
D、1.0,1.0

答案:B


如何将打开res raw目录中的数据库文件?

解答:在Android中不能直接打开res raw目录中的数据库文件,而需要在程序第一次启动时将该文件复制到手机内存或SD卡的某个目录中,然后再打开该数据库文件。复制的基本方法是使用getResources().openRawResource方法获得res raw目录中资源的InputStream对象,然后将该InputStream对象中的数据写入其他的目录中相应文件中。在Android SDK中可以使用SQLiteDatabase.openOrCreateDatabase方法来打开任意目录中的SQLite数据库文件。


在继承中,关于构造方法的说明,下列说法错误的是()

A、子类无条件的继承父类的无参构造方法,
B、子类可以引用父类中的有参构造方法,使用super关键字,
C、如果子类没有构造方法,则父类无参构造方法作为自已的构造方法,
D、如果子类有无参构造方法,而父类的无参构造方法则被覆盖。

答案:D


Android引入广播机制的用意?

答:a:从MVC的角度考虑(应用程序内)
其实回答这个问题的时候还可以这样问,android为什么要有那4大组件,现在的移动开发模型基本上也是照搬的web那一套MVC架构,只不过是改了点嫁妆而已。android的四大组件本质上就是为了实现移动或者说嵌入式设备上的MVC架构,它们之间有时候是一种相互依存的关系,有时候又是一种补充关系,引入广播机制可以方便几大组件的信息和数据交互。
b:程序间互通消息(例如在自己的应用程序内监听系统来电)
c:效率上(参考UDP的广播协议在局域网的方便性)
d:设计模式上(反转控制的一种应用,类似监听者模式)


以下程序的运行结果为()

public class IfTest {
	public static void main(String args[]) {
		int x = 3;
		int y = 1;
		if (x == y)
			System.out.println("Not equal");
		else
			System.out.println("Equal");
	}
}
A、Not equal     
B、Equal    
C、无输出    
D、编译出错

答案:B


Android的四大组件是哪些,它们的作用?

答:Activity:Activity是Android程序与用户交互的窗口,是Android构造块中最基本的一种,它需要为保持各界面的状态,做很多持久化的事情,妥善管理生命周期以及一些跳转逻辑
service:后台服务于Activity,封装有一个完整的功能逻辑实现,接受上层指令,完成相关的食物,定义好需要接受的Intent提供同步和异步的接口
Content Provider:是Android提供的第三方应用数据的访问方案,可以派生Content Provider类,对外提供数据,可以像数据库一样进行选择排序,屏蔽内部数据的存储细节,向外提供统一的借口模型,大大简化上层应用,对数据的整合提供了更方便的途径
BroadCast Receiver:接受一种或者多种Intent作触发事件,接受相关消息,做一些简单处理,转换成一条Notification,统一了Android的事件广播模型


Java语言中字符串“学Java”所占的内存空间是()

A. 6个字节
B. 7个字节
C. 10个字节
D. 11个字节

答案:A


android 中有哪几种解析xml的类?官方推荐哪种?以及它们的原理和区别。

答:XML解析主要有三种方式,SAX、DOM、PULL。常规在PC上开发我们使用Dom相对轻松些,但一些性能敏感的数据库或手机上还是主要采用SAX方式,SAX读取是单向的,优点:不占内存空间、解析属性方便,但缺点就是对于套嵌多个分支来说处理不是很方便。而DOM方式会把整个XML文件加载到内存中去,这里Android开发网提醒大家该方法在查找方面可以和XPath很好的结合如果数据量不是很大推荐使用,而PULL常常用在J2ME对于节点处理比较好,类似SAX方式,同样很节省内存,在J2ME中我们经常使用的KXML库来解析。


java.io包中的类主要用于对对象(Object)的读写。

答案:objectinputstream和objectoutputstream


Math.round(11.5)等于多少(). Math.round(-11.5)等于多少().

A、11 ,-11   
B、11 ,-12   
C、12 ,-11   
D、12 ,-12

答案:C


谈谈android数据存储方式。

答:Android提供了5种方式存储数据:
(1)使用SharedPreferences存储数据;它是Android提供的用来存储一些简单配置信息的一种机制,采用了XML格式将数据存储到设备中。只能在同一个包内使用,不能在不同的包之间使用。
(2)文件存储数据;文件存储方式是一种较常用的方法,在Android中读取/写入文件的方法,与Java中实现I/O的程序是完全一样的,提供了openFileInput()和openFileOutput()方法来读取设备上的文件。
(3)SQLite数据库存储数据;SQLite是Android所带的一个标准的数据库,它支持SQL语句,它是一个轻量级的嵌入式数据库。
(4)使用ContentProvider存储数据;主要用于应用程序之间进行数据交换,从而能够让其他的应用保存或读取此Content Provider的各种数据类型。
(5)网络存储数据;通过网络上提供给我们的存储空间来上传(存储)和下载(获取)我们存储在网络空间中的数据信息。


关于下列程序段的输出结果,说法正确的是:()

public class MyClass {
	static int i;
	public static void main(String argv[]) {
		System.out.println(i);
	}
}
A、有错误,变量i没有初始化。
B、null
C、1
D、0

答案:D


ListView的优化方案

答:1、如果自定义适配器,那么在getView方法中要考虑方法传进来的参数contentView是否为null,如果为null就创建contentView并返回,如果不为null则直接使用。在这个方法中尽可能少创建view。
2、给contentView设置tag(setTag()),传入一个viewHolder对象,用于缓存要显示的数据,可以达到图像数据异步加载的效果。
3、如果listview需要显示的item很多,就要考虑分页加载。比如一共要显示100条或者更多的时候,我们可以考虑先加载20条,等用户拉到列表底部的时候再去加载接下来的20条。


请介绍下Android的数据存储方式。

答:使用SharedPreferences存储数据;文件存储数据;SQLite数据库存储数据;使用ContentProvider存储数据;网络存储数据;
Preference,File, DataBase这三种方式分别对应的目录是/data/data/Package Name/Shared_Pref, /data/data/Package Name/files, /data/data/Package Name/database 。

一:使用SharedPreferences存储数据

首先说明SharedPreferences存储方式,它是Android提供的用来存储一些简单配置信息的一种机制,例如:登录用户的用户名与密码。其采用了Map数据结构来存储数据,以键值的方式存储,可以简单的读取与写入,具体实例如下:

void ReadSharedPreferences() {
	String strName, strPassword;
	SharedPreferences user = getSharedPreferences("user_info", 0);
	strName = user.getString("NAME", "");
	strPassword = user.getString("PASSWORD", "");
}
void WriteSharedPreferences(String strName, String strPassword) {
	SharedPreferences user = getSharedPreferences("user_info", 0);
	uer.edit();
	user.putString("NAME", strName);
	user.putString("PASSWORD", strPassword);
	user.commit();
}

数据读取与写入的方法都非常简单,只是在写入的时候有些区别:先调用edit()使其处于编辑状态,然后才能修改数据,最后使用commit()提交修改的数据。实际上SharedPreferences是采用了XML格式将数据存储到设备中,在DDMS中的File Explorer中的/data/data//shares_prefs下。使用SharedPreferences是有些限制的:只能在同一个包内使用,不能在不同的包之间使用。

二:文件存储数据

文件存储方式是一种较常用的方法,在Android中读取/写入文件的方法,与Java中实现I/O的程序是完全一样的,提供了openFileInput()和openFileOutput()方法来读取设备上的文件。具体实例如下:

String fn = "moandroid.log";
FileInputStream fis = openFileInput(fn);
FileOutputStream fos = openFileOutput(fn,Context.MODE_PRIVATE);

三:网络存储数据

网络存储方式,需要与Android 网络数据包打交道,关于Android 网络数据包的详细说明,请阅读Android SDK引用了Java SDK的哪些package?。

四:ContentProvider

1、ContentProvider简介

当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,如:采用文件方式对外共享数据,需要进行文件操作读写数据;采用sharedpreferences共享数据,需要使用sharedpreferences API读写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式。

2、Uri类简介

Uri代表了要操作的数据,Uri主要包含了两部分信息:1.需要操作的ContentProvider,2.对ContentProvider中的什么数据进行操作,一个Uri由以下几部分组成:
1.scheme:ContentProvider(内容提供者)的scheme已经由Android所规定为:content://…
2.主机名(或Authority):用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。
3.路径(path):可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:
要操作contact表中id为10的记录,可以构建这样的路径:/contact/10
要操作contact表中id为10的记录的name字段, contact/10/name
要操作contact表中的所有记录,可以构建这样的路径:/contact?
要操作的数据不一定来自数据库,也可以是文件等他存储方式,如下:
要操作xml文件中contact节点下的name节点,可以构建这样的路径:/contact/name
如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:
Uri uri = Uri.parse(“content://com.changcheng.provider.contactprovider/contact”)

3、UriMatcher、ContentUrist和ContentResolver简介

因为Uri代表了要操作的数据,所以我们很经常需要解析Uri,并从 Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher 和ContentUris 。掌握它们的使用,会便于我们的开发工作。
UriMatcher:用于匹配Uri,它的用法如下:
1.首先把你需要匹配Uri路径全部给注册上,如下:

//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码(-1)。
UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//如果match()方法匹配content://com.changcheng.sqlite.provider.contactprovider /contact路径,返回匹配码为1
uriMatcher.addURI("com.changcheng.sqlite.provider.contactprovider", "contact", 1);//添加需要匹配uri,如果匹配就会返回匹配码
//如果match()方法匹配 content://com.changcheng.sqlite.provider.contactprovider/contact/230路径,返回匹配码为2
uriMatcher.addURI("com.changcheng.sqlite.provider.contactprovider", "contact/", 2);//号为通配符

2.注册完需要匹配的Uri后,就可以使用uriMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用 addURI()方法传入的第三个参数,假设匹配 content://com.changcheng.sqlite.provider.contactprovider/contact路径,返回的匹配码为1。
ContentUris:用于获取Uri路径后面的ID部分,它有两个比较实用的方法:

withAppendedId(uri, id)用于为路径加上ID部分
parseId(uri)方法用于从路径中获取ID部分

ContentResolver:当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver类来完成,要获取ContentResolver 对象,可以使用Activity提供的getContentResolver()方法。 ContentResolver使用insert、delete、update、query方法,来操作数据。


activity的启动模式有哪些?是什么含义?

答:在android里,有4种activity的启动模式,分别为:

standard” (默认)
“singleTop”
“singleTask”
“singleInstance

它们主要有如下不同:

1. 如何决定所属task

“standard”和”singleTop”的activity的目标task,和收到的Intent的发送者在同一个task内,除非intent包括参数FLAG_ACTIVITY_NEW_TASK。
如果提供了FLAG_ACTIVITY_NEW_TASK参数,会启动到别的task里。
“singleTask”和”singleInstance”总是把activity作为一个task的根元素,他们不会被启动到一个其他task里。

2. 是否允许多个实例

“standard”和”singleTop”可以被实例化多次,并且存在于不同的task中,且一个task可以包括一个activity的多个实例;
“singleTask”和”singleInstance”则限制只生成一个实例,并且是task的根元素。 singleTop要求如果创建intent的时候栈顶已经有要创建 的Activity的实例,则将intent发送给该实例,而不发送给新的实例。

3. 是否允许其它activity存在于本task内

“singleInstance”独占一个task,其它activity不能存在那个task里;如果它启动了一个新的activity,不管新的activity的launch mode 如何,新的activity都将会到别的task里运行(如同加了FLAG_ACTIVITY_NEW_TASK参数)。
而另外三种模式,则可以和其它activity共存。

4. 是否每次都生成新实例

“standard”对于没一个启动Intent都会生成一个activity的新实例;
“singleTop”的activity如果在task的栈顶的话,则不生成新的该activity的实例,直接使用栈顶的实例,否则,生成该activity的实例。
比如现在task栈元素为A-B-C-D(D在栈顶),这时候给D发一个启动intent,如果D是“standard”的,则生成D的一个新实例,栈变为A-B-C-D-D。
如果D是singleTop的话,则不会生产D的新实例,栈状态仍为A-B-C-D
如果这时候给B发Intent的话,不管B的launchmode是”standard” 还是 “singleTop” ,都会生成B的新实例,栈状态变为A-B-C-D-B。
“singleInstance”是其所在栈的唯一activity,它会每次都被重用。
“singleTask”如果在栈顶,则接受intent,否则,该intent会被丢弃,但是该task仍会回到前台。
当已经存在的activity实例处理新的intent时候,会调用onNewIntent()方法
如果收到intent生成一个activity实例,那么用户可以通过back键回到上一个状态;如果是已经存在的一个activity来处理这个intent的话,用户不能通过按back键返回到这之前的状态。


跟activity和Task 有关的 Intent启动方式有哪些?其含义?

核心的Intent Flag有:

FLAG_ACTIVITY_NEW_TASK
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
FLAG_ACTIVITY_SINGLE_TOP
FLAG_ACTIVITY_NEW_TASK

如果设置,这个Activity会成为历史stack中一个新Task的开始。一个Task(从启动它的Activity到下一个Task中的Activity)定义了用户可以迁移的Activity原子组。Task可以移动到前台和后台;在某个特定Task中的所有Activity总是保持相同的次序。
这个标志一般用于呈现“启动”类型的行为:它们提供用户一系列可以单独完成的事情,与启动它们的Activity完全无关。
使用这个标志,如果正在启动的Activity的Task已经在运行的话,那么,新的Activity将不会启动;代替的,当前Task会简单的移入前台。参考FLAG_ACTIVITY_MULTIPLE_TASK标志,可以禁用这一行为。
这个标志不能用于调用方对已经启动的Activity请求结果。

FLAG_ACTIVITY_CLEAR_TOP

如果设置,并且这个Activity已经在当前的Task中运行,因此,不再是重新启动一个这个Activity的实例,而是在这个Activity上方的所有Activity都将关闭,然后这个Intent会作为一个新的Intent投递到老的Activity(现在位于顶端)中。
例如,假设一个Task中包含这些Activity:A,B,C,D。如果D调用了startActivity(),并且包含一个指向Activity B的Intent,那么,C和D都将结束,然后B接收到这个Intent,因此,目前stack的状况是:A,B。
上例中正在运行的Activity B既可以在onNewIntent()中接收到这个新的Intent,也可以把自己关闭然后重新启动来接收这个Intent。如果它的启动模式声明为“multiple”(默认值),并且你没有在这个Intent中设置FLAG_ACTIVITY_SINGLE_TOP标志,那么它将关闭然后重新创建;对于其它的启动模式,或者在这个Intent中设置FLAG_ACTIVITY_SINGLE_TOP标志,都将把这个Intent投递到当前这个实例的onNewIntent()中。
这个启动模式还可以与FLAG_ACTIVITY_NEW_TASK结合起来使用:用于启动一个Task中的根Activity,它会把那个Task中任何运行的实例带入前台,然后清除它直到根Activity。这非常有用,例如,当从Notification Manager处启动一个Activity。

FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

如果设置这个标志,这个activity不管是从一个新的栈启动还是从已有栈推到栈顶,它都将以the front door of the task的方式启动。这就讲导致任何与应用相关的栈都讲重置到正常状态(不管是正在讲activity移入还是移除),如果需要,或者直接重置该栈为初始状态。

FLAG_ACTIVITY_SINGLE_TOP

如果设置,当这个Activity位于历史stack的顶端运行时,不再启动一个新的

FLAG_ACTIVITY_BROUGHT_TO_FRONT

这个标志一般不是由程序代码设置的,如在launchMode中设置singleTask模式时系统帮你设定。

FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET

如果设置,这将在Task的Activity stack中设置一个还原点,当Task恢复时,需要清理Activity。也就是说,下一次Task带着FLAG_ACTIVITY_RESET_TASK_IF_NEEDED标记进入前台时(典型的操作是用户在主画面重启它),这个Activity和它之上的都将关闭,以至于用户不能再返回到它们,但是可以回到之前的Activity。
这在你的程序有分割点的时候很有用。例如,一个e-mail应用程序可能有一个操作是查看一个附件,需要启动图片浏览Activity来显示。这个Activity应该作为e-mail应用程序Task的一部分,因为这是用户在这个Task中触发的操作。然而,当用户离开这个Task,然后从主画面选择e-mail app,我们可能希望回到查看的会话中,但不是查看图片附件,因为这让人困惑。通过在启动图片浏览时设定这个标志,浏览及其它启动的Activity在下次用户返回到mail程序时都将全部清除。

FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

如果设置,新的Activity不会在最近启动的Activity的列表中保存。

FLAG_ACTIVITY_FORWARD_RESULT

如果设置,并且这个Intent用于从一个存在的Activity启动一个新的Activity,那么,这个作为答复目标的Activity将会传到这个新的Activity中。这种方式下,新的Activity可以调用setResult(int),并且这个结果值将发送给那个作为答复目标的 Activity。

FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY

这个标志一般不由应用程序代码设置,如果这个Activity是从历史记录里启动的(常按HOME键),那么,系统会帮你设定。

FLAG_ACTIVITY_MULTIPLE_TASK

不要使用这个标志,除非你自己实现了应用程序启动器。与FLAG_ACTIVITY_NEW_TASK结合起来使用,可以禁用把已存的Task送入前台的行为。当设置时,新的Task总是会启动来处理Intent,而不管这是是否已经有一个Task可以处理相同的事情。
由于默认的系统不包含图形Task管理功能,因此,你不应该使用这个标志,除非你提供给用户一种方式可以返回到已经启动的Task。
如果FLAG_ACTIVITY_NEW_TASK标志没有设置,这个标志被忽略。

FLAG_ACTIVITY_NO_ANIMATION

如果在Intent中设置,并传递给Context.startActivity()的话,这个标志将阻止系统进入下一个Activity时应用Acitivity迁移动画。这并不意味着动画将永不运行——如果另一个Activity在启动显示之前,没有指定这个标志,那么,动画将被应用。这个标志可以很好的用于执行一连串的操作,而动画被看作是更高一级的事件的驱动。

FLAG_ACTIVITY_NO_HISTORY

如果设置,新的Activity将不再历史stack中保留。用户一离开它,这个Activity就关闭了。这也可以通过设置noHistory特性。

FLAG_ACTIVITY_NO_USER_ACTION

如果设置,作为新启动的Activity进入前台时,这个标志将在Activity暂停之前阻止从最前方的Activity回调的onUserLeaveHint()。
典型的,一个Activity可以依赖这个回调指明显式的用户动作引起的Activity移出后台。这个回调在Activity的生命周期中标记一个合适的点,并关闭一些Notification。
如果一个Activity通过非用户驱动的事件,如来电或闹钟,启动的,这个标志也应该传递给Context.startActivity,保证暂停的Activity不认为用户已经知晓其Notification。

FLAG_ACTIVITY_PREVIOUS_IS_TOP

If set and this intent is being used to launch a new activity from an existing one, the current activity will not be counted as the top activity for deciding whether the new intent should be delivered to the top instead of starting a new one. The previous activity will be used as the top, with the assumption being that the current activity will finish itself immediately.

FLAG_ACTIVITY_REORDER_TO_FRONT

如果在Intent中设置,并传递给Context.startActivity(),这个标志将引发已经运行的Activity移动到历史stack的顶端。
例如,假设一个Task由四个Activity组成:A,B,C,D。如果D调用startActivity()来启动Activity B,那么,B会移动到历史stack的顶端,现在的次序变成A,C,D,B。如果FLAG_ACTIVITY_CLEAR_TOP标志也设置的话,那么这个标志将被忽略。


请描述下Activity的生命周期。

答:activity的生命周期方法有:onCreate()、onStart()、onReStart()、onResume()、onPause()、onStop()、onDestory();
可见生命周期:从onStart()直到系统调用onStop()
前台生命周期:从onResume()直到系统调用onPause()


activity在屏幕旋转时的生命周期

答:不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次;设置Activity的android:configChanges=”orientation”时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次;设置Activity的android:configChanges=”orientation|keyboardHidden”时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法


如何启用Service,如何停用Service。

服务的开发比较简单,如下:
第一步:继承Service类
public class SMSService extends Service {}
第二步:在AndroidManifest.xml文件中的节点里对服务进行配置:
服务不能自己运行,需要通过调用Context.startService()或Context.bindService()方法启动服务。这两个方法都可以启动Service,但是它们的使用场合有所不同。使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。
如果打算采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。
如果打算采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()–>onDestroy()方法。

服务常用生命周期回调方法如下:

1、onCreate()该方法在服务被创建时调用,该方法只会被调用一次,无论调用多少次startService()或bindService()方法,服务也只被创建一次。
2、onDestroy()该方法在服务被终止时调用。
与采用Context.startService()方法启动服务有关的生命周期方法
3、onStart()只有采用Context.startService()方法启动服务时才会回调该方法。该方法在服务开始运行时被调用。多次调用startService()方法尽管不会多次创建服务,但onStart() 方法会被多次调用。
与采用Context.bindService()方法启动服务有关的生命周期方法
4、onBind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用,当调用者与服务已经绑定,多次调用Context.bindService()方法并不会导致该方法被多次调用。
5、onUnbind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务解除绑定时被调用。


注册广播有几种方式,这些方式有何优缺点?请谈谈Android引入广播机制的用意。

答:首先写一个类要继承BroadcastReceiver
第一种:在清单文件中声明,添加

<receive android:name=".IncomingSMSReceiver " >
	<intent-filter>
	   <action android:name="android.provider.Telephony.SMS_RECEIVED")
	<intent-filter>
<receiver>

第二种使用代码进行注册如:

IntentFilter filter =  new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
IncomingSMSReceiver receiver = new IncomgSMSReceiver();
registerReceiver(receiver.filter);

两种注册类型的区别是:
1)第一种不是常驻型广播,也就是说广播跟随程序的生命周期。
2)第二种是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。


请解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系。

答:简单的说,Handler获取当前线程中的looper对象,looper用来从存放Message的MessageQueue中取出Message,再有Handler进行Message的分发和处理.
Message Queue(消息队列):用来存放通过Handler发布的消息,通常附属于某一个创建它的线程,可以通过Looper.myQueue()得到当前线程的消息队列
Handler:可以发布或者处理一个消息或者操作一个Runnable,通过Handler发布消息,消息将只会发送到与它关联的消息队列,然也只能处理该消息队列中的消息
Looper:是Handler和消息队列之间通讯桥梁,程序组件首先通过Handler把消息传递给Looper,Looper把消息放入队列。Looper也把消息队列里的消息广播给所有的
Handler:Handler接受到消息后调用handleMessage进行处理
Message:消息的类型,在Handler类中的handleMessage方法中得到单个的消息进行处理
在单线程模型下,为了线程通信问题,Android设计了一个Message Queue(消息队列), 线程间可以通过该Message Queue并结合Handler和Looper组件进行信息交换。下面将对它们进行分别介绍:

1. Message

Message消息,理解为线程间交流的信息,处理数据后台线程需要更新UI,则发送Message内含一些数据给UI线程。

2. Handler

Handler处理者,是Message的主要处理者,负责Message的发送,Message内容的执行处理。后台线程就是通过传进来的Handler对象引用来sendMessage(Message)。而使用Handler,需要implement 该类的 handleMessage(Message)方法,它是处理这些Message的操作内容,例如Update UI。通常需要子类化Handler来实现handleMessage方法。

3. Message Queue

Message Queue消息队列,用来存放通过Handler发布的消息,按照先进先出执行。
每个message queue都会有一个对应的Handler。Handler会向message queue通过两种方法发送消息:sendMessage或post。这两种消息都会插在message queue队尾并按先进先出执行。但通过这两种方法发送的消息执行的方式略有不同:通过sendMessage发送的是一个message对象,会被Handler的handleMessage()函数处理;而通过post方法发送的是一个runnable对象,则会自己执行。

4. Looper

Looper是每条线程里的Message Queue的管家。Android没有Global的Message Queue,而Android会自动替主线程(UI线程)建立Message Queue,但在子线程里并没有建立Message Queue。所以调用Looper.getMainLooper()得到的主线程的Looper不为NULL,但调用Looper.myLooper()得到当前线程的Looper就有可能为NULL。对于子线程使用Looper,API Doc提供了正确的使用方法:这个Message机制的大概流程:

  1. 在Looper.loop()方法运行开始后,循环地按照接收顺序取出Message Queue里面的非NULL的Message。
  2. 一开始Message Queue里面的Message都是NULL的。当Handler.sendMessage(Message)到Message Queue,该函数里面设置了那个Message对象的target属性是当前的Handler对象。随后Looper取出了那个Message,则调用该Message的target指向的Hander的dispatchMessage函数对Message进行处理。在dispatchMessage方法里,如何处理Message则由用户指定,三个判断,优先级从高到低:
    1) Message里面的Callback,一个实现了Runnable接口的对象,其中run函数做处理工作;
    2) Handler里面的mCallback指向的一个实现了Callback接口的对象,由其handleMessage进行处理;
    3) 处理消息Handler对象对应的类继承并实现了其中handleMessage函数,通过这个实现的handleMessage函数处理消息。
    由此可见,我们实现的handleMessage方法是优先级最低的!
  3. Handler处理完该Message (update UI) 后,Looper则设置该Message为NULL,以便回收!
    在网上有很多文章讲述主线程和其他子线程如何交互,传送信息,最终谁来执行处理信息之类的,个人理解是最简单的方法——判断Handler对象里面的Looper对象是属于哪条线程的,则由该线程来执行!
  4. 当Handler对象的构造函数的参数为空,则为当前所在线程的Looper;
  5. Looper.getMainLooper()得到的是主线程的Looper对象,Looper.myLooper()得到的是当前线程的Looper对象。

说说mvc模式的原理,它在android中的运用,android的官方建议应用程序的开发采用mvc模式。何谓mvc?

mvc是model,view,controller的缩写,mvc包含三个部分:
模型(model)对象:是应用程序的主体部分,所有的业务逻辑都应该写在该层。
视图(view)对象:是应用程序中负责生成用户界面的部分。也是在整个mvc架构中用户唯一可以看到的一层,接收用户的输入,显示处理结果。
控制器(control)对象:是根据用户的输入,控制用户界面数据显示及更新model对象状态的部分,控制器更重要的一种导航功能,响应用户出发的相关事件,交给m层处理。
android鼓励弱耦合和组件的重用,在android中mvc的具体体现如下:
1)视图层(view):一般采用xml文件进行界面的描述,使用的时候可以非常方便的引入,当然,如果你对android了解的比较的多了话,就一定可以想到在android中也可以使用javascript+html等的方式作为view层,当然这里需要进行java和javascript之间的通信,幸运的是,android提供了它们之间非常方便的通信实现。
2)控制层(controller):android的控制层的重任通常落在了众多的acitvity的肩上,这句话也就暗含了不要在acitivity中写代码,要通过activity交割model业务逻辑层处理,这样做的另外一个原因是android中的acitivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。
3)模型层(model):对数据库的操作、对网络等的操作都应该在model里面处理,当然对业务计算等操作也是必须放在的该层的。


android 中service的实现方法是:

答案:startservice和bindservice。


下列程序段的输出结果是:()

void complicatedexpression_r() {
	int x = 20, y = 30;
	boolean b;
	b = x > 50 && y > 60 || x > 50 && y < -60 || x < -50 && y > 60
			|| x < -50 && y < -60;
	System.out.println(b);
}
A、true  
B、false  
C、1  
D、011.activity

答案:B


Android中Activity, Intent, Content Provider, Service各有什么区别。

答:
Activity:活动,是最基本的android应用程序组件。一个活动就是一个单独的屏幕,每一个活动都被实现为一个独立的类,并且从活动基类继承而来。
Intent:意图,描述应用想干什么。最重要的部分是动作和动作对应的数据。
Content Provider:内容提供器,android应用程序能够将它们的数据保存到文件、SQLite数据库中,甚至是任何有效的设备中。当你想将你的应用数据和其他应用共享时,内容提供器就可以发挥作用了。
Service:服务,具有一段较长生命周期且没有用户界面的程序。


什么情况会导致Force Close?如何避免?能否捕获导致其的异常?

答:程序出现异常,比如nullpointer。
避免:编写程序时逻辑连贯,思维缜密。能捕获异常,在logcat中能看到异常信息


描述一下android的系统架构

android系统架构分从下往上为linux 内核层、运行库、应用程序框架层、和应用程序层。

linuxkernel:负责硬件的驱动程序、网络、电源、系统安全以及内存管理等功能。

libraries和 android runtime:libraries:即c/c++函数库部分,大多数都是开放源代码的函数库,例如webkit(引擎),该函数库负责 android网页浏览器的运行,例如标准的c函数库libc、openssl、sqlite等,当然也包括支持游戏开发2dsgl和 3dopengles,在多媒体方面有mediaframework框架来支持各种影音和图形文件的播放与显示,例如mpeg4、h.264、mp3、 aac、amr、jpg和png等众多的多媒体文件格式。android的runtime负责解释和执行生成的dalvik格式的字节码。

applicationframework(应用软件架构),java应用程序开发人员主要是使用该层封装好的api进行快速开发。

applications:该层是java的应用程序层,android内置的googlemaps、e-mail、即时通信工具、浏览器、mp3播放器等处于该层,java开发人员开发的程序也处于该层,而且和内置的应用程序具有平等的位置,可以调用内置的应用程序,也可以替换内置的应用程序。

上面的四个层次,下层为上层服务,上层需要下层的支持,调用下层的服务,这种严格分层的方式带来的极大的稳定性、灵活性和可扩展性,使得不同层的开发人员可以按照规范专心特定层的开发。

android应用程序使用框架的api并在框架下运行,这就带来了程序开发的高度一致性,另一方面也告诉我们,要想写出优质高效的程序就必须对整个applicationframework进行非常深入的理解。精通applicationframework,你就可以真正的理解android的设计和运行机制,也就更能够驾驭整个应用层的开发。


请介绍下ContentProvider是如何实现数据共享的。

一个程序可以通过实现一个Content provider的抽象接口将自己的数据完全暴露出去,而且Content providers是以类似数据库中表的方式将数据暴露。Content providers存储和检索数据,通过它可以让所有的应用程序访问到,这也是应用程序之间唯一共享数据的方法。
要想使应用程序的数据公开化,可通过2种方法:创建一个属于你自己的Content provider或者将你的数据添加到一个已经存在的Content provider中,前提是有相同数据类型并且有写入Content provider的权限。
如何通过一套标准及统一的接口获取其他应用程序暴露的数据?
Android提供了ContentResolver,外界的程序可以通过ContentResolver接口访问ContentProvider提供的数据。


Service和Thread的区别?

答:servie是系统的组件,它由系统进程托管(servicemanager);它们之间的通信类似于client和server,是一种轻量级的ipc通信,这种通信的载体是binder,它是在linux层交换信息的一种ipc。而thread是由本应用程序托管。
1). Thread:Thread是程序执行的最小单元,它是分配CPU的基本单位。可以用 Thread 来执行一些异步的操作。
2). Service:Service是android的一种机制,当它运行的时候如果是Local Service,那么对应的Service是运行在主进程的main线程上的。如:onCreate,onStart 这些函数在被系统调用的时候都是在主进程的 main 线程上运行的。如果是Remote Service,那么对应的 Service 则是运行在独立进程的 main 线程上。
既然这样,那么我们为什么要用Service呢?其实这跟android的系统机制有关,我们先拿Thread来说。Thread的运行是独立于Activity的,也就是说当一个Activity被finish之后,如果你没有主动停止Thread或者Thread里的run方法没有执行完毕的话,Thread也会一直执行。因此这里会出现一个问题:当 Activity 被 finish 之后,你不再持有该 Thread 的引用。另一方面,你没有办法在不同的 Activity 中对同一Thread进行控制。
举个例子:如果你的Thread需要不停地隔一段时间就要连接服务器做某种同步的话,该Thread需要在Activity没有start的时候也在运行。这个时候当你start一个Activity就没有办法在该Activity里面控制之前创建的Thread。因此你便需要创建并启动一个Service,在Service里面创建、运行并控制该 Thread,这样便解决了该问题(因为任何 Activity 都可以控制同一Service,而系统也只会创建一个对应Service的实例)。
因此你可以把Service想象成一种消息服务,而你可以在任何有Context的地方调用Context.startService、Context.stopService、Context.bindService,Context.unbindService,来控制它,你也可以在Service里注册BroadcastReceiver,在其他地方通过发送broadcast来控制它,当然这些都是 Thread 做不到的。


Android本身的api并未声明会抛出异常,则其在运行时有无可能抛出runtime异常,你遇到过吗?诺有的话会导致什么问题?如何解决?

答:会,比如nullpointerException。我遇到过,比如textview.setText()时,textview没有初始化。会导致程序无法正常运行出现forceclose。打开控制台查看logcat信息找出异常信息并修改程序。


如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态?

答:重写onSaveInstanceState()方法,在此方法中保存需要保存的数据,该方法将会在activity被回收之前调用。通过重写onRestoreInstanceState()方法可以从中提取保存好的数据


如何将一个Activity设置成窗口的样式。

答:中配置:android :theme=”@android:style/Theme.Dialog”
另外android:theme=”@android:style/Theme.Translucent” 是设置透明


如何退出Activity?如何安全退出已调用多个Activity的Application?

答:对于单一Activity的应用来说,退出很简单,直接finish()即可。当然,也可以用killProcess()和System.exit()这样的方法。
对于多个activity,1、记录打开的Activity:每打开一个Activity,就记录下来。在需要退出时,关闭每一个Activity即可。2、发送特定广播:在需要结束应用时,发送一个特定的广播,每个Activity收到广播后,关闭即可。3、递归退出:在打开新的Activity时使用startActivityForResult,然后自己加标志,在onActivityResult中处理,递归关闭。为了编程方便,最好定义一个Activity基类,处理这些共通问题。
在2.1之前,可以使用ActivityManager的restartPackage方法。
它可以直接结束整个应用。在使用时需要权限android.permission.RESTART_PACKAGES。
注意不要被它的名字迷惑。
可是,在2.2,这个方法失效了。在2.2添加了一个新的方法,killBackground Processes(),需要权限android.permission.KILL_BACKGROUND_PROCESSES。可惜的是,它和2.2的restartPackage一样,根本起不到应有的效果。
另外还有一个方法,就是系统自带的应用程序管理里,强制结束程序的方法,forceStopPackage()。它需要权限android.permission.FORCE_STOP_PACKAGES。并且需要添加android:sharedUserId=”android.uid.system”属性。同样可惜的是,该方法是非公开的,他只能运行在系统进程,第三方程序无法调用。
因为需要在Android.mk中添加LOCAL_CERTIFICATE := platform。
而Android.mk是用于在Android源码下编译程序用的。
从以上可以看出,在2.2,没有办法直接结束一个应用,而只能用自己的办法间接办到。
现提供几个方法,供参考:

1、抛异常强制退出:

该方法通过抛异常,使程序Force Close。
验证可以,但是,需要解决的问题是,如何使程序结束掉,而不弹出Force Close的窗口。

2、记录打开的Activity:

每打开一个Activity,就记录下来。在需要退出时,关闭每一个Activity即可。

3、发送特定广播:

在需要结束应用时,发送一个特定的广播,每个Activity收到广播后,关闭即可。

4、递归退出

在打开新的Activity时使用startActivityForResult,然后自己加标志,在onActivityResult中处理,递归关闭。
除了第一个,都是想办法把每一个Activity都结束掉,间接达到目的。但是这样做同样不完美。你会发现,如果自己的应用程序对每一个Activity都设置了nosensor,在两个Activity结束的间隙,sensor可能有效了。但至少,我们的目的达到了,而且没有影响用户使用。为了编程方便,最好定义一个Activity基类,处理这些共通问题。


AIDL的全称是什么?如何工作?能处理哪些类型的数据?

答:全称是:Android Interface Define Language
在Android中,每个应用程序都可以有自己的进程.在写UI应用的时候,经常要用到Service.在不同的进程中,怎样传递对象呢?显然,Java中不允许跨进程内存共享.因此传递对象,只能把对象拆分成操作系统能理解的简单形式,以达到跨界对象访问的目的.在J2EE中,采用RMI的方式,可以通过序列化传递对象. 在Android中, 则采用AIDL的方式. 理论上AIDL可以传递Bundle,实际上做起来却比较麻烦。
AIDL(AndRoid接口描述语言)是一种借口描述语言; 编译器可以通过aidl文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程的目的. 如果需要在一个Activity中,访问另一个Service中的某个对象,需要先将对象转化成AIDL可识别的参数(可能是多个参数),然后使用AIDL来传递这些参数, 在消息的接收端, 使用这些参数组装成自己需要的对象.
AIDL的IPC的机制和COM或CORBA类似,是基于接口的,但它是轻量级的。它使用代理类在客户端和实现层间传递值.如果要使用AIDL,需要完成2件事情: 1. 引入AIDL的相关类.; 2. 调用aidl产生的class.

AIDL的创建方法:

AIDL语法很简单,可以用来声明一个带一个或多个方法的接口,也可以传递参数和返回值。由于远程调用的需要,这些参数和返回值并不是任何类型.下面是些AIDL支持的数据类型:

  1. 不需要import声明的简单Java编程语言类型(int,boolean等)
  2. String, CharSequence不需要特殊声明
  3. List, Map和Parcelables类型, 这些类型内所包含的数据成员也只能是简单数据类型, String等其他比支持的类型.
    (另外: 我没尝试Parcelables, 在Eclipse+ADT下编译不过, 或许以后会有所支持)

请解释下Android程序运行时权限与文件系统权限的区别。

答:运行时权限Dalvik( android授权)
文件系统 linux 内核授权


activity一般会重载7个方法用来维护其生命周期,除了onCreate(),onStart(),onDestory()外还有,,,

答案:onrestart,onresume,onpause,onstop


对一些资源以及状态的操作保存,最好是保存在生命周期的哪个函数中进行()

AonPause()  
BonCreate()   
ConResume()   
DonStart()

答案:D


View, surfaceView, GLSurfaceView有什么区别。

答:view是最基础的,必须在UI主线程内更新画面,速度较慢。
SurfaceView 是view的子类,类似使用双缓机制,在新的线程中更新画面所以刷新界面速度比view快。
GLSurfaceView 是SurfaceView的子类,opengl 专用的。


系统上安装了多种浏览器,能否指定某浏览器访问指定页面?请说明原由。

通过直接发送Uri把参数带过去,或者通过manifest里的intentfilter里的data属性


android系统的优势和不足

答:Android平台手机 5大优势:

一、开放性

在优势方面,Android平台首先就是其开发性,开发的平台允许任何移动终端厂商加入到Android联盟中来。显著的开放性可以使其拥有更多的开发者,随着用户和应用的日益丰富,一个崭新的平台也将很快走向成熟。开放性对于Android的发展而言,有利于积累人气,这里的人气包括消费者和厂商,而对于消费者来讲,随大的受益正是丰富的软件资源。开放的平台也会带来更大竞争,如此一来,消费者将可以用更低的价位购得心仪的手机。

二、挣脱运营商的束缚

在过去很长的一段时间,特别是在欧美地区,手机应用往往受到运营商制约,使用什么功能接入什么网络,几乎都受到运营商的控制。从去年iPhone上市,用户可以更加方便地连接网络,运营商的制约减少。随着EDGE、HSDPA这些2G至3G移动网络的逐步过渡和提升,手机随意接入网络已不是运营商口中的笑谈,当你可以通过手机IM软件方便地进行即时聊天时,再回想不久前天价的彩信和图铃下载业务,是不是像噩梦一样?互联网巨头Google推动的Android终端天生就有网络特色,将让用户离互联网更近。

三、丰富的硬件选择

这一点还是与Android平台的开放性相关,由于Android的开放性,众多的厂商会推出千奇百怪,功能特色各具的多种产品。功能上的差异和特色,却不会影响到数据同步、甚至软件的兼容,好比你从诺基亚 Symbian风格手机 一下改用苹果 iPhone ,同时还可将Symbian中优秀的软件带到iPhone上使用、联系人等资料更是可以方便地转移,是不是非常方便呢?

四、不受任何限制的开发商

Android平台提供给第三方开发商一个十分宽泛、自由的环境,不会受到各种条条框框的阻扰,可想而知,会有多少新颖别致的软件会诞生。但也有其两面性,血腥、暴力、情色方面的程序和游戏如可控制正是留给Android难题之一。
五、无缝结合的Google应用
如今叱诧互联网的Google已经走过10年度历史,从搜索巨人到全面的互联网渗透,Google服务如地图、邮件、搜索等已经成为连接用户和互联网的重要纽带,而Android平台手机将无缝结合这些优秀的Google服务。
再说Android的5大不足:

一、安全和隐私

由于手机与互联网的紧密联系,个人隐私很难得到保守。除了上网过程中经意或不经意留下的个人足迹,Google这个巨人也时时站在你的身后,洞穿一切,因此,互联网的深入将会带来新一轮的隐私危机。

二、首先开卖Android手机的不是最大运营商

众所周知,T-Mobile在23日,于美国纽约发布了Android首款手机G1。但是在北美市场,最大的两家运营商乃AT&T和Verizon,而目前所知取得Android手机销售权的仅有T-Mobile和Sprint,其中T-Mobile的3G网络相对于其他三家也要逊色不少,因此,用户可以买账购买G1,能否体验到最佳的3G网络服务则要另当别论了!

三、运营商仍然能够影响到Android手机

在国内市场,不少用户对购得移动定制机不满,感觉所购的手机被人涂画了广告一般。这样的情况在国外市场同样出现。Android手机的另一发售运营商Sprint就将在其机型中内置其手机商店程序。

四、同类机型用户减少

在不少手机论坛都会有针对某一型号的子论坛,对一款手机的使用心得交流,并分享软件资源。而对于Android平台手机,由于厂商丰富,产品类型多样,这样使用同一款机型的用户越来越少,缺少统一机型的程序强化。举个稍显不当的例子,现在山寨机泛滥,品种各异,就很少有专门针对某个型号山寨机的讨论和群组,除了哪些功能异常抢眼、颇受追捧的机型以外。

五、过分依赖开发商缺少标准配置

在使用PC端的Windows Xp系统的时候,都会内置微软Windows Media Player这样一个浏览器程序,用户可以选择更多样的播放器,如Realplay或暴风影音等。但入手开始使用默认的程序同样可以应付多样的需要。在Android平台中,由于其开放性,软件更多依赖第三方厂商,比如Android系统的SDK中就没有内置音乐播放器,全部依赖第三方开发,缺少了产品的统一性。


DDMS和TraceView的区别?

DDMS是一个程序执行查看器,在里面可以看见线程和堆栈等信息,TraceView是程序性能分析器 。


java中如何引用本地语言

可以用JNI(java native interface java本地接口)接口 。


谈谈Android的IPC(进程间通信)机制

IPC是内部进程通信的简称,是共享”命名管道”的资源。Android中的IPC机制是为了让Activity和Service之间可以随时的进行交互,故在Android中该机制,只适用于Activity和Service之间的通信,类似于远程方法调用,类似于C/S模式的访问。通过定义AIDL接口文件来定义IPC接口。Servier端实现IPC接口,Client端调用IPC接口本地代理。


NDK是什么

NDK是一些列工具的集合,NDK提供了一系列的工具,帮助开发者迅速的开发C/C++的动态库,并能自动将so和java 应用打成apk包。
NDK集成了交叉编译器,并提供了相应的mk文件和隔离cpu、平台等的差异,开发人员只需简单的修改mk文件就可以创建出so


android的数据存储的方式,,,,_____。

答案:sharedpreference,文件,SQlite,contentprovider,网络


Intent传递数据时,下列的数据类型哪些可以被传递()(多选)

A、Serializable  
B、charsequence  
C、Parcelable  
D、Bundle

答案:ABCD


Adapter有什么作用?常见的Adapter有哪些?

答:Adapter是连接后端数据和前端显示的适配器接口。常见的Adapter有ArrayAdapter, BaseAdapter, CursorAdapter, HeaderViewListAdapter, ListAdapter, ResourceCursorAdapter, SimpleAdapter, SimpleCursorAdapter, SpinnerAdapter, WrapperListAdapter等


当启动一个Activity并且新的Activity执行完后需要返回到启动它的Activity来执行 的回调函数是_____。

答案:startActivityResult()


android 中下列属于Intent的作用的是()

A、实现应用程序间的数据共享
B、是一段长的生命周期,没有用户界面的程序,可以保持应用在后台运行,而不会因为切换页面而消失
C、可以实现界面间的切换,可以包含动作和动作数据,连接四大组件的纽带
D、处理一个应用程序整体性的工作

答案:C


Manifest.xml文件中主要包括哪些信息?

答:manifest:根节点,描述了package中所有的内容。
uses-permission:请求你的package正常运作所需赋予的安全许可。
permission:声明了安全许可来限制哪些程序能你package中的组件和功能。
instrumentation:声明了用来测试此package或其他package指令组件的代码。
application:包含package中application级别组件声明的根节点。
activity:Activity是用来与用户交互的主要工具。
receiver:IntentReceiver能使的application获得数据的改变或者发生的操作,即使它当前不在运行。
service:Service是能在后台运行任意时间的组件。
provider:ContentProvider是用来管理持久化数据并发布给其他应用程序使用的组件。


请使用命令行的方式创建一个名字为myAvd,sdk版本为2.2,sd卡是在d盘的根目录下,名字为scard.img,并指定屏幕大小HVGA.____

答案:adnroid create acd -n myAvd -t 8 -s HVDA - C d:\card.img


下列属于SAX解析xml文件的优点的是()

A、将整个文档树在内存中,便于操作,支持删除,修改,重新排列等多种功能
B、不用事先调入整个文档,占用资源少
C、整个文档调入内存,浪费时间和空间
D、不是长久驻留在内存,数据不是持久的,事件过后,若没有保存数据,数据就会消失

答案:B


根据自己的理解描述下Android数字签名。

答:(1)所有的应用程序都必须有数字证书,Android系统不会安装一个没有数字证书的应用程序。
(2)Android程序包使用的数字证书可以是自签名的,不需要一个权威的数字证书机构签名认证。
(3)如果要正式发布一个Android,必须使用一个合适的私钥生成的数字证书来给程序签名,而不能使用adt插件或者ant工具生成的调试证书来发布。
(4)数字证书都是有有效期的,Android只是在应用程序安装的时候才会检查证书的有效期。如果程序已经安装在系统中,即使证书过期也不会影响程序的正常功能。


程序运行的结果是:__

public class Example {
	String str = new String("good");
	char[] ch = { 'a', 'b', 'c' };
	public static void main(String args[]) {
		Example ex = new Example();
		ex.change(ex.str, ex.ch);
		System.out.print(ex.str + " and ");
		Sytem.out.print(ex.ch);
	}
	public void change(String str, char ch[]) {
		str = "test ok";
		ch[0] = 'g';
	}
}

答案:good and gbc


下面的对自定style的方式正确的是()

A、
<resources>
	<style name="myStyle">
		<item name="android:layout_width">fill_parent</item>
	</style>
</resources>

B、
<style name="myStyle">
	<item name="android:layout_width">fill_parent</item>
</style>

C、
<resources>
	<item name="android:layout_width">fill_parent</item>
</resources>

D、
<resources>
	<style name="android:layout_width">fill_parent</style>
</resources>

答案:A


Android dvm的进程和Linux的进程,应用程序的进程是否为同一个概念?

答:DVM指dalivk的虚拟机。每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例。而每一个DVM都是在Linux中的一个进程,所以说可以认为是同一个概念。



本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

好久没写博客了,原因竟然是。。 上一篇
蒲公英 下一篇