如下面试题来自于百度、小米、乐视、美团、5八、猎豹、360、新浪、搜狐内部题库html
熟悉本文中列出的知识点会大大增长经过前两轮技术面试的概率。java
欢迎一线公司员工提交内部面试题库,欢迎star。 ##目录android
java基础git
接口的意义-百度
抽象类的意义-乐视
内部类的做用-乐视
父类的静态方法可否被子类重写-猎豹
java排序算法-美团
列举java的集合和继承关系-百度-美团
java虚拟机的特性-百度-乐视
哪些状况下的对象会被垃圾回收机制处理掉-美团-小米
进程和线程的区别-猎豹-美团
==和equals和hashCode的区别-乐视
常见的排序算法时间复杂度-小米
HashMap的实现原理-美团
java状态机
int-char-long各占多少字节数
int与integer的区别
string-stringbuffer-stringbuilder区别-小米-乐视-百度
java多态-乐视
什么致使线程阻塞-58-美团
抽象类接口区别-360
容器类之间的区别-乐视-美团
内部类
hashmap和hashtable的区别-乐视-小米
ArrayMap对比HashMap
安卓程序员
如何导入外部数据库
本地广播和全局广播有什么差异
intentService做用是什么,AIDL解决了什么问题?-小米
Activity,Window,View三者的差异,fragment的特色?-360
描述一次网络请求的流程-新浪
Handler、Thread和HandlerThread的差异-小米
低版本SDK实现高版本api-小米
Ubuntu编译安卓系统-百度
launch mode应用场景-百度-小米-乐视
Touch事件传递流程-小米
view绘制流程-百度
多线程-360
线程同步-百度
什么状况致使内存泄漏-美团
ANR定位和修正
什么状况致使oom-乐视-美团
Android Service与Activity之间通讯的几种方式
Android各个版本API的区别
Android代码中实现WAP方式联网-360
如何保证service在后台不被kill
Requestlayout,onlayout,onDraw,DrawChild区别与联系-猎豹
invalidate()和postInvalidate() 的区别及使用-百度
Android动画框架实现原理
Android为每一个应用程序分配的内存大小是多少?-美团
Android View刷新机制-百度-美团
LinearLayout对比RelativeLayout-百度
优化自定义view百度-乐视-小米
ContentProvider-乐视
fragment生命周期
volley解析-美团-乐视
Android Glide源码解析
Android 设计模式
架构设计-搜狐
Android属性动画特性-乐视-小米
专题github
性能优化
架构分析
阿里巴巴
腾讯
###java面试
####接口的意义-百度算法
规范、扩展、回调数据库
####抽象类的意义-乐视编程
为其子类提供一个公共的类型 封装子类中得重复内容 定义抽象方法,子类虽然有不一样的实现 可是定义是一致的
####内部类的做用-乐视
内部类能够用多个实例,每一个实例都有本身的状态信息,而且与其余外围对象的信息相互独立。
在单个外围类中,可让多个内部类以不一样的方式实现同一个接口,或者继承同一个类。
建立内部类对象的时刻并不依赖于外围类对象的建立。
内部类并无使人迷惑的“is-a”关系,他就是一个独立的实体。
内部类提供了更好的封装,除了该外围类,其余类都不能访问
####父类的静态方法可否被子类重写-猎豹
不能
子类继承父类后,用相同的静态方法和非静态方法,这时非静态方法覆盖父类中的方法(即方法重写),父类的该静态方法被隐藏(若是对象是父类则调用该隐藏的方法),另外子类可继承父类的静态与非静态方法,至于方法重载我以为它其中一要素就是在同一类中,不能说父类中的什么方法与子类里的什么方法是方法重载的体现
####java排序算法-美团
http://blog.csdn.net/qy1387/article/details/7752973
####列举java的集合和继承关系-百度-美团
####java虚拟机的特性-百度-乐视
Java语言的一个很是重要的特色就是与平台的无关性。而使用Java虚拟机是实现这一特色的关键。通常的高级语言若是要在不一样的平台上运行,至少须要编译成不一样的目标代码。而引入Java语言虚拟机后,Java语言在不一样平台上运行时不须要从新编译。Java语言使用模式Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就能够在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。
####哪些状况下的对象会被垃圾回收机制处理掉-美团-小米
Java 垃圾回收机制最基本的作法是分代回收。内存中的区域被划分红不一样的世代,对象根据其存活的时间被保存在对应世代的区域中。通常的实现是划分红3个世代:年轻、年老和永久。内存的分配是发生在年轻世代中的。当一个对象存活时间足够长的时候,它就会被复制到年老世代中。对于不一样的世代能够使用不一样的垃圾回收算法。进行世代划分的出发点是对应用中对象存活时间进行研究以后得出的统计规律。通常来讲,一个应用中的大部分对象的存活时间都很短。好比局部变量的存活时间就只在方法的执行过程当中。基于这一点,对于年轻世代的垃圾回收算法就能够颇有针对性。
####进程和线程的区别-猎豹-美团
简而言之,一个程序至少有一个进程,一个进程至少有一个线程。
线程的划分尺度小于进程,使得多线程程序的并发性高。
另外,进程在执行过程当中拥有独立的内存单元,而多个线程共享内存,从而极大地提升了程序的运行效率。
线程在执行过程当中与进程仍是有区别的。每一个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。可是线程不可以独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分能够同时执行。但操做系统并无将多个线程看作多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
进程是具备必定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程本身基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),可是它可与同属一个进程的其余的线程共享进程所拥有的所有资源.
一个线程能够建立和撤销另外一个线程;同一个进程中的多个线程之间能够并发执行.
进程和线程的主要差异在于它们是不一样的操做系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不一样执行路径。线程有本身的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,因此多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行而且又要共享某些变量的并发操做,只能用线程,不能用进程。若是有兴趣深刻的话,我建议大家看看《现代操做系统》或者《操做系统的设计与实现》。对就个问题说得比较清楚。
####java中==和equals和hashCode的区别-乐视
http://blog.csdn.net/tiantiandjava/article/details/46988461
####常见的排序算法时间复杂度-小米
####HashMap的实现原理-美团
HashMap概述: HashMap是基于哈希表的Map接口的非同步实现。此实现提供全部可选的映射操做,并容许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
HashMap的数据结构: 在java编程语言中,最基本的结构就是两种,一个是数组,另一个是模拟指针(引用),全部的数据结构均可以用这两个基本结构来构造的,HashMap也不例外。HashMap其实是一个“链表散列”的数据结构,即数组和链表的结合体。
从上图中能够看出,HashMap底层就是一个数组结构,数组中的每一项又是一个链表。当新建一个HashMap的时候,就会初始化一个数组。
####状态机
http://www.jdon.com/designpatterns/designpattern_State.htm
####int-char-long各占多少字节数
byte 位数 8 字节数 1
short 16 2
int 32 4
long 64 8
float 32 4
double 64 8
char 16 2
####int与integer的区别
http://www.cnblogs.com/shenliang123/archive/2011/10/27/2226903.html
####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 StringBuffer("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 要快。二者的方法基本相同
####java多态-乐视
Java多态性理解
Java中多态性的实现
什么是多态
面向对象的三大特性:封装、继承、多态。从必定角度来看,封装和继承几乎都是为多态而准备的。这是咱们最后一个概念,也是最重要的知识点。
多态的定义:指容许不一样类的对象对同一消息作出响应。即同一消息能够根据发送对象的不一样而采用多种不一样的行为方式。(发送消息就是函数调用)
实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实 际类型,根据其实际的类型调用其相应的方法。
多态的做用:消除类型之间的耦合关系。
现实中,关于多态的例子不胜枚举。比方说按下 F1 键这个动做,若是当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;若是当前在 Word 下弹出的就是 Word 帮助;在 Windows 下弹出的就是 Windows 帮助和支持。同一个事件发生在不一样的对象上会产生不一样的结果。 下面是多态存在的三个必要条件,要求你们作梦时都能背出来!
多态存在的三个必要条件 1、要有继承; 2、要有重写; 3、父类引用指向子类对象。
多态的好处:
1.可替换性(substitutability)。多态对已存在代码具备可替换性。例如,多态对圆Circle类工做,对其余任何圆形几何体,如圆环,也一样工做。
2.可扩充性(extensibility)。多态对代码具备可扩充性。增长新的子类不影响已存在类的多态性、继承性,以及其余特性的运行和操做。实际上新加子类更容易得到多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。
3.接口性(interface-ability)。多态是超类经过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。如图8.3 所示。图中超类Shape规定了两个实现多态的接口方法,computeArea()以及computeVolume()。子类,如Circle和Sphere为了实现多态,完善或者覆盖这两个接口方法。
4.灵活性(flexibility)。它在应用中体现了灵活多样的操做,提升了使用效率。
5.简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤为在处理大量对象的运算和操做时,这个特色尤其突出和重要。
Java中多态的实现方式:接口实现,继承父类进行方法重写,同一个类中进行方法重载。
####什么致使线程阻塞-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() 方法,由于它们的功能最强大,使用也最灵活,可是这也致使了它们的效率较低,较容易出错。实际使用中咱们应该灵活使用各类方法,以便更好地达到咱们的目的。
####抽象类接口区别-360
默认的方法实现 抽象类能够有默认的方法实现彻底是抽象的。接口根本不存在方法的实现
实现 子类使用extends关键字来继承抽象类。若是子类不是抽象类的话,它须要提供抽象类中全部声明的方法的实现。 子类使用关键字implements来实现接口。它须要提供接口中全部声明的方法的实现
构造器 抽象类能够有构造器 接口不能有构造器
与正常Java类的区别 除了你不能实例化抽象类以外,它和普通Java类没有任何区 接口是彻底不一样的类型
访问修饰符 抽象方法能够有public、protected和default这些修饰符 接口方法默认修饰符是public。你不能够使用其它修饰符。
main方法 抽象方法能够有main方法而且咱们能够运行它 接口没有main方法,所以咱们不能运行它。
多继承 抽象类在java语言中所表示的是一种继承关系,一个子类只能存在一个父类,可是能够存在多个接口。
速度 它比接口速度要快 接口是稍微有点慢的,由于它须要时间去寻找在类中实现的方法。
添加新方法 若是你往抽象类中添加新的方法,你能够给它提供默认的实现。所以你不须要改变你如今的代码。 若是你往接口中添加方法,那么你必须改变实现该接口的类。
####容器类之间的区别-乐视-美团
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
####内部类
http://www.cnblogs.com/chenssy/p/3388487.html
####hashmap和hashtable的区别-乐视-小米
http://www.233.com/ncre2/JAVA/jichu/20100717/084230917.html
####ArrayMap对比HashMap
http://lvable.com/?p=217
###Android
####如何导入外部数据库
把原数据库包括在项目源码的 res/raw
android系统下数据库应该存放在 /data/data/com..(package name)/ 目录下,因此咱们须要作的是把已有的数据库传入那个目录下.操做方法是用FileInputStream读取原数据库,再用FileOutputStream把读取到的东西写入到那个目录.
####本地广播和全局广播有什么差异
因广播数据在本应用范围内传播,不用担忧隐私数据泄露的问题。 不用担忧别的应用伪造广播,形成安全隐患。 相比在系统内发送全局广播,它更高效。
####intentService做用是什么,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同样,可是更加轻量级。它是使用代理类在客户端和实现端传递数据。
####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的生命周期影响。
####描述一次网络请求的流程-新浪
?
####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。
####低版本SDK实现高版本api-小米
本身实现或@TargetApi annotation
####Ubuntu编译安卓系统-百度
进入源码根目录
. build/envsetup.sh
lunch
full(编译所有)
userdebug(选择编译版本)
make -j8(开启8个线程编译)
####LaunchMode应用场景-百度-小米-乐视
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点。在上午5点58分,你启动了闹铃设置界面,并按 Home 键回桌面;在上午5点59分时,你在微信和朋友聊天;在6点时,闹铃响了,而且弹出了一个对话框形式的 Activity(名为 AlarmAlertActivity) 提示你到6点了(这个 Activity 就是以 SingleInstance 加载模式打开的),你按返回键,回到的是微信的聊天界面,这是由于 AlarmAlertActivity 所在的 Task 的栈只有他一个元素, 所以退出以后这个 Task 的栈空了。若是是以 SingleTask 打开 AlarmAlertActivity,那么当闹铃响了的时候,按返回键应该进入闹铃设置界面。
####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/
####View绘制流程-百度
http://www.codekk.com/blogs/detail/54cfab086c4761e5001b253f
####多线程-360
Activity.runOnUiThread(Runnable)
View.post(Runnable),View.postDelay(Runnable,long)
Handler
AsyncTask
####线程同步-百度
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;
}
}
####什么状况致使内存泄漏-美团
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的话,那状况就更严重了。
####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处理。
####什么状况致使oom-乐视-美团
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0920/3478.html
1)使用更加轻量的数据结构 2)Android里面使用Enum 3)Bitmap对象的内存占用 4)更大的图片 5)onDraw方法里面执行对象的建立 6)StringBuilder
####Service与Activity之间通讯的几种方式
经过Binder对象
经过broadcast(广播)的形式
####Android各个版本API的区别
http://blog.csdn.net/lijun952048910/article/details/7980562
####Android代码中实现WAP方式联网-360
http://blog.csdn.net/asce1885/article/details/7844159
####如何保证service在后台不被Kill
1、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。
2、提高service优先级
在AndroidManifest.xml文件中对于intent-filter能够经过android:priority = "1000"这个属性设置最高优先级,1000是最高值,若是数字越小则优先级越低,同时适用于广播。
3、提高service进程优先级
Android中的进程是托管的,当系统进程空间紧张的时候,会依照优先级自动进行进程的回收。Android将进程分为6个等级,它们按优先级顺序由高到低依次是:
前台进程( FOREGROUND_APP)
可视进程(VISIBLE_APP )
次要服务进程(SECONDARY_SERVER )
后台进程 (HIDDEN_APP)
内容供应节点(CONTENT_PROVIDER)
空进程(EMPTY_APP)
当service运行在低内存的环境时,将会kill掉一些存在的进程。所以进程的优先级将会很重要,能够使用startForeground 将service放到前台状态。这样在低内存时被kill的概率会低一些。
4、onDestroy方法里重启service
service +broadcast 方式,就是当service走ondestory的时候,发送一个自定义的广播,当收到广播的时候,从新启动service;
5、Application加上Persistent属性
6、监听系统广播判断Service状态
经过系统的一些广播,好比:手机重启、界面唤醒、应用状态改变等等监听并捕获到,而后判断咱们的Service是否还存活,别忘记加权限啊。
####Requestlayout,onlayout,onDraw,DrawChild区别与联系-猎豹
requestLayout()方法 :会致使调用measure()过程 和 layout()过程 。 将会根据标志位判断是否须要ondraw
onLayout()方法(若是该View是ViewGroup对象,须要实现该方法,对每一个子视图进行布局)
调用onDraw()方法绘制视图自己 (每一个View都须要重载该方法,ViewGroup不须要实现该方法)
drawChild()去从新回调每一个子视图的draw()方法
####invalidate()和postInvalidate()的区别及使用-百度
http://blog.csdn.net/mars2639/article/details/6650876
####Android动画框架实现原理
Animation框架定义了透明度,旋转,缩放和位移几种常见的动画,并且控制的是整个View,实现原理是每次绘制视图时View所在的ViewGroup中的drawChild函数获取该View的Animation的Transformation值,而后调用canvas.concat(transformToApply.getMatrix()),经过矩阵运算完成动画帧,若是动画没有完成,继续调用invalidate()函数,启动下次绘制来驱动动画,动画过程当中的帧之间间隙时间是绘制函数所消耗的时间,可能会致使动画消耗比较多的CPU资源,最重要的是,动画改变的只是显示,并不能相应事件。
####Android为每一个应用程序分配的内存大小是多少-美团
android程序内存通常限制在16M,也有的是24M
####View刷新机制-百度-美团
由ViewRoot对象的performTraversals()方法调用draw()方法发起绘制该View树,值得注意的是每次发起绘图时,并不会从新绘制每一个View树的视图,而只会从新绘制那些“须要重绘”的视图,View类内部变量包含了一个标志位DRAWN,当该视图须要重绘时,就会为该View添加该标志位。
调用流程 :
mView.draw()开始绘制,draw()方法实现的功能以下:
绘制该View的背景
为显示渐变框作一些准备操做(见5,大多数状况下,不须要改渐变框)
调用onDraw()方法绘制视图自己 (每一个View都须要重载该方法,ViewGroup不须要实现该方法)
调用dispatchDraw ()方法绘制子视图(若是该View类型不为ViewGroup,即不包含子视图,不须要重载该方法)值得说明的是,ViewGroup类已经为咱们重写了dispatchDraw ()的功能实现,应用程序通常不须要重写该方法,但能够重载父类函数实现具体的功能。
####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嵌套对性能的影响会更大一些。
####优化自定义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法则,直接设置它们的大小。
####ContentProvider-乐视
http://blog.csdn.net/coder_pig/article/details/47858489
####Fragment生命周期
####volley解析-美团-乐视
http://a.codekk.com/detail/Android/grumoon/Volley%20%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90
####Glide源码解析
http://www.lightskystreet.com/2015/10/12/glide_source_analysis/ http://frodoking.github.io/2015/10/10/android-glide/
####Android设计模式
http://blog.csdn.net/bboyfeiyu/article/details/44563871
####架构设计-搜狐
http://www.tianmaying.com/tutorial/AndroidMVC
####Android属性动画特性-乐视-小米
若是你的需求中只须要对View进行移动、缩放、旋转和淡入淡出操做,那么补间动画确实已经足够健全了。可是很显然,这些功能是不足以覆盖全部的场景的,一旦咱们的需求超出了移动、缩放、旋转和淡入淡出这四种对View的操做,那么补间动画就不能再帮咱们忙了,也就是说它在功能和可扩展方面都有至关大的局限性,那么下面咱们就来看看补间动画所不能胜任的场景。
注意上面我在介绍补间动画的时候都有使用“对View进行操做”这样的描述,没错,补间动画是只可以做用在View上的。也就是说,咱们能够对一个Button、TextView、甚至是LinearLayout、或者其它任何继承自View的组件进行动画操做,可是若是咱们想要对一个非View的对象进行动画操做,抱歉,补间动画就帮不上忙了。可能有的朋友会感到不能理解,我怎么会须要对一个非View的对象进行动画操做呢?这里我举一个简单的例子,好比说咱们有一个自定义的View,在这个View当中有一个Point对象用于管理坐标,而后在onDraw()方法当中就是根据这个Point对象的坐标值来进行绘制的。也就是说,若是咱们能够对Point对象进行动画操做,那么整个自定义View的动画效果就有了。显然,补间动画是不具有这个功能的,这是它的第一个缺陷。
而后补间动画还有一个缺陷,就是它只可以实现移动、缩放、旋转和淡入淡出这四种动画操做,那若是咱们但愿能够对View的背景色进行动态地改变呢?很遗憾,咱们只能靠本身去实现了。说白了,以前的补间动画机制就是使用硬编码的方式来完成的,功能限定死就是这些,基本上没有任何扩展性可言。
最后,补间动画还有一个致命的缺陷,就是它只是改变了View的显示效果而已,而不会真正去改变View的属性。什么意思呢?好比说,如今屏幕的左上角有一个按钮,而后咱们经过补间动画将它移动到了屏幕的右下角,如今你能够去尝试点击一下这个按钮,点击事件是绝对不会触发的,由于实际上这个按钮仍是停留在屏幕的左上角,只不过补间动画将这个按钮绘制到了屏幕的右下角而已。
专题
性能优化
Android性能优化典范 - 第1季
Render Performance Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染,若是每次渲染都成功,这样就可以达到流畅的画面所须要的60fps,为了可以实现60fps,这意味着程序的大多数操做都必须在16ms内完成。咱们能够经过一些工具来定位问题,好比能够使用HierarchyViewer来查找Activity中的布局是否过于复杂,也能够使用手机设置里面的开发者选项,打开Show GPU Overdraw等选项进行观察。你还能够使用TraceView来观察CPU的执行状况,更加快捷的找到性能瓶颈。
Understanding Overdraw Overdraw(过分绘制)描述的是屏幕上的某个像素在同一帧的时间内被绘制了屡次。在多层次的UI结构里面,若是不可见的UI也在作绘制的操做,这就会致使某些像素区域被绘制了屡次。这就浪费大量的CPU以及GPU资源。Overdraw有时候是由于你的UI布局存在大量重叠的部分,还有的时候是由于非必须的重叠背景。例如某个Activity有一个背景,而后里面的Layout又有本身的背景,同时子View又分别有本身的背景。仅仅是经过移除非必须的背景图片,这就可以减小大量的红色Overdraw区域,增长蓝色区域的占比。这一措施可以显著提高程序性能。
Understanding VSYNC Refresh Rate:表明了屏幕在一秒内刷新屏幕的次数,这取决于硬件的固定参数,例如60Hz。Frame Rate:表明了GPU在一秒内绘制操做的帧数,例如30fps,60fps。一般来讲,帧率超过刷新频率只是一种理想的情况,在超过60fps的状况下,GPU所产生的帧数据会由于等待VSYNC的刷新信息而被Hold住,这样可以保持每次刷新都有实际的新的数据能够显示。可是咱们遇到更多的状况是帧率小于刷新频率。
Tool:Profile GPU Rendering 性能问题如此的麻烦,幸亏咱们能够有工具来进行调试。打开手机里面的开发者选项,选择Profile GPU Rendering,选中On screen as bars的选项。
Why 60fps? 咱们一般都会提到60fps与16ms,但是知道为什么会是以程序是否达到60fps来做为App性能的衡量标准吗?这是由于人眼与大脑之间的协做没法感知超过60fps的画面更新。开发app的性能目标就是保持60fps,这意味着每一帧你只有16ms=1000/60的时间来处理全部的任务。
Android, UI and the GPU 在Android里面那些由主题所提供的资源,例如Bitmaps,Drawables都是一块儿打包到统一的Texture纹理当中,而后再传递到GPU里面,这意味着每次你须要使用这些资源的时候,都是直接从纹理里面进行获取渲染的。固然随着UI组件的愈来愈丰富,有了更多演变的形态。例如显示图片的时候,须要先通过CPU的计算加载到内存中,而后传递给GPU进行渲染。文字的显示更加复杂,须要先通过CPU换算成纹理,而后再交给GPU进行渲染,回到CPU绘制单个字符的时候,再从新引用通过GPU渲染的内容。动画则是一个更加复杂的操做流程。为了可以使得App流畅,咱们须要在每一帧16ms之内处理完全部的CPU与GPU计算,绘制,渲染等等操做。
Invalidations, Layouts, and Performance 任什么时候候View中的绘制内容发生变化时,都会从新执行建立DisplayList,渲染DisplayList,更新到屏幕上等一系列操做。这个流程的表现性能取决于你的View的复杂程度,View的状态变化以及渲染管道的执行性能。举个例子,假设某个Button的大小须要增大到目前的两倍,在增大Button大小以前,须要经过父View从新计算并摆放其余子View的位置。修改View的大小会触发整个HierarcyView的从新计算大小的操做。若是是修改View的位置则会触发HierarchView从新计算其余View的位置。若是布局很复杂,这就会很容易致使严重的性能问题。咱们须要尽可能减小Overdraw。
Overdraw, Cliprect, QuickReject 咱们能够经过canvas.clipRect()来帮助系统识别那些可见的区域。这个方法能够指定一块矩形区域,只有在这个区域内才会被绘制,其余的区域会被忽视。这个API能够很好的帮助那些有多组重叠组件的自定义View来控制显示的区域。同时clipRect方法还能够帮助节约CPU与GPU资源,在clipRect区域以外的绘制指令都不会被执行,那些部份内容在矩形区域内的组件,仍然会获得绘制。
Memory Churn and performance 执行GC操做的时候,全部线程的任何操做都会须要暂停,等待GC操做完成以后,其余操做才可以继续运行。Memory Churn内存抖动,内存抖动是由于大量的对象被建立又在短期内立刻被释放。瞬间产生大量的对象会严重占用Young Generation的内存区域,当达到阀值,剩余空间不够的时候,也会触发GC。即便每次分配的对象占用了不多的内存,可是他们叠加在一块儿会增长Heap的压力,从而触发更多其余类型的GC。这个操做有可能会影响到帧率,并使得用户感知到性能问题。
Garbage Collection in Android 原始JVM中的GC机制在Android中获得了很大程度上的优化。Android里面是一个三级Generation的内存模型,最近分配的对象会存放在Young Generation区域,当这个对象在这个区域停留的时间达到必定程度,它会被移动到Old Generation,最后到Permanent Generation区域。若是不当心在最小的for循环单元里面执行了建立对象的操做,这将很容易引发GC并致使性能问题。经过Memory Monitor咱们能够查看到内存的占用状况,每一次瞬间的内存下降都是由于此时发生了GC操做,若是在短期内发生大量的内存上涨与下降的事件,这说明颇有可能这里有性能问题。咱们还能够经过Heap and Allocation Tracker工具来查看此时内存中分配的到底有哪些对象。
Performance Cost of Memory Leaks 内存泄漏指的是那些程序再也不使用的对象没法被GC识别,这样就致使这个对象一直留在内存当中,占用了宝贵的内存空间。显然,这还使得每级Generation的内存区域可用空间变小,GC就会更容易被触发,从而引发性能问题。
Memory Performance 一般来讲,Android对GC作了大量的优化操做,虽然执行GC操做的时候会暂停其余任务,但是大多数状况下,GC操做仍是相对很安静而且高效的。可是若是咱们对内存的使用不恰当,致使GC频繁执行,这样就会引发不小的性能问题。
Tool - Memory Monitor Android Studio中的Memory Monitor能够很好的帮助咱们查看程序的内存使用状况。
Battery Performance 咱们应该尽可能减小唤醒屏幕的次数与持续的时间,使用WakeLock来处理唤醒的问题,可以正确执行唤醒操做并根据设定及时关闭操做进入睡眠状态。某些非必须立刻执行的操做,例如上传歌曲,图片处理等,能够等到设备处于充电状态或者电量充足的时候才进行。触发网络请求的操做,每次都会保持无线信号持续一段时间,咱们能够把零散的网络请求打包进行一次操做,避免过多的无线信号引发的电量消耗。关于网络请求引发无线信号的电量消耗
Understanding Battery Drain on Android 使用WakeLock或者JobScheduler唤醒设备处理定时的任务以后,必定要及时让设备回到初始状态。每次唤醒无线信号进行数据传递,都会消耗不少电量,它比WiFi等操做更加的耗电
Battery Drain and WakeLocks 这正是JobScheduler API所作的事情。它会根据当前的状况与任务,组合出理想的唤醒时间,例如等到正在充电或者链接到WiFi的时候,或者集中任务一块儿执行。咱们能够经过这个API实现不少免费的调度算法。
Android性能优化典范 - 第2季
Battery Drain and Networking 咱们能够有针对性的把请求行为捆绑起来,延迟到某个时刻统一发起请求。这部分主要会涉及到Prefetch(预取)与Compressed(压缩)这两个技术。对于Prefetch的使用,咱们须要预先判断用户在这次操做以后,后续零散的请求是否颇有可能会立刻被触发,能够把后面5分钟有可能会使用到的零散请求都一次集中执行完毕。对于Compressed的使用,在上传与下载数据以前,使用CPU对数据进行压缩与解压,能够很大程度上减小网络传输的时间。
Wear & Sensors 首先咱们须要尽可能使用Android平台提供的既有运动数据,而不是本身去实现监听采集数据,由于大多数Android Watch自身记录Sensor数据的行为是有通过作电量优化的。其次在Activity不须要监听某些Sensor数据的时候须要尽快释放监听注册。还有咱们须要尽可能控制更新的频率,仅仅在须要刷新显示数据的时候才触发获取最新数据的操做。另外咱们能够针对Sensor的数据作批量处理,待数据累积必定次数或者某个程度的时候才更新到UI上。最后当Watch与Phone链接起来的时候,能够把某些复杂操做的事情交给Phone来执行,Watch只须要等待返回的结果。
Smooth Android Wear Animation 在Android里面一个相对操做比较繁重的事情是对Bitmap进行旋转,缩放,裁剪等等。例如在一个圆形的钟表图上,咱们把时钟的指针抠出来当作单独的图片进行旋转会比旋转一张完整的圆形图的所造成的帧率要高56%。
Android Wear Data Batching 仅仅在真正须要刷新界面的时候才发出请求,尽可能把计算复杂操做的任务交给Phone来处理,Phone仅仅在数据发生变化的时候才通知到Wear,把零碎的数据请求捆绑一块儿再进行操做。
Object Pools 使用对象池技术有不少好处,它能够避免内存抖动,提高性能,可是在使用的时候有一些内容是须要特别注意的。一般状况下,初始化的对象池里面都是空白的,当使用某个对象的时候先去对象池查询是否存在,若是不存在则建立这个对象而后加入对象池,可是咱们也能够在程序刚启动的时候就事先为对象池填充一些即将要使用到的数据,这样能够在须要使用到这些对象的时候提供更快的首次加载速度,这种行为就叫作预分配。使用对象池也有很差的一面,程序员须要手动管理这些对象的分配与释放,因此咱们须要慎重地使用这项技术,避免发生对象的内存泄漏。为了确保全部的对象可以正确被释放,咱们须要保证加入对象池的对象和其余外部对象没有互相引用的关系。
To Index or Iterate? for index的方式有更好的效率,可是由于不一样平台编译器优化各有差别,咱们最好仍是针对实际的方法作一下简单的测量比较好,拿到数据以后,再选择效率最高的那个方式。
The Magic of LRU Cache 使用LRU Cache可以显著提高应用的性能,但是也须要注意LRU Cache中被淘汰对象的回收,否者会引发严重的内存泄露。
Using LINT for Performance Tips Lint已经集成到Android Studio中了,咱们能够手动去触发这个工具,点击工具栏的Analysis -> Inspect Code,触发以后,Lint会开始工做,并把结果输出到底部的工具栏,咱们能够逐个查看缘由并根据指示作相应的优化修改。
Hidden Cost of Transparency 一般来讲,对于不透明的View,显示它只须要渲染一次便可,但是若是这个View设置了alpha值,会至少须要渲染两次。
Avoiding Allocations in onDraw() 首先onDraw()方法是执行在UI线程的,在UI线程尽可能避免作任何可能影响到性能的操做。虽然分配内存的操做并不须要花费太多系统资源,可是这并不意味着是免费无代价的。设备有必定的刷新频率,致使View的onDraw方法会被频繁的调用,若是onDraw方法效率低下,在频繁刷新累积的效应下,效率低的问题会被扩大,而后会对性能有严重的影响。
Tool: Strict Mode Android提供了一个叫作Strict Mode的工具,咱们能够经过手机设置里面的开发者选项,打开Strict Mode选项,若是程序存在潜在的隐患,屏幕就会闪现红色。咱们也能够经过StrictMode API在代码层面作细化的跟踪,能够设置StrictMode监听那些潜在问题,出现问题时如何提醒开发者,能够对屏幕闪红色,也能够输出错误日志。
Custom Views and Performance Useless calls to onDraw():咱们知道调用View.invalidate()会触发View的重绘,有两个原则须要遵照,第1个是仅仅在View的内容发生改变的时候才去触发invalidate方法,第2个是尽可能使用ClipRect等方法来提升绘制的性能。Useless pixels:减小绘制时没必要要的绘制元素,对于那些不可见的元素,咱们须要尽可能避免重绘。Wasted CPU cycles:对于不在屏幕上的元素,能够使用Canvas.quickReject把他们给剔除,避免浪费CPU资源。另外尽可能使用GPU来进行UI的渲染,这样可以极大的提升程序的总体表现性能。
Batching Background Work Until Later 1.AlarmManager 使用AlarmManager设置定时任务,能够选择精确的间隔时间,也能够选择非精确时间做为参数。除非程序有很强烈的须要使用精确的定时唤醒,否者必定要避免使用他,咱们应该尽可能使用非精确的方式。2.SyncAdapter 咱们能够使用SyncAdapter为应用添加设置帐户,这样在手机设置的帐户列表里面能够找到咱们的应用。这种方式功能更多,可是实现起来比较复杂。咱们能够从这里看到官方的培训课程:http://developer.android.com/training/sync-adapters/index.html 3.JobSchedulor 这是最简单高效的方法,咱们能够设置任务延迟的间隔,执行条件,还能够增长重试机制。
Smaller Pixel Formats Android的Heap空间是不会自动作兼容压缩的,意思就是若是Heap空间中的图片被收回以后,这块区域并不会和其余已经回收过的区域作从新排序合并处理,那么当一个更大的图片须要放到heap以前,极可能找不到那么大的连续空闲区域,那么就会触发GC,使得heap腾出一块足以放下这张图片的空闲区域,若是没法腾出,就会发生OOM。
Smaller PNG Files 尽可能减小PNG图片的大小是Android里面很重要的一条规范。相比起JPEG,PNG可以提供更加清晰无损的图片,可是PNG格式的图片会更大,占用更多的磁盘空间。究竟是使用PNG仍是JPEG,须要设计师仔细衡量,对于那些使用JPEG就能够达到视觉效果的,能够考虑采用JPEG便可。
Pre-scaling Bitmaps 对bitmap作缩放,这也是Android里面最遇到的问题。对bitmap作缩放的意义很明显,提示显示性能,避免分配没必要要的内存。Android提供了现成的bitmap缩放的API,叫作createScaledBitmap()
Re-using Bitmaps 使用inBitmap属性能够告知Bitmap解码器去尝试使用已经存在的内存区域,新解码的bitmap会尝试去使用以前那张bitmap在heap中所占据的pixel data内存区域,而不是去问内存从新申请一块区域来存放bitmap。利用这种特性,即便是上千张的图片,也只会仅仅只须要占用屏幕所可以显示的图片数量的内存大小。
The Performance Lifecycle Gather:收集数据,Insight:分析数据,Action:解决问题
Android性能优化典范 - 第3季
Fun with ArrayMaps 为了解决HashMap更占内存的弊端,Android提供了内存效率更高的ArrayMap。它内部使用两个数组进行工做,其中一个数组记录key hash事后的顺序列表,另一个数组按key的顺序记录Key-Value值
Beware Autoboxing 有时候性能问题也多是由于那些不起眼的小细节引发的,例如在代码中不经意的“自动装箱”。咱们知道基础数据类型的大小:boolean(8 bits), int(32 bits), float(32 bits),long(64 bits),为了可以让这些基础数据类型在大多数Java容器中运做,会须要作一个autoboxing的操做,转换成Boolean,Integer,Float等对象
SparseArray Family Ties 为了不HashMap的autoboxing行为,Android系统提供了SparseBoolMap,SparseIntMap,SparseLongMap,LongSparseMap等容器。
The price of ENUMs Android官方强烈建议不要在Android程序里面使用到enum。
Trimming and Sharing Memory Android系统提供了一些回调来通知应用的内存使用状况,一般来讲,当全部的background应用都被kill掉的时候,forground应用会收到onLowMemory()的回调。在这种状况下,须要尽快释放当前应用的非必须内存资源,从而确保系统可以稳定继续运行。Android系统还提供了onTrimMemory()的回调,当系统内存达到某些条件的时候,全部正在运行的应用都会收到这个回调
DO NOT LEAK VIEWS 避免使用异步回调,避免使用Static对象,避免把View添加到没有清除机制的容器里面
Location & Battery Drain 其中存在的一个优化点是,咱们能够经过判断返回的位置信息是否相同,从而决定设置下次的更新间隔是否增长一倍,经过这种方式能够减小电量的消耗
Double Layout Taxation 布局中的任何一个View一旦发生一些属性变化,均可能引发很大的连锁反应。例如某个button的大小忽然增长一倍,有可能会致使兄弟视图的位置变化,也有可能致使父视图的大小发生改变。当大量的layout()操做被频繁调用执行的时候,就极可能引发丢帧的现象。
Network Performance 101 减小移动网络被激活的时间与次数,压缩传输数据
Effective Network Batching 发起网络请求与接收返回数据都是比较耗电的,在网络硬件模块被激活以后,会继续保持几十秒的电量消耗,直到没有新的网络操做行为以后,才会进入休眠状态。前面一个段落介绍了使用Batching的技术来捆绑网络请求,从而达到减小网络请求的频率。那么如何实现Batching技术呢?一般来讲,咱们能够会把那些发出的网络请求,先暂存到一个PendingQueue里面,等到条件合适的时候再触发Queue里面的网络请求。
Optimizing Network Request Frequencies 前面的段落已经提到了应该减小网络请求的频率,这是为了减小电量的消耗。咱们能够使用Batching,Prefetching的技术来避免频繁的网络请求。Google提供了GCMNetworkManager来帮助开发者实现那些功能,经过提供的API,咱们能够选择在接入WiFi,开始充电,等待移动网络被激活等条件下再次激活网络请求。
Effective Prefetching 相似上面的状况会频繁触发网络请求,可是若是咱们可以预先请求后续可能会使用到网络资源,避免频繁的触发网络请求,这样就可以显著的减小电量的消耗。但是预先获取多少数据量是很值得考量的,由于若是预取数据量偏少,就起不到减小频繁请求的做用,但是若是预取数据过多,就会形成资源的浪费。
Android性能优化典范 - 第4季
Cachematters for networking 想要使得Android系统上的网络访问操做更加的高效就必须作好网络数据的缓存。这是提升网络访问性能最基础的步骤之一。从手机的缓存中直接读取数据确定比从网络上获取数据要更加的便捷高效,特别是对于那些会被频繁访问到的数据,须要把这些数据缓存到设备上,以便更加快速的进行访问。
Optimizing Network Request Frequencies 首先咱们要对网络行为进行分类,区分须要当即更新数据的行为和其余能够进行延迟的更新行为,为不一样的场景进行差别化处理。其次要避免客户端对服务器的轮询操做,这样会浪费不少的电量与带宽流量。解决这个问题,咱们能够使用Google Cloud Message来对更新的数据进行推送。而后在某些必须作同步的场景下,须要避免使用固定的间隔频率来进行更新操做,咱们应该在返回的数据无更新的时候,使用双倍的间隔时间来进行下一次同步。最后更进一步,咱们还能够经过判断当前设备的状态来决定同步的频率,例如判断设备处于休眠,运动等不一样的状态设计各自不一样时间间隔的同步频率。
Effective Prefetching 到底预取多少才比较合适呢?一个比较普适的规则是,在3G网络下能够预取1-5Mb的数据量,或者是按照提早预期后续1-2分钟的数据做为基线标准。在实际的操做当中,咱们还须要考虑当前的网络速度来决定预取的数据量,例如在一样的时间下,4G网络能够获取到12张图片的数据,而2G网络则只能拿到3张图片的数据。因此,咱们还须要把当前的网络环境状况添加到设计预取数据量的策略当中去。判断当前设备的状态与网络状况,能够使用前面提到过的GCMNetworkManager。
Adapting to Latency 一个典型的网络操做行为,一般包含如下几个步骤:首先手机端发起网络请求,到达网络服务运营商的基站,再转移到服务提供者的服务器上,通过解码以后,接着访问本地的存储数据库,获取到数据以后,进行编码,最后按照原来传递的路径逐层返回。常来讲,咱们能够把网络请求延迟划分为三档:例如把网络延迟小于60ms的划分为GOOD,大于220ms的划分为BAD,介于二者之间的划分为OK(这里的60ms,220ms会须要根据不一样的场景提早进行预算推测)。
Minimizing Asset Payload 为了可以减少网络传输的数据量,咱们须要对传输的数据作压缩的处理,这样可以提升网络操做的性能。首先须要作的是减小图片的大小,其次须要作的是减小序列化数据的大小。
Service Performance Patterns Service是Android程序里面最经常使用的基础组件之一,可是使用Service很容易引发电量的过分消耗以及系统资源的未及时释放。避免错误的使用Service,例如咱们不该该使用Service来监听某些事件的变化,不该该搞一个Service在后台对服务器不断的进行轮询(应该使用Google Cloud Messaging)。若是已经事先知道Service里面的任务应该执行在后台线程(非默认的主线程)的时候,咱们应该使用IntentService或者结合HanderThread,AsycnTask Loader实现的Service。
Removing unused code Android为咱们提供了Proguard的工具来帮助应用程序对代码进行瘦身,优化,混淆的处理。它会帮助移除那些没有使用到的代码,还能够对类名,方法名进行混淆处理以免程序被反编译。
Removing unused resources 所幸的是,咱们能够使用Gradle来帮助咱们分析代码,分析引用的资源,对于那些没有被引用到的资源,会在编译阶段被排除在APK安装包以外,要实现这个功能,对咱们来讲仅仅只须要在build.gradle文件中配置shrinkResource为true就行了
Perf Theory: Caching 当咱们讨论性能优化的时候,缓存是最多见最有效的策略之一。不管是为了提升CPU的计算速度仍是提升数据的访问速度,在绝大多数的场景下,咱们都会使用到缓存。
Perf Theory: Approximation(近似法) 例如使用一张比较接近实际大小的图片来替代原图,换取更快的加载速度。因此对于那些对计算结果要求不须要十分精确的场景,咱们能够使用近似法则来提升程序的性能。
Perf Theory: Culling(遴选,挑选) 一个提升性能的方法是逐步对数据进行过滤筛选,减少搜索的数据集,以此提升程序的执行性能。例如咱们须要搜索到居住在某个地方,年龄是多少,符合某些特定条件的候选人,就能够经过逐层过滤筛选的方式来提升后续搜索的执行效率。
Perf Theory: Threading 使用多线程并发处理任务,从某种程度上能够快速提升程序的执行性能。对于Android程序来讲,主线程一般也成为UI线程,须要处理UI的渲染,响应用户的操做等等。
Perf Theory: Batching 网络请求的批量执行是另一个比较适合说明batching使用场景的例子,由于每次发起网络请求都相对来讲比较耗时耗电,若是可以作到批量一块儿执行,能够大大的减小电量的消耗。
Serialization performance 数据序列化的行为可能发生在数据传递过程当中的任何阶段,例如网络传输,不一样进程间数据传递,不一样类之间的参数传递,把数据存储到磁盘上等等。一般状况下,咱们会把那些须要序列化的类实现Serializable接口(以下图所示),可是这种传统的作法效率不高,实施的过程会消耗更多的内存。可是咱们若是使用GSON库来处理这个序列化的问题,不只仅执行速度更快,内存的使用效率也更高。Android的XML布局文件会在编译的阶段被转换成更加复杂的格式,具有更加高效的执行性能与更高的内存使用效率。
Smaller Serialized Data 数据呈现的顺序以及结构会对序列化以后的空间产生不小的影响。
Caching UI data 缓存UI界面上的数据,能够采用方案有存储到文件系统,Preference,SQLite等等,作了缓存以后,这样就能够在请求数据返回结果以前,呈现给用户旧的数据,而不是使用正在加载的方式让用户什么数据都看不到,固然在请求网络最新数据的过程当中,须要有正在刷新的提示。至于到底选择哪一个方案来对数据进行缓存,就须要根据具体状况来作选择了。
CPU Frequency Scaling 调节CPU的频率会执行的性能产生较大的影响,为了最大化的延长设备的续航时间,系统会动态调整CPU的频率,频率越高执行代码的速度天然就越快。咱们能够使用Systrace工具来导出CPU的执行状况,以便帮助定位性能问题。
Android性能优化典范 - 第5季
Threading Performance AsyncTask: 为UI线程与工做线程之间进行快速的切换提供一种简单便捷的机制。适用于当下当即须要启动,可是异步执行的生命周期短暂的使用场景。HandlerThread: 为某些回调方法或者等待某些任务的执行设置一个专属的线程,并提供线程任务的调度机制。ThreadPool: 把任务分解成不一样的单元,分发到各个不一样的线程上,进行同时并发处理。IntentService: 适合于执行由UI触发的后台Service任务,并能够把后台任务执行的状况经过必定的机制反馈给UI。
Understanding Android Threading 一般来讲,一个线程须要经历三个生命阶段:开始,执行,结束。线程会在任务执行完毕以后结束,那么为了确保线程的存活,咱们会在执行阶段给线程赋予不一样的任务,而后在里面添加退出的条件从而确保任务可以执行完毕后退出。
Memory & Threading 不要在任何非UI线程里面去持有UI对象的引用。系统为了确保全部的UI对象都只会被UI线程所进行建立,更新,销毁的操做,特意设计了对应的工做机制(当Activity被销毁的时候,由该Activity所触发的非UI线程都将没法对UI对象进行操做,否者就会抛出程序执行异常的错误)来防止UI对象被错误的使用。
Good AsyncTask Hunting AsyncTask虽然提供了一种简单便捷的异步机制,可是咱们仍是颇有必要特别关注到他的缺点,避免出现由于使用错误而致使的严重系统性能问题。
Getting a HandlerThread HandlerThread比较合适处理那些在工做线程执行,须要花费时间偏长的任务。咱们只须要把任务发送给HandlerThread,而后就只须要等待任务执行结束的时候通知返回到主线程就行了。另外很重要的一点是,一旦咱们使用了HandlerThread,须要特别注意给HandlerThread设置不一样的线程优先级,CPU会根据设置的不一样线程优先级对全部的线程进行调度优化。
Swimming in Threadpools 线程池适合用在把任务进行分解,并发进行执行的场景。一般来讲,系统里面会针对不一样的任务设置一个单独的守护线程用来专门处理这项任务。
The Zen of IntentService 默认的Service是执行在主线程的,但是一般状况下,这很容易影响到程序的绘制性能(抢占了主线程的资源)。除了前面介绍过的AsyncTask与HandlerThread,咱们还能够选择使用IntentService来实现异步操做。IntentService继承自普通Service同时又在内部建立了一个HandlerThread,在onHandlerIntent()的回调里面处理扔到IntentService的任务。因此IntentService就不只仅具有了异步线程的特性,还同时保留了Service不受主页面生命周期影响的特色。
Threading and Loaders 当启动工做线程的Activity被销毁的时候,咱们应该作点什么呢?为了方便的控制工做线程的启动与结束,Android为咱们引入了Loader来解决这个问题。咱们知道Activity有可能由于用户的主动切换而频繁的被建立与销毁,也有多是由于相似屏幕发生旋转等被动缘由而销毁再重建。在Activity不停的建立与销毁的过程中,颇有可能由于工做线程持有Activity的View而致使内存泄漏(由于工做线程极可能持有View的强引用,另外工做线程的生命周期还没法保证和Activity的生命周期一致,这样就容易发生内存泄漏了)。除了可能引发内存泄漏以外,在Activity被销毁以后,工做线程还继续更新视图是没有意义的,由于此时视图已经不在界面上显示了。
The Importance of Thread Priority 在Android系统里面,咱们能够经过android.os.Process.setThreadPriority(int)设置线程的优先级,参数范围从-20到24,数值越小优先级越高。Android系统还为咱们提供了如下的一些预设值,咱们能够经过给不一样的工做线程设置不一样数值的优先级来达到更细粒度的控制。
Profile GPU Rendering : M Update 从Android M系统开始,系统更新了GPU Profiling的工具来帮助咱们定位UI的渲染性能问题。早期的CPU Profiling工具只能粗略的显示出Process,Execute,Update三大步骤的时间耗费状况。
官方性能优化系列教程
架构分析
MVVM
MVP
阿里面试题
进程间通讯方式
经过Intent在Activity、Service或BroadcastReceiver间进行进程间通讯,可经过Intent传递数据
AIDL方式
Messenger方式
利用ContentProvider
Socket方式
基于文件共享的方式
什么是协程
咱们知道多个线程相对独立,有本身的上下文,切换受系统控制;而协程也相对独立,有本身的上下文,可是其切换由本身控制,由当前协程切换到其余协程由当前协程来控制。 ?
内存泄露是怎么回事
由忘记释放分配的内存致使的
程序计数器,引到了逻辑地址(虚地址)和物理地址及其映射关系
虚拟机中的程序计数器是Java运行时数据区中的一小块内存区域,可是它的功能和一般的程序计数器是相似的,它指向虚拟机正在执行字节码指令的地址。具体点儿说,当虚拟机执行的方法不是native的时,程序计数器指向虚拟机正在执行字节码指令的地址;当虚拟机执行的方法是native的时,程序计数器中的值是未定义的。另外,程序计数器是线程私有的,也就是说,每个线程都拥有仅属于本身的程序计数器。
数组和链表的区别
数组是将元素在内存中连续存放,因为每一个元素占用内存相同,能够经过下标迅速访问数组中任何元素。可是若是要在数组中增长一个元素,须要移动大量元素,在内存中空出一个元素的空间,而后将要增长的元素放在其中。一样的道理,若是想删除一个元素,一样须要移动大量元素去填掉被移动的元素。若是应用须要快速访问数据,不多或不插入和删除元素,就应该用数组。
链表刚好相反,链表中的元素在内存中不是顺序存储的,而是经过存在元素中的指针联系到一块儿。好比:上一个元素有个指针指到下一个元素,以此类推,直到最后一个元素。若是要访问链表中一个元素,须要从第一个元素开始,一直找到须要的元素位置。可是增长和删除一个元素对于链表数据结构就很是简单了,只要修改元素中的指针就能够了。若是应用须要常常插入和删除元素你就须要用链表数据结构了。
二叉树的深度优先遍历和广度优先遍历的具体实现
http://www.i3geek.com/archives/794
堆的结构
年轻代(Young Generation)、年老代(Old Generation)和持久代(Permanent Generation)。其中持久代主要存放的是Java类的类信息,与垃圾收集要收集的Java对象关系 不大。年轻代和年老代的划分是对垃 圾收集影响比较大的。
bitmap对象的理解
http://blog.csdn.net/angel1hao/article/details/51890938
什么是深拷贝和浅拷
浅拷贝:使用一个已知实例对新建立实例的成员变量逐个赋值,这个方式被称为浅拷贝。 深拷贝:当一个类的拷贝构造方法,不只要复制对象的全部非引用成员变量值,还要为引用类型的成员变量建立新的实例,而且初始化为形式参数实例值。这个方式称为深拷贝
对象锁和类锁是否会互相影响
对象锁:Java的全部对象都含有1个互斥锁,这个锁由JVM自动获取和释放。线程进入synchronized方法的时候获取该对象的锁,固然若是已经有线程获取了这个对象的锁,那么当前线程会等待;synchronized方法正常返回或者抛异常而终止,JVM会自动释放对象锁。这里也体现了用synchronized来加锁的1个好处,方法抛异常的时候,锁仍然能够由JVM来自动释放。 类锁: 对象锁是用来控制实例方法之间的同步,类锁是用来控制静态方法(或静态变量互斥体)之间的同步。其实类锁只是一个概念上的东西,并非真实存在的,它只是用来帮助咱们理解锁定实例方法和静态方法的区别的。咱们都知道,java类可能会有不少个对象,可是只有1个Class对象,也就是说类的不一样实例之间共享该类的Class对象。Class对象其实也仅仅是1个java对象,只不过有点特殊而已。因为每一个java对象都有1个互斥锁,而类的静态方法是须要Class对象。因此所谓的类锁,不过是Class对象的锁而已。获取类的Class对象有好几种,最简单的就是MyClass.class的方式。 类锁和对象锁不是同1个东西,一个是类的Class对象的锁,一个是类的实例的锁。也就是说:1个线程访问静态synchronized的时候,容许另外一个线程访问对象的实例synchronized方法。反过来也是成立的,由于他们须要的锁是不一样的。
looper架构
http://wangkuiwu.github.io/2014/08/26/MessageQueue/
自定义控件原理
http://www.jianshu.com/p/988326f9c8a3
binder工做原理
Binder是客户端和服务端进行通信的媒介
ActivityThread,Ams,Wms的工做原理
ActivityThread: 运行在应用进程的主线程上,响应 ActivityManangerService 启动、暂停Activity,广播接收等消息。 ams:统一调度各应用程序的Activity、内存管理、进程管理
Java中final,finally,finalize的区别
final 用于声明属性,方法和类, 分别表示属性不可变, 方法不可覆盖, 类不可继承.?
finally 是异常处理语句结构的一部分,表示老是执行.?
finalize 是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,能够覆盖此方法提供垃圾收集时的其余资源回收,例如关闭文件等. JVM不保证此方法总被调用.
一个文件中有100万个整数,由空格分开,在程序中判断用户输入的整数是否在此文件中。说出最优的方法
两个进程同时要求写或者读,能不能实现?如何防止进程的同步?
volatile 的意义?
防止CPU指令重排序
单例
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;
}
}
Given a string, determine if it is a palindrome(回文,若是不清楚,按字面意思脑补下), considering only alphanumeric characters and ignoring cases.
For example, "A man, a plan, a canal: Panama" is a palindrome. "race a car" is not a palindrome.
Note: Have you consider that the string might be empty? This is a good question to ask during an interview. For the purpose of this problem, we define empty string as valid palindrome.
public boolean isPalindrome(String palindrome){
char[] palindromes = palidrome.toCharArray();
if(palindromes.lengh == 0){
return true
}
Arraylist<Char> temp = new Arraylist();
for(int i=0;i<palindromes.length;i++){
if((palindromes[i]>'a' && palindromes[i]<'z')||palindromes[i]>'A' && palindromes[i]<'Z')){
temp.add(palindromes[i].toLowerCase());
}
}
for(int i=0;i<temp.size()/2;i++){
if(temp.get(i) != temp.get(temp.size()-i)){
//
return false;
}
}
return true;
}
烧一根不均匀的绳,从头烧到尾总共须要1个小时。如今有若干条材质相同的绳子,问如何用烧绳的方法来计时一个小时十五分钟呢
用两根绳子,一个绳子两头烧,一个一头烧。
腾讯
2000万个整数,找出第五十大的数字?
冒泡、选择、建堆
从网络加载一个10M的图片,说下注意事项
图片缓存、异常恢复、质量压缩
自定义View注意事项
渲染帧率、内存
项目中经常使用的设计模式
单例、观察者、适配器、建造者。。
JVM的理解
http://www.infoq.com/cn/articles/java-memory-model-1