|
1. 内容介绍................................................................................................................................................................................................................... 8java
2. JavaSE基础(★★)............................................................................................................................................................................................ 8linux
1、 Java面向对象思想................................................................................................................................................................................ 8android
一、面向对象都有哪些特性以及你对这些特性的理解............................................................................................................... 8面试
2、 Java中的多态......................................................................................................................................................................................... 9算法
一、 Java中实现多态的机制是什么?............................................................................................................................................ 9sql
3、 Java的异常处理.................................................................................................................................................................................. 10数据库
一、 Java中异常分为哪些种类........................................................................................................................................................ 10apache
二、 调用下面的方法,获得的返回值是什么............................................................................................................................. 10编程
4、 Java的数据类型.................................................................................................................................................................................. 11
一、 Java的基本数据类型都有哪些各占几个字节.................................................................................................................. 11
二、 String是基本数据类型吗?能够被继承吗?................................................................................................................... 11
5、 Java的IO.............................................................................................................................................................................................. 12
一、 Java中有几种类型的流............................................................................................................................................................ 12
二、 字节流如何转为字符流.............................................................................................................................................................. 12
三、 如何将一个java对象序列化到文件里................................................................................................................................ 12
6、 Java的集合........................................................................................................................................................................................... 12
一、HashMap排序题,上机题。(本人主要靠这道题入职的第一家公司).................................................................... 12
二、 集合的安全性问题....................................................................................................................................................................... 14
7、 Java的多线程...................................................................................................................................................................................... 15
一、 多线程的两种建立方式.............................................................................................................................................................. 15
二、 在java中wait和sleep方法的不一样?.............................................................................................................................. 15
三、 synchronized和volatile关键字的做用.......................................................................................................................... 15
四、 分析代码解释缘由....................................................................................................................................................................... 16
五、 什么是线程池,如何使用?.................................................................................................................................................... 18
3. JavaSE高级(★★).......................................................................................................................................................................................... 18
1、 Java中的反射...................................................................................................................................................................................... 18
一、说说你对Java中反射的理解.................................................................................................................................................... 18
2、 Java中的动态代理............................................................................................................................................................................. 18
一、 写一个ArrayList的动态代理类(笔试题)...................................................................................................................... 19
3、 Java中的设计模式............................................................................................................................................................................. 19
一、 你所知道的设计模式有哪些.................................................................................................................................................... 19
二、 单例设计模式................................................................................................................................................................................ 19
三、 工厂设计模式................................................................................................................................................................................ 20
四、 建造者模式(Builder)............................................................................................................................................................ 24
五、 适配器设计模式............................................................................................................................................................................ 25
六、 装饰模式(Decorator).......................................................................................................................................................... 27
七、 策略模式(strategy).............................................................................................................................................................. 28
八、 观察者模式(Observer)....................................................................................................................................................... 29
4. Android基础(★★★)................................................................................................................................................................................... 31
1、 Android基本常识.............................................................................................................................................................................. 31
一、 写10个简单的linux命令....................................................................................................................................................... 31
二、 书写出android工程的目录结构.......................................................................................................................................... 32
三、 什么是ANR 如何避免它?..................................................................................................................................................... 32
四、 谈谈Android的优势和不足之处......................................................................................................................................... 33
五、 一条最长的短信息约占多少byte?....................................................................................................................................... 34
六、 sim卡的EF文件有何做用?.................................................................................................................................................. 34
七、 如何判断是否有SD卡?.......................................................................................................................................................... 37
八、 dvm的进程和Linux的进程, 应用程序的进程是否为同一个概念?..................................................................... 37
九、 Android程序与Java程序的区别?................................................................................................................................... 38
十、 启动应用后,改变系统语言,应用的语言会改变么?.............................................................................................. 38
十一、 请介绍下adb、ddms、aapt的做用.............................................................................................................................. 38
十二、 ddms 和traceview的区别................................................................................................................................................. 39
1三、 补充知识:TraceView的使用............................................................................................................................................. 39
2、 Activity................................................................................................................................................................................................... 43
一、 什么是Activity?........................................................................................................................................................................... 43
二、 请描述一下Activity 生命周期............................................................................................................................................... 43
三、 如何保存Activity的状态?..................................................................................................................................................... 44
四、 两个Activity之间跳转时必然会执行的是哪几个方法?............................................................................................. 45
五、 横竖屏切换时Activity的生命周期....................................................................................................................................... 45
六、 如何将一个Activity设置成窗口的样式............................................................................................................................. 45
七、 如何退出Activity?如何安全退出已调用多个Activity的Application?.......................................................... 45
八、 请描述一下Activity的启动模式都有哪些以及各自的特色........................................................................................ 46
3、 Service.................................................................................................................................................................................................... 55
一、 Service是否在main thread中执行, service里面是否能执行耗时的操做?..................................................... 56
二、 Activity怎么和Service绑定,怎么在Activity中启动本身对应的Service?.................................................. 56
三、 请描述一下Service的生命周期............................................................................................................................................ 56
四、 什么是IntentService?有何优势?.................................................................................................................................... 58
五、 说说Activity、Intent、Service是什么关系................................................................................................................... 60
六、 Service和Activity在同一个线程吗.................................................................................................................................... 60
七、 Service里面能够弹吐司么...................................................................................................................................................... 61
4、 BroadCastReceiver.......................................................................................................................................................................... 61
一、 请描述一下BroadcastReceiver........................................................................................................................................... 61
二、 在manifest和代码中如何注册和使用BroadcastReceiver..................................................................................... 62
三、 BroadCastReceiver的生命周期.......................................................................................................................................... 62
5、 ContentProvider............................................................................................................................................................................... 62
一、 请介绍下ContentProvider是如何实现数据共享的.................................................................................................... 63
二、 请介绍下Android的数据存储方式..................................................................................................................................... 63
三、 为何要用ContentProvider?它和sql的实现上有什么差异?.......................................................................... 63
四、 说说ContentProvider、ContentResolver、ContentObserver之间的关系................................................ 64
6、 Android中的布局.............................................................................................................................................................................. 64
一、Android中经常使用的布局都有哪些............................................................................................................................................. 64
二、 谈谈UI中, Padding和Margin有什么区别?.......................................................................................................... 64
7、 ListView................................................................................................................................................................................................. 65
一、 ListView如何提升其效率?................................................................................................................................................... 65
二、 当ListView数据集改变后,如何更新ListView............................................................................................................ 65
三、 ListView如何实现分页加载................................................................................................................................................... 65
四、 ListView能够显示多种类型的条目吗................................................................................................................................. 66
五、 ListView如何定位到指定位置............................................................................................................................................... 66
六、 当在ScrollView中如何嵌入ListView............................................................................................................................... 66
七、 ListView中如何优化图片........................................................................................................................................................ 67
八、 ListView中图片错位的问题是如何产生的....................................................................................................................... 68
九、 Java中引用类型都有哪些........................................................................................................................................................ 68
8、 JNI&NDK.............................................................................................................................................................................................. 71
一、 在Android中如何调用C语言.............................................................................................................................................. 71
二、 请介绍一下NDK.......................................................................................................................................................................... 71
三、 JNI调用经常使用的两个参数.......................................................................................................................................................... 71
9、 Android中的网络访问.................................................................................................................................................................... 72
一、Android中如何访问网络........................................................................................................................................................... 72
二、 如何解析服务器传来的JSON文件...................................................................................................................................... 72
三、 如何解析服务器传来的XML格式数据............................................................................................................................... 74
四、 如何从网络上加载一个图片显示到界面............................................................................................................................. 76
五、 如何播放网络视频....................................................................................................................................................................... 77
10、 Intent...................................................................................................................................................................................................... 77
一、 Intent传递数据时,能够传递哪些类型数据?............................................................................................................... 77
二、 Serializable和Parcelable的区别...................................................................................................................................... 77
三、 请描述一下Intent 和 IntentFilter..................................................................................................................................... 78
11、 Fragment.......................................................................................................................................................................................... 80
一、 Fragment跟Activity之间是如何传值的.......................................................................................................................... 80
二、 描述一下Fragment的生命周期........................................................................................................................................... 81
5. Android高级(★★★)................................................................................................................................................................................... 81
1、 Android性能优化.............................................................................................................................................................................. 81
一、 如何对Android应用进行性能分析..................................................................................................................................... 82
二、 什么状况下会致使内存泄露.................................................................................................................................................... 83
三、 如何避免OOM异常.................................................................................................................................................................. 87
四、 Android中如何捕获未捕获的异常...................................................................................................................................... 89
2、 Android屏幕适配.............................................................................................................................................................................. 90
一、 屏幕适配方式都有哪些.............................................................................................................................................................. 90
二、 屏幕适配的处理技巧都有哪些................................................................................................................................................ 96
三、 dp和px之间的关系.................................................................................................................................................................. 99
3、 AIDL......................................................................................................................................................................................................... 99
一、 什么是AIDL以及如何使用...................................................................................................................................................... 99
4、自定义控件............................................................................................................................................................................................ 100
一、如何自定义一个控件.................................................................................................................................................................. 100
二、 请描述一下View的绘制流程.............................................................................................................................................. 101
5、Android中的事件处理.................................................................................................................................................................... 103
一、Handler机制................................................................................................................................................................................ 103
二、 事件分发机制.............................................................................................................................................................................. 104
6、Android签名....................................................................................................................................................................................... 106
一、简单描述下Android 数字签名............................................................................................................................................ 106
二、 使用Eclipse如何生成数字签名......................................................................................................................................... 107
7、 Android中的动画........................................................................................................................................................................... 107
一、 Android中的动画有哪几类,它们的特色和区别是什么......................................................................................... 108
二、 如何修改Activity进入和退出动画.................................................................................................................................... 108
8、 其余知识(非归类内容).............................................................................................................................................................. 108
一、 AsyncTask如何使用............................................................................................................................................................... 109
二、 都使用过哪些框架、平台...................................................................................................................................................... 113
三、 都使用过哪些自定义控件...................................................................................................................................................... 113
6. Android项目(★★★)................................................................................................................................................................................ 114
一、 如何介绍本身的项目................................................................................................................................................................ 114
二、 项目介绍示范.............................................................................................................................................................................. 114
附录:更新记录..................................................................................................................................................................................................... 115
=======================================
更多精品教程尽在【perfect教程】
http://shop117393101.taobao.com
如地址失效,可联系Q1871209564
=======================================
非此地址购买得到,均为二次倒卖、翻录
获得的视频不完整、无售后保障
本店长期更新黑马Android视频
一次购买终身售后
=======================================
Android面试宝典-V1
该面试宝典不只收录了本人亲身面试遇到的问题,还收录了从黑马学子那里收集过来的问题。在之后的工做中本人也会不断的更新和充实该面试宝典,固然也但愿你们可以多多奉献比较优质的面试题。
该面试宝典不只展现了常见的面试问题以及回答技巧,还详细讲解了每一道题所包含的知识点,让黑马学子不只知其然,更知其因此然。
本人的面试实战记录发布在黑马论坛:http://bbs.itheima.com/thread-196394-1-1.html
你们能够访问上面的网址,经过阳哥的实战记录略微感知一下真实面试的状况,从中学习一些面试技巧以便让本身在将来的面试中可以驾轻就熟,顺利拿到本身喜欢的offer。
有人可能会问对于咱们学Android的同窗来说,面试还会问Java基础吗?答案是会的,可是不会太多,所以我给了两颗星的重要程度。通常笔试的时候出现java基础题的几率比较大,口头面试的时候比较少,好比本身在面试的时候一些对基础知识比较看重的面试官会深究着Java基础去问,好比问你异常的类型以及处理方式,集合的体系结构等等。
继承:继承是从已有类获得继承信息建立新类的过程。提供继承信息的类被称为父类(超类、基类);获得继承信息的类被称为子类(派生类)。继承让变化中的软件系统有了必定的延续性,同时继承也是封装程序中可变因素的重要手段。
封装:一般认为封装是把数据和操做数据的方法绑定起来,对数据的访问只能经过已定义的接口。面向对象的本质就是将现实世界描绘成一系列彻底自治、封闭的对象。咱们在类中编写的方法就是对实现细节的一种封装;咱们编写一个类就是对数据和数据操做的封装。能够说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口。
多态性:多态性是指容许不一样子类型的对象对同一消息做出不一样的响应。简单的说就是用一样的对象引用调用一样的方法可是作了不一样的事情。多态性分为编译时的多态性和运行时的多态性。若是将对象的方法视为对象向外界提供的服务,那么运行时的多态性能够解释为:当A系统访问B系统提供的服务时,B系统有多种提供服务的方式,但一切对A系统来讲都是透明的。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。运行时的多态是面向对象最精髓的东西,要实现多态须要作两件事:1. 方法重写(子类继承父类并重写父类中已有的或抽象的方法);2. 对象造型(用父类型引用引用子类型对象,这样一样的引用调用一样的方法就会根据子类对象的不一样而表现出不一样的行为)。
抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。
靠的是父类或接口定义的引用变量能够指向子类或具体实现类的实例对象,而程序调用的方法在运行期才动态绑定,就是引用变量所指向的具体实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变量的类型中定义的方法。
1)按照异常须要处理的时机分为编译时异常也叫CheckedException和运行时异常也叫RuntimeException。只有java语言提供了Checked异常,Java认为Checked异常都是能够被处理的异常,因此Java程序必须显式处理Checked异常。若是程序没有处理Checked异常,该程序在编译时就会发生错误没法编译。这体现了Java的设计哲学:没有完善错误处理的代码根本没有机会被执行。对Checked异常处理方法有两种:
1 当前方法知道如何处理该异常,则用try...catch块来处理该异常。
2 当前方法不知道如何处理,则在定义该方法是声明抛出该异常。
运行时异常只有当代码在运行时才发行的异常,编译时不须要try catch。Runtime如除数是0和数组下标越界等,其产生频繁,处理麻烦,若显示申明或者捕获将会对程序的可读性和运行效率影响很大。因此由系统自动检测并将它们交给缺省的异常处理程序。固然若是你有处理要求也能够显示捕获它们。
代码在走到第3行的时候雨大了一个MathException,这时第四行的代码就不会执行了,代码直接跳转到catch语句中,走到第6行的时候,异常机制有这么一个原则若是在catch中遇到了return或者异常等能使该函数终止的话那么用finally就必须先执行完finally代码块里面的代码而后再返回值。所以代码又跳到第8行,惋惜第8行是一个return语句,那么这个时候方法就结束了,所以第6行的返回结果就没法被真正返回。若是finally仅仅是处理了一个释放资源的操做,那么该道题最终返回的结果就是2。
所以上面返回值是3。
Java有8种基本数据类型
byte 1
char 2
sort 2
int 4
float 4
double 8
long 8
boolean 1(boolean类型比较特别可能只占一个bit,多个boolean可能共同占用一个字节)
String是引用类型,底层用char数组实现的。由于String是final类,在java中被final修饰的类不能被继承,所以String固然不能够被继承。
字节流和字符流。字节流继承于InputStream和OutputStream,字符流继承于InputStreamReader 和OutputStreamWriter。
字节输入流转字符输入流经过InputStreamReader实现,该类的构造函数能够传入InputStream对象。
字节输出流转字符输出流经过OutputStreamWriter实现,该类的构造函数能够传入OutputStream对象。
在java中可以被序列化的类必须先实现Serializable接口,该接口没有任何抽象方法只是起到一个标记做用。
已知一个HashMap<Integer,User>集合, User有name(String)和age(int)属性。请写一个方法实现对HashMap的排序功能,该方法接收HashMap<Integer,User>为形参,返回类型为HashMap<Integer,User>,要求对HashMap中的User的age倒序进行排序。排序时key=value键值对不得拆散。
:要作出这道题必须对集合的体系结构很是的熟悉。HashMap自己就是不可排序的,可是该道题恰恰让给HashMap排序,那咱们就得想在API中有没有这样的Map结构是有序的,LinkedHashMap,对的,就是他,他是Map结构,也是链表结构,有序的,更可喜的是他是HashMap的子类,咱们返回LinkedHashMap<Integer,User>便可,还符合面向接口(父类编程的思想)。
但凡是对集合的操做,咱们应该保持一个原则就是能用JDK中的API就有JDK中的API,好比排序算法咱们不该该去用冒泡或者选择,而是首先想到用Collections集合工具类。 users = new HashMap<>(); users.put(1, new User("张三", 25)); users.put(3, new User("李四", 22)); users.put(2, new User("王五", 28)); System.out.println(users); HashMap<integer,user> sortHashMap = sortHashMap(users); System.out.println(sortHashMap); /** * 控制台输出内容 * {1=User [name=张三, age=25], 2=User [name=王五, age=28], 3=User [name=李四, age=22]} {2=User [name=王五, age=28], 1=User [name=张三, age=25], 3=User [name=李四, age=22]} */ } public static HashMap<integer, user=""> sortHashMap(HashMap<integer, user=""> map) { // 首先拿到map的键值对集合 Set<entry<integer, user="">> entrySet = map.entrySet(); // 将set集合转为List集合,为何,为了使用工具类的排序方法 List<entry<integer, user="">> list = new ArrayList<entry<integer, user="">>(entrySet); " v:shapes="_x0000_s1091">
>() { @Override public int compare(Entry<integer, user=""> o1, Entry<integer, user=""> o2) { //按照要求根据User的age的倒序进行排 return o2.getValue().getAge()-o1.getValue().getAge(); } }); //建立一个新的有序的HashMap子类的集合 LinkedHashMap<integer, user=""> linkedHashMap = new LinkedHashMap<integer, user="">(); //将List中的数据存储在LinkedHashMap中 for(Entry<integer, user=""> entry : list){ linkedHashMap.put(entry.getKey(), entry.getValue()); } //返回结果 return linkedHashMap; } } " v:shapes="_x0000_s1090">
请问ArrayList、HashSet、HashMap是线程安全的吗?若是不是我想要线程安全的集合怎么办?
咱们都看过上面那些集合的源码(若是没有那就看看吧),每一个方法都没有加锁,显然都是线程不安全的。话又说过来若是他们安全了也就没第二问了。
在集合中Vector和HashTable却是线程安全的。你打开源码会发现其实就是把各自核心方法添加上了synchronized关键字。
Collections工具类提供了相关的API,可让上面那3个不安全的集合变为安全的。
上面几个函数都有对应的返回值类型,传入什么类型返回什么类型。打开源码其实实现原理很是简单,就是将集合的核心方法添加上了synchronized关键字。
java.lang.Thread 类的实例就是一个线程可是它须要调用java.lang.Runnable接口来执行,因为线程类自己就是调用的Runnable接口因此你能够继承java.lang.Thread 类或者直接实现Runnable接口来重写run()方法实现线程。
最大的不一样是在等待时wait会释放锁,而sleep一直持有锁。wait一般被用于线程间交互,sleep一般被用于暂停执行。
一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰以后,那么就具有了两层语义:
1)保证了不一样线程对这个变量进行操做时的可见性,即一个线程修改了某个变量的值,这新值对其余线程来讲是当即可见的。
2)禁止进行指令重排序。
volatile本质是在告诉jvm当前变量在寄存器(工做内存)中的值是不肯定的,须要从主存中读取;
synchronized则是锁定当前变量,只有当前线程能够访问该变量,其余线程被阻塞住。
1.volatile仅能使用在变量级别;
synchronized则能够使用在变量、方法、和类级别的
2.volatile仅能实现变量的修改可见性,并不能保证原子性;
synchronized则能够保证变量的修改可见性和原子性
3.volatile不会形成线程的阻塞;
synchronized可能会形成线程的阻塞。
4.volatile标记的变量不会被编译器优化;
synchronized标记的变量能够被编译器优化
上面的代码执行完后输出的结果肯定为1000吗?
答案是不必定,或者不等于1000。这是为何吗?
在 java 的内存模型中每个线程运行时都有一个线程栈,线程栈保存了线程运行时候变量值信息。当线程访问某一个对象时候值的时候,首先经过对象的引用找到对应在堆内存的变量的值,而后把堆内存变量的具体值load到线程本地内存中,创建一个变量副本,以后线程就再也不和对象在堆内存变量值有任何关系,而是直接修改副本变量的值,在修改完以后的某一个时刻(线程退出以前),自动把线程变量副本的值回写到对象在堆中变量。这样在堆中的对象的值就产生变化了。
也就是说上面主函数中开启了1000个子线程,每一个线程都有一个变量副本,每一个线程修改变量只是临时修改了本身的副本,当线程结束时再将修改的值写入在主内存中,这样就出现了线程安全问题。所以结果就不可能等于1000了,通常都会小于1000。
上面的解释用一张图表示以下:
(图片来自网络,非本人所绘)
线程池就是事先将多个线程对象放到一个容器中,当使用的时候就不用new线程而是直接去池中拿线程便可,节省了开辟子线程的时间,提升的代码执行效率。
在JDK的java.util.concurrent.Executors中提供了生成多种线程池的静态方法。
而后调用他们的execute方法便可。
Java中的反射首先是可以获取到Java中要反射类的字节码,获取字节码有三种方法,1.Class.forName(className) 2.类名.class 3.this.getClass()。而后将字节码中的方法,变量,构造函数等映射成相应的Method、Filed、Constructor等类,这些类提供了丰富的方法能够被咱们所使用。
list = new ArrayList(); List proxyInstance = (List) Proxy.newProxyInstance(list.getClass().getClassLoader(), list.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(list, args); } }); proxyInstance.add("你好"); System.out.println(list); " v:shapes="_x0000_s1086">
Java中通常认为有23种设计模式,咱们不须要全部的都会,可是其中经常使用的几种设计模式应该去掌握。下面列出了全部的设计模式。须要掌握的设计模式我单独列出来了,固然能掌握的越多越好。
整体来讲设计模式分为三大类:
建立型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
最好理解的一种设计模式,分为懒汉式和饿汉式。
饿汉式:
懒汉式:
工厂模式分为工厂方法模式和抽象工厂模式。
工厂方法模式
工厂方法模式分为三种:普通工厂模式,就是创建一个工厂类,对实现了同一接口的一些类进行实例的建立。
多个工厂方法模式,是对普通工厂方法模式的改进,在普通工厂方法模式中,若是传递的字符串出错,则不能正确建立对象,而多个工厂方法模式是提供多个工厂方法,分别建立对象。
静态工厂方法模式,将上面的多个工厂方法模式里的方法置为静态的,不须要建立实例,直接调用便可。
普通工厂模式
多个工厂方法模式
该模式是对普通工厂方法模式的改进,在普通工厂方法模式中,若是传递的字符串出错,则不能正确建立对象,而多个工厂方法模式是提供多个工厂方法,分别建立对象。
静态工厂方法模式,将上面的多个工厂方法模式里的方法置为静态的,不须要建立实例,直接调用便可。
抽象工厂模式
工厂方法模式有一个问题就是,类的建立依赖工厂类,也就是说,若是想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,因此,从设计角度考虑,有必定的问题,如何解决?就用到抽象工厂模式,建立多个工厂类,这样一旦须要增长新的功能,直接增长新的工厂类就能够了,不须要修改以前的代码。
工厂类模式提供的是建立单个类的模式,而建造者模式则是将各类产品集中起来进行管理,用来建立复合对象,所谓复合对象就是指某个类具备不一样的属性,其实建造者模式就是前面抽象工厂模式和最后的Test结合起来获得的。
list = new ArrayList(); public void produceMailSender(int count) { for (int i = 0; i < count; i++) { list.add(new MailSender()); } } public void produceSmsSender(int count) { for (int i = 0; i < count; i++) { list.add(new SmsSender()); } } } " v:shapes="_x0000_s1078">
适配器模式将某个类的接口转换成客户端指望的另外一个接口表示,目的是消除因为接口不匹配所形成的类的兼容性问题。主要分为三类:类的适配器模式、对象的适配器模式、接口的适配器模式。
类的适配器模式
对象的适配器模式
基本思路和类的适配器模式相同,只是将Adapter类做修改,此次不继承Source类,而是持有Source类的实例,以达到解决兼容性的问题。
接口的适配器模式
接口的适配器是这样的:有时咱们写的一个接口中有多个抽象方法,当咱们写该接口的实现类时,必须实现该接口的全部方法,这明显有时比较浪费,由于并非全部的方法都是咱们须要的,有时只须要某一些,此处为了解决这个问题,咱们引入了接口的适配器模式,借助于一个抽象类,该抽象类实现了该接口,实现了全部的方法,而咱们不和原始的接口打交道,只和该抽象类取得联系,因此咱们写一个类,继承该抽象类,重写咱们须要的方法就行。
顾名思义,装饰模式就是给一个对象增长一些新的功能,并且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例。
策略模式定义了一系列算法,并将每一个算法封装起来,使他们能够相互替换,且算法的变化不会影响到使用算法的客户。须要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,设计一个抽象类(无关紧要,属于辅助类),提供辅助函数。策略模式的决定权在用户,系统自己提供不一样算法的实现,新增或者删除算法,对各类算法作封装。所以,策略模式多用在算法决策系统中,外部用户只须要决定用哪一个算法便可。
观察者模式很好理解,相似于邮件订阅和RSS订阅,当咱们浏览一些博客或wiki时,常常会看到RSS图标,就这的意思是,当你订阅了该文章,若是后续有更新,会及时通知你。其实,简单来说就一句话:当一个对象变化时,其它依赖该对象的对象都会收到通知,而且随着变化!对象之间是一种一对多的关系。
vector = new Vector(); @Override public void add(Observer observer) { vector.add(observer); } @Override public void del(Observer observer) { vector.remove(observer); } @Override public void notifyObservers() { Enumeration enumo = vector.elements(); while (enumo.hasMoreElements()) { enumo.nextElement().update(); } } } public class MySubject extends AbstractSubject { @Override public void operation() { System.out.println("update self!"); notifyObservers(); } } public class ObserverTest { public static void main(String[] args) { Subject sub = new MySubject(); sub.add(new Observer1()); " v:shapes="_x0000_s1070">
mkdir 建立文件夹
rmdir 删除文件夹
rm 删除文件
mv 移动文件
cp 拷贝文件
cat 查看文件
tail 查看文件尾部
more 分页查看文件
cd 切换当前目录
ls 列出文件清单
reboot 重启
date 显示日期
cal 显示日历
ps 查看系统进程至关于windows的任务管理器
ifconfig 配置网络
src 源文件
gen 生成的文件 R文件就在此
android. jar 依赖的android sdk
assets 资源文件
bin 生成的字节码apk在此
libs 依赖jar和so
res 资源文件
drawable
drawable-hdpi
layout
menu
values
AndroidManifest.xml
project.properties
在Android上,若是你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称做应用程序无响应(ANR:Application Not Responding)对话框。用户能够选择让程序继续运行,可是,他们在使用你的应用程序时,并不但愿每次都要处理这个对话框。所以,在程序里对响应性能的设计很重要,这样,系统不会显示ANR给用户。
不一样的组件发生ANR的时间不同,主线程(Activity、Service)是5秒,BroadCastReceiver 是10秒。
解决方案:
将全部耗时操做,好比访问网络,Socket通讯,查询大量SQL语句,复杂逻辑计算等都放在子线程中去,而后经过handler.sendMessage、runonUITread、AsyncTask等方式更新UI。不管如何都要确保用户界面操做的流畅度。若是耗时操做须要让用户等待,那么能够在界面上显示进度条。
优势:
一、开放性,开源,免费,可定制
二、挣脱运营商束缚
三、丰富的硬件选择
四、不受任何限制的开发商
五、无缝结合的Google应用
缺点:
一、安全问题、隐私问题
二、同质化严重
三、运营商对Android手机仍然有影响
四、山寨化严重
五、过度依赖开发商,缺少标准配置
在国内的三大运营商一般状况下中文70(包括标点),英文160个。对于国外的其余运行商具体多长须要看运营商类型了。
android内部是经过以下代码进行判断具体一个短信多少byte的。
ArrayList<String> android.telephony.SmsManager.divideMessage(String text)
基本文件EF(Elementary File)是SIM卡文件系统的一部分。
|
经过以下方法:
Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
若是返回true就是有sdcard,若是返回false则没有。
dvm指dalvik的虚拟机。每个Android应用程序都拥有一个独立的Dalvik虚拟机实例,应用程序都在它本身的进程中运行。而每个dvm都是在Linux 中的一个进程,因此说能够近似认为是同一个概念。
什么是android DVM:Dalvik是Google公司本身设计用于Android平台的Java虚拟机,每个Dalvik 应用做为一个独立的Linux 进程执行。独立的进程能够防止在虚拟机崩溃的时候全部程序都被关闭。
Dalvik和Java虚拟机的区别
1:Dalvik主要是完成对象生命周期管理,堆栈管理,线程管理,安全和异常管理,以及垃圾回收等等重要功能。
2:Dalvik负责进程隔离和线程管理,每个Android应用在底层都会对应一个独立的Dalvik虚拟机实例,其代码在虚拟机的解释下得以执行。
3:不一样于Java虚拟机运行java字节码,Dalvik虚拟机运行的是其专有的文件格式Dex
4: dex文件格式能够减小总体文件尺寸,提升I/O操做的类查找速度。
5: odex是为了在运行过程当中进一步提升性能,对dex文件的进一步优化。
6:全部的Android应用的线程都对应一个Linux线程,虚拟机于是能够更多的依赖操做系统的线程调度和管理机制
7:有一个特殊的虚拟机进程Zygote,他是虚拟机实例的孵化器。它在系统启动的时候就会产生,它会完成虚拟机的初始化,库的加载,预制类库和初始化的操做。若是系统须要一个新的虚拟机实例,它会迅速复制自身,以最快的数据提供给系统。对于一些只读的系统库,全部虚拟机实例都和Zygote共享一块内存区域。
Android程序用android sdk开发,java程序用javasdk开发.
Android SDK引用了大部分的Java SDK,少数部分被Android SDK抛弃,好比说界面部分,java.awt swing package除了java.awt.font被引用外,其余都被抛弃,在Android平台开发中不能使用。android sdk 添加工具jar httpclient , pull opengl
这个通常是不会的,通常须要重启应用才能改变应用语言。可是对应应用来讲若是作了国际化处理则支持若是没有处理那系统语言再更改也是无用的。
adb是Android Debug Bridge ,Android调试桥的意思,ddms是Dalvik Debug Monitor Service,dalvik调试监视服务。aapt即Android Asset Packaging Tool,在SDK的build-tools目录下。该工具能够查看,建立, 更新ZIP格式的文档附件(zip, jar, apk)。也可将资源文件编译成二进制文件,尽管咱们没有直接使用过该工具,可是开发工具会使用这个工具打包apk文件构成一个Android 应用程序。
Android 的主要调试工具是adb(Android debuging bridge),ddms是一个在adb基础上的一个图形化工具。
adb,它是一个命令行工具。而ddms功能与adb相同,只是它有一个图形化界面。对不喜欢命今操做方式的人来讲是一个不错的选择。
简单的说ddms是一个程序执行查看器,在里面能够看见线程和堆栈等信息,traceView是程序性能分析器。
1、TraceView简介
Traceview是Android平台特有的数据采集和分析工具,它主要用于分析Android中应用程序的hotspot(瓶颈)。Traceview自己只是一个数据分析工具,而数据的采集则须要使用Android SDK中的Debug类或者利用DDMS工具。两者的用法以下:
开发者在一些关键代码段开始前调用Android SDK中Debug类的startMethodTracing函数,并在关键代码段结束前调用stopMethodTracing函数。这两个函数运行过程当中将采集运行时间内该应用全部线程(注意,只能是Java线程)的函数执行状况,并将采集数据保存到/mnt/sdcard/下的一个文件中。开发者而后须要利用SDK中的Traceview工具来分析这些数据。
借助Android SDK中的DDMS工具。DDMS可采集系统中某个正在运行的进程的函数调用信息。对开发者而言,此方法适用于没有目标应用源代码的状况。DDMS工具中Traceview的使用以下图所示。
点击上图中所示按钮便可以采集目标进程的数据。当中止采集时,DDMS会自动触发Traceview工具来浏览采集数据。
下面,咱们经过一个示例程序介绍Traceview的使用。
实例程序以下图所示:界面有4个按钮,对应四个方法。
点击不一样的方法会进行不一样的耗时操做。
咱们分别点击按钮一次,要求找出最耗时的方法。点击前经过DDMS 启动 Start Method Profiling按钮。
而后依次点击4个按钮,都执行后再次点击上图中红框中按钮,中止收集数据。
接下来咱们开始对数据进行分析。
当咱们中止收集数据的时候会出现以下分析图表。该图表分为2大部分,上面分不一样的行,每一行表明一个线程的执行耗时状况。main线程对应行的的内容很是丰富,而其余线程在这段时间内干得工做则要少得多。图表的下半部分是具体的每一个方法执行的时间状况。显示方法执行状况的前提是先选中某个线程。
咱们主要是分析main线程。
上面方法指标参数所表明的意思以下:
列名 |
描述 |
Name |
该线程运行过程当中所调用的函数名 |
Incl Cpu Time |
某函数占用的CPU时间,包含内部调用其它函数的CPU时间 |
Excl Cpu Time |
某函数占用的CPU时间,但不含内部调用其它函数所占用的CPU时间 |
Incl Real Time |
某函数运行的真实时间(以毫秒为单位),内含调用其它函数所占用的真实时间 |
Excl Real Time |
某函数运行的真实时间(以毫秒为单位),不含调用其它函数所占用的真实时间 |
Call+Recur Calls/Total |
某函数被调用次数以及递归调用占总调用次数的百分比 |
Cpu Time/Call |
某函数调用CPU时间与调用次数的比。至关于该函数平均执行时间 |
Real Time/Call |
同CPU Time/Call相似,只不过统计单位换成了真实时间 |
咱们为了找到最耗时的操做,那么能够经过点击Incl Cpu Time,让其按照时间的倒序排列。我点击后效果以下图:
经过分析发现:method1最耗时,耗时2338毫秒。
那么有了上面的信息咱们能够进入咱们的method1方法查看分析咱们的代码了。
四大组件之一,一般一个用户交互界面对应一个activity。activity 是Context的子类,同时实现了window.callback和keyevent.callback, 能够处理与窗体用户交互的事件。
常见的Activity类型有FragmentActivitiy,ListActivity,TabAcitivty等。
若是界面有共同的特色或者功能的时候,还会本身定义一个BaseActivity。
Activity从建立到销毁有多种状态,从一种状态到另外一种状态时会激发相应的回调方法,这些回调方法包括:onCreate onStart onResume onPause onStop onDestroy
其实这些方法都是两两对应的,onCreate建立与onDestroy销毁;
onStart可见与onStop不可见;onResume可编辑(即焦点)与onPause;
这6个方法是相对应的,那么就只剩下一个onRestart方法了,这个方法在何时调用呢?
答案就是:在Activity被onStop后,可是没有被onDestroy,在再次启动此Activity时就调用onRestart(而再也不调用onCreate)方法;
若是被onDestroy了,则是调用onCreate方法。
Activity的状态一般状况下系统会自动保存的,只有当咱们须要保存额外的数据时才须要使用到这样的功能。
通常来讲, 调用onPause()和onStop()方法后的activity实例仍然存在于内存中, activity的全部信息和状态数据不会消失, 当activity从新回到前台以后, 全部的改变都会获得保留。
可是当系统内存不足时, 调用onPause()和onStop()方法后的activity可能会被系统摧毁, 此时内存中就不会存有该activity的实例对象了。若是以后这个activity从新回到前台, 以前所做的改变就会消失。为了不此种状况的发生, 咱们能够覆写onSaveInstanceState()方法。onSaveInstanceState()方法接受一个Bundle类型的参数, 开发者能够将状态数据存储到这个Bundle对象中, 这样即便activity被系统摧毁, 当用户从新启动这个activity而调用它的onCreate()方法时, 上述的Bundle对象会做为实参传递给onCreate()方法, 开发者能够从Bundle对象中取出保存的数据, 而后利用这些数据将activity恢复到被摧毁以前的状态。
须要注意的是, onSaveInstanceState()方法并非必定会被调用的, 由于有些场景是不须要保存状态数据的. 好比用户按下BACK键退出activity时, 用户显然想要关闭这个activity, 此时是没有必要保存数据以供下次恢复的, 也就是onSaveInstanceState()方法不会被调用. 若是调用onSaveInstanceState()方法, 调用将发生在onPause()或onStop()方法以前。
通常状况下好比说有两个activity,分别叫A,B,当在A里面激活B组件的时候, A会调用 onPause()方法,而后B调用onCreate() ,onStart(), onResume()。
这个时候B覆盖了窗体, A会调用onStop()方法. 若是B是个透明的,或者是对话框的样式, 就不会调用A的onStop()方法。
此时的生命周期跟清单文件里的配置有关系。
一、不设置Activity的android:configChanges时,切屏会从新调用各个生命周期
默认首先销毁当前activity,而后从新加载。
二、设置Activity的android:configChanges="orientation|keyboardHidden|screenSize"时,切屏不会从新调用各个生命周期,只会执行onConfigurationChanged方法。
一般在游戏开发, 屏幕的朝向都是写死的。
只须要给咱们的Activity配置以下属性便可。
android:theme="@android:style/Theme.Dialog"
一、一般状况用户退出一个Activity只需按返回键,咱们写代码想退出activity直接调用finish()方法就行。
二、记录打开的Activity:
每打开一个Activity,就记录下来。在须要退出时,关闭每个Activity便可。
lists ;// 在application 全局的变量里面 lists = new ArrayList(); lists.add(this); for(Activity activity: lists) { activity.finish(); } lists.remove(this); " v:shapes="_x0000_s1067">
三、发送特定广播:
在须要结束应用时,发送一个特定的广播,每一个Activity收到广播后,关闭便可。
//给某个activity 注册接受接受广播的意图
registerReceiver(receiver, filter)
//若是过接受到的是 关闭activity的广播 就调用finish()方法 把当前的activity finish()掉
四、递归退出
在打开新的Activity时使用startActivityForResult,而后本身加标志,在onActivityResult中处理,递归关闭。
五、其实 也能够经过 intent的flag 来实现intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)激活一个新的activity。此时若是该任务栈中已经有该Activity,那么系统会把这个Activity上面的全部Activity干掉。其实至关于给Activity配置的启动模式为SingleTop。
启动模式(launchMode)在多个Activity跳转的过程当中扮演着重要的角色,它能够决定是否生成新的Activity实例,是否重用已存在的Activity实例,是否和其余Activity实例公用一个task里。这里简单介绍一下task的概念,task是一个具备栈结构的对象,一个task能够管理多个Activity,启动一个应用,也就建立一个与之对应的task。
Activity一共有如下四种launchMode:
1.standard
2.singleTop
3.singleTask
4.singleInstance
咱们能够在AndroidManifest.xml配置<activity>的android:launchMode属性为以上四种之一便可。
下面咱们结合实例一一介绍这四种lanchMode:
standard模式是默认的启动模式,不用为<activity>配置android:launchMode属性便可,固然也能够指定值为standard。
咱们将建立一个Activity,命名为FirstActivity,来演示一下标准的启动模式。FirstActivity代码以下:
FirstActivity界面中的TextView用于显示当前Activity实例的序列号,Button用于跳转到下一个FirstActivity界面。
而后咱们连续点击几回按钮,将会出现下面的现象:
咱们注意到都是FirstActivity的实例,但序列号不一样,而且咱们须要连续按后退键两次,才能回到第一个FirstActivity。standard模式的原理以下图所示:
如图所示,每次跳转系统都会在task中生成一个新的FirstActivity实例,而且放于栈结构的顶部,当咱们按下后退键时,才能看到原来的FirstActivity实例。
这就是standard启动模式,无论有没有已存在的实例,都生成新的实例。
咱们在上面的基础上为<activity>指定属性android:launchMode="singleTop",系统就会按照singleTop启动模式处理跳转行为。咱们重复上面几个动做,将会出现下面的现象:
咱们看到这个结果跟standard有所不一样,三个序列号是相同的,也就是说使用的都是同一个FirstActivity实例;若是按一下后退键,程序当即退出,说明当前栈结构中只有一个Activity实例。singleTop模式的原理以下图所示:
正如上图所示,跳转时系统会先在栈结构中寻找是否有一个FirstActivity实例正位于栈顶,若是有则再也不生成新的,而是直接使用。也许朋友们会有疑问,我只看到栈内只有一个Activity,若是是多个Activity怎么办,若是不是在栈顶会如何?咱们接下来再经过一个示例来证明一下你们的疑问。
咱们再新建一个Activity命名为SecondActivity,以下:
而后将以前的FirstActivity跳转代码改成:
这时候,FirstActivity会跳转到SecondActivity,SecondActivity又会跳转到FirstActivity。演示结果以下:
咱们看到,两个FirstActivity的序列号是不一样的,证实从SecondActivity跳转到FirstActivity时生成了新的FirstActivity实例。原理图以下:
咱们看到,当从SecondActivity跳转到FirstActivity时,系统发现存在有FirstActivity实例,但不是位于栈顶,因而从新生成一个实例。
这就是singleTop启动模式,若是发现有对应的Activity实例正位于栈顶,则重复利用,再也不生成新的实例。
在上面的基础上咱们修改FirstActivity的属性android:launchMode="singleTask"。演示的结果以下:
咱们注意到,在上面的过程当中,FirstActivity的序列号是不变的,SecondActivity的序列号却不是惟一的,说明从SecondActivity跳转到FirstActivity时,没有生成新的实例,可是从FirstActivity跳转到SecondActivity时生成了新的实例。singleTask模式的原理图以下图所示:
在图中的下半部分是SecondActivity跳转到FirstActivity后的栈结构变化的结果,咱们注意到,SecondActivity消失了,没错,在这个跳转过程当中系统发现有存在的FirstActivity实例,因而再也不生成新的实例,而是将FirstActivity之上的Activity实例通通出栈,将FirstActivity变为栈顶对象,显示到幕前。也许朋友们有疑问,若是将SecondActivity也设置为singleTask模式,那么SecondActivity实例是否是能够惟一呢?在咱们这个示例中是不可能的,由于每次从SecondActivity跳转到FirstActivity时,SecondActivity实例都被迫出栈,下次等FirstActivity跳转到SecondActivity时,找不到存在的SecondActivity实例,因而必须生成新的实例。可是若是咱们有ThirdActivity,让SecondActivity和ThirdActivity互相跳转,那么SecondActivity实例就能够保证惟一。
这就是singleTask模式,若是发现有对应的Activity实例,则使此Activity实例之上的其余Activity实例通通出栈,使此Activity实例成为栈顶对象,显示到幕前。
这种启动模式比较特殊,由于它会启用一个新的栈结构,将Activity放置于这个新的栈结构中,并保证再也不有其余Activity实例进入。
咱们修改FirstActivity的launchMode="standard",SecondActivity的launchMode="singleInstance",因为涉及到了多个栈结构,咱们须要在每一个Activity中显示当前栈结构的id,因此咱们为每一个Activity添加以下代码:
而后咱们再演示一下这个流程:
咱们发现这两个Activity实例分别被放置在不一样的栈结构中,关于singleInstance的原理图以下
咱们看到从FirstActivity跳转到SecondActivity时,从新启用了一个新的栈结构,来放置SecondActivity实例,而后按下后退键,再次回到原始栈结构;图中下半部分显示的在SecondActivity中再次跳转到FirstActivity,这个时候系统会在原始栈结构中生成一个FirstActivity实例,而后回退两次,注意,并无退出,而是回到了SecondActivity,为何呢?是由于从SecondActivity跳转到FirstActivity的时候,咱们的起点变成了SecondActivity实例所在的栈结构,这样一来,咱们须要“回归”到这个栈结构。
若是咱们修改FirstActivity的launchMode值为singleTop、singleTask、singleInstance中的任意一个,流程将会如图所示:
singleInstance启动模式多是最复杂的一种模式,为了帮助你们理解,我举一个例子,假如咱们有一个share应用,其中的ShareActivity是入口Activity,也是可供其余应用调用的Activity,咱们把这个Activity的启动模式设置为singleInstance,而后在其余应用中调用。咱们编辑ShareActivity的配置:
" v:shapes="_x0000_s1062">
而后咱们在其余应用中这样启动该Activity:
当咱们打开ShareActivity后再按后退键回到原来界面时,ShareActivity作为一个独立的个体存在,若是这时咱们打开share应用,无需建立新的ShareActivity实例便可看到结果,由于系统会自动查找,存在则直接利用。你们能够在ShareActivity中打印一下taskId,看看效果。关于这个过程,原理图以下:
默认状况,若是没有显示的指servic所运行的进程, Service和activity是运行在当前app所在进程的main thread(UI主线程)里面。
service里面不能执行耗时的操做(网络请求,拷贝数据库,大文件 )
特殊状况 ,能够在清单文件配置 service 执行所在的进程 ,让service在另外的进程中执行
" v:shapes="_x0000_s1060">
Activity经过bindService(Intent service, ServiceConnection conn, int flags)跟Service进行绑定,当绑定成功的时候Service会将代理对象经过回调的形式传给conn,这样咱们就拿到了Service提供的服务代理对象。
在Activity中能够经过startService和bindService方法启动Service。通常状况下若是想获取Service的服务对象那么确定须要经过bindService()方法,好比音乐播放器,第三方支付等。若是仅仅只是为了开启一个后台任务那么能够使用startService()方法。
Service有绑定模式和非绑定模式,以及这两种模式的混合使用方式。不一样的使用方法生命周期方法也不一样。
非绑定模式:当第一次调用startService的时候执行的方法依次为onCreate()、onStartCommand(),当Service关闭的时候调用onDestory方法。
绑定模式:第一次bindService()的时候,执行的方法为onCreate()、onBind()解除绑定的时候会执行onUnbind()、onDestory()。
上面的两种生命周期是在相对单纯的模式下的情形。咱们在开发的过程当中还必须注意Service实例只会有一个,也就是说若是当前要启动的Service已经存在了那么就不会再次建立该Service固然也不会调用onCreate()方法。
一个Service能够被多个客户进行绑定,只有全部的绑定对象都执行了onBind()方法后该Service才会销毁,不过若是有一个客户执行了onStart()方法,那么这个时候若是全部的bind客户都执行了unBind()该Service也不会销毁。
Service的生命周期图以下所示,帮助你们记忆。
咱们一般只会使用Service,可能IntentService对大部分同窗来讲都是第一次据说。那么看了下面的介绍相信你就再也不陌生了。若是你仍是不了解那么在面试的时候你就坦诚说没用过或者不了解等。并非全部的问题都须要回答上来的。
1、IntentService简介
IntentService是Service的子类,比普通的Service增长了额外的功能。先看Service自己存在两个问题:
Service不会专门启动一条单独的进程,Service与它所在应用位于同一个进程中;
Service也不是专门一条新线程,所以不该该在Service中直接处理耗时的任务;
2、IntentService特征
会建立独立的worker线程来处理全部的Intent请求;
会建立独立的worker线程来处理onHandleIntent()方法实现的代码,无需处理多线程问题;
全部请求处理完成后,IntentService会自动中止,无需调用stopSelf()方法中止Service;
为Service的onBind()提供默认实现,返回null;
为Service的onStartCommand提供默认实现,将请求Intent添加到队列中;
3、使用IntentService
本人写了一个IntentService的使用例子供参考。该例子中一个MainActivity一个MyIntentService,这两个类都是四大组件固然须要在清单文件中注册。这里只给出核心代码:
MainActivity.java:
MyIntentService.java
运行后效果以下:
他们都是Android开发中使用频率最高的类。其中Activity和Service都是Android四大组件之一。他俩都是Context类的子类ContextWrapper的子类,所以他俩能够算是兄弟关系吧。不过兄弟俩各有各自的本领,Activity负责用户界面的显示和交互,Service负责后台任务的处理。Activity和Service之间能够经过Intent传递数据,所以能够把Intent看做是通讯使者。
对于同一app来讲默认状况下是在同一个线程中的,main Thread (UI Thread)。
能够的。弹吐司有个条件就是得有一个Context上下文,而Service自己就是Context的子类,所以在Service里面弹吐司是彻底能够的。好比咱们在Service中完成下载任务后能够弹一个吐司通知用户。
BroadCastReceiver是Android四大组件之一,主要用于接收系统或者app发送的广播事件。
广播分两种:有序广播和无序广播。
内部通讯实现机制:经过Android系统的Binder机制实现通讯。
无序广播:彻底异步,逻辑上能够被任何广播接收者接收到。优势是效率较高。缺点是一个接收者不能将处理结果传递给下一个接收者,并没有法终止广播intent的传播。
有序广播:按照被接收者的优先级顺序,在被接收者中依次传播。好比有三个广播接收者A,B,C,优先级是A > B > C。那这个消息先传给A,再传给B,最后传给C。每一个接收者有权终止广播,好比B终止广播,C就没法接收到。此外A接收到广播后能够对结果对象进行操做,当广播传给B时,B能够从结果对象中取得A存入的数据。
在经过Context.sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler, initialCode, initialData, initialExtras)时咱们能够指定resultReceiver广播接收者,这个接收者咱们能够认为是最终接收者,一般状况下若是比他优先级更高的接收者若是没有终止广播,那么他的onReceive会被执行两次,第一次是正常的按照优先级顺序执行,第二次是做为最终接收者接收。若是比他优先级高的接收者终止了广播,那么他依然能接收到广播。
在咱们的项目中常用广播接收者接收系统通知,好比开机启动、sd挂载、低电量、外播电话、锁屏等。
若是咱们作的是播放器,那么监听到用户锁屏后咱们应该将咱们的播放之暂停等。
在清单文件中注册广播接收者称为静态注册,在代码中注册称为动态注册。静态注册的广播接收者只要app在系统中运行则一直能够接收到广播消息,动态注册的广播接收者当注册的Activity或者Service销毁了那么就接收不到广播了。
静态注册:在清单文件中进行以下配置
" v:shapes="_x0000_s1057">
动态注册:在代码中进行以下注册
a. 广播接收者的生命周期很是短暂的,在接收到广播的时候建立,onReceive()方法结束以后销毁;
b. 广播接收者中不要作一些耗时的工做,不然会弹出Application No Response错误对话框;
c. 最好也不要在广播接收者中建立子线程作耗时的工做,由于广播接收者被销毁后进程就成为了空进程,很容易被系统杀掉;
d. 耗时的较长的工做最好放在服务中完成;
在Android中若是想将本身应用的数据(通常多为数据库中的数据)提供给第三发应用,那么咱们只能经过ContentProvider来实现了。
ContentProvider是应用程序之间共享数据的接口。使用的时候首先自定义一个类继承ContentProvider,而后覆写query、insert、update、delete等方法。由于其是四大组件之一所以必须在AndroidManifest文件中进行注册。
" v:shapes="_x0000_s1055">
第三方能够经过ContentResolver来访问该Provider。
File存储
SharedPreference存储
ContentProvider存储
SQLiteDataBase存储
网络存储
ContentProvider屏蔽了数据存储的细节,内部实现对用户彻底透明,用户只须要关心操做数据的uri就能够了,ContentProvider能够实现不一样app之间共享。
Sql也有增删改查的方法,可是sql只能查询本应用下的数据库。而ContentProvider 还能够去增删改查本地文件. xml文件的读取等。
ContentProvider 内容提供者,用于对外提供数据
ContentResolver.notifyChange(uri)发出消息
ContentResolver 内容解析者,用于获取内容提供者提供的数据
ContentObserver 内容监听器,能够监听数据的改变状态
ContentResolver.registerContentObserver()监听消息。
FrameLayout
RelativeLayout
LinearLayout
AbsoluteLayout
TableLayout
android:padding和android:layout_margin的区别,其实概念很简单,padding是站在父view的角度描述问题,它规定它里面的内容必须与这个父view边界的距离。margin则是站在本身的角度描述问题,规定本身和其余(上下左右)的view之间的距离,若是同一级只有一个view,那么它的效果基本上就和padding同样了。
① 复用ConvertView
② 自定义静态类ViewHolder
③ 使用分页加载
④ 使用WeakRefrence引用ImageView对象
使用该ListView的adapter的notifyDataSetChanged()方法。该方法会使ListView从新绘制。
① 设置ListView的滚动监听器:setOnScrollListener(new OnScrollListener{….})
在监听器中有两个方法: 滚动状态发生变化的方法(onScrollStateChanged)和listView被滚动时调用的方法(onScroll)
② 在滚动状态发生改变的方法中,有三种状态:
手指按下移动的状态: SCROLL_STATE_TOUCH_SCROLL: // 触摸滑动
惯性滚动(滑翔(flgin)状态): SCROLL_STATE_FLING: // 滑翔
静止状态: SCROLL_STATE_IDLE: // 静止
对不一样的状态进行处理:
分批加载数据,只关心静止状态:关心最后一个可见的条目,若是最后一个可见条目就是数据适配器(集合)里的最后一个,此时可加载更多的数据。在每次加载的时候,计算出滚动的数量,当滚动的数量大于等于总数量的时候,能够提示用户无更多数据了。
这个固然能够的,ListView显示的每一个条目都是经过baseAdapter的getView(int position, View convertView, ViewGroup parent)来展现的,理论上咱们彻底可让每一个条目都是不一样类型的view,除此以外adapter还提供了getViewTypeCount()和getItemViewType(int position)两个方法。在getView方法中咱们能够根据不一样的viewtype加载不一样的布局文件。
能够经过ListView提供的lv.setSelection(48);方法。
一般状况下咱们不会在ScrollView中嵌套ListView,可是若是面试官非让我嵌套的话也是能够的。
在ScrollView添加一个ListView会致使listview控件显示不全,一般只会显示一条,这是由于两个控件的滚动事件冲突致使。因此须要经过listview中的item数量去计算listview的显示高度,从而使其完整展现,以下提供一个方法供你们参考。
图片的优化策略比较多。
一、处理图片的方式:
若是ListView中自定义的Item中有涉及到大量图片的,必定要对图片进行细心的处理,由于图片占的内存是ListView项中最头疼的,处理图片的方法大体有如下几种:
①、不要直接拿路径就去循环BitmapFactory.decodeFile;使用Options保存图片大小、不要加载图片到内存去。
②、对图片必定要通过边界压缩尤为是比较大的图片,若是你的图片是后台服务器处理好的那就不须要了
③、在ListView中取图片时也不要直接拿个路径去取图片,而是以WeakReference(使用WeakReference代替强引用。好比能够使用WeakReference mContextRef)、SoftReference、WeakHashMap等的来存储图片信息。
④、在getView中作图片转换时,产生的中间变量必定及时释放
二、异步加载图片基本思想:
1)、 先从内存缓存中获取图片显示(内存缓冲)
2)、获取不到的话从SD卡里获取(SD卡缓冲)
3)、都获取不到的话从网络下载图片并保存到SD卡同时加入内存并显示(视状况看是否要显示)
原理:
优化一:先从内存中加载,没有则开启线程从SD卡或网络中获取,这里注意从SD卡获取图片是放在子线程里执行的,不然快速滑屏的话会不够流畅。
优化二:于此同时,在adapter里有个busy变量,表示listview是否处于滑动状态,若是是滑动状态则仅从内存中获取图片,没有的话无需再开启线程去外存或网络获取图片。
优化三:ImageLoader里的线程使用了线程池,从而避免了过多线程频繁建立和销毁,若是每次老是new一个线程去执行这是很是不可取的,好一点的用的AsyncTask类,其实内部也是用到了线程池。在从网络获取图片时,先是将其保存到sd卡,而后再加载到内存,这么作的好处是在加载到内存时能够作个压缩处理,以减小图片所占内存。
图片错位问题的本质源于咱们的listview使用了缓存convertView,假设一种场景,一个listview一屏显示九个item,那么在拉出第十个item的时候,事实上该item是重复使用了第一个item,也就是说在第一个item从网络中下载图片并最终要显示的时候,其实该item已经不在当前显示区域内了,此时显示的后果将可能在第十个item上输出图像,这就致使了图片错位的问题。因此解决之道在于可见则显示,不可见则不显示。
Java中对象的引用分为四种级别,这四种级别由高到低依次为:强引用、软引用、弱引用和虚引用。
强引用(StrongReference)
这个就很少说,咱们写代码每天在用的就是强引用。若是一个对象被被人拥有强引用,那么垃圾回收器毫不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具备强引用的对象来解决内存不足问题。
Java的对象是位于heap中的,heap中对象有强可及对象、软可及对象、弱可及对象、虚可及对象和不可到达对象。应用的强弱顺序是强、软、弱、和虚。对于对象是属于哪一种可及的对象,由他的最强的引用决定。以下代码:
softRef=new SoftReference(abc); //2 WeakReference weakRef = new WeakReference(abc); //3 abc=null; //4 softRef.clear();//5 " v:shapes="_x0000_s1048">
第一行在heap堆中建立内容为“abc”的对象,并创建abc到该对象的强引用,该对象是强可及的。
第二行和第三行分别创建对heap中对象的软引用和弱引用,此时heap中的abc对象已经有3个引用,显然此时abc对象还是强可及的。
第四行以后heap中对象再也不是强可及的,变成软可及的。
第五行执行以后变成弱可及的。
软引用(SoftReference)
若是一个对象只具备软引用,那么若是内存空间足够,垃圾回收器就不会回收它,若是内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就能够被程序使用。软引用可用来实现内存敏感的高速缓存。
软引用能够和一个引用队列(ReferenceQueue)联合使用,若是软引用所引用的对象被垃圾回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。
软引用是主要用于内存敏感的高速缓存。在jvm报告内存不足以前会清除全部的软引用,这样以来gc就有可能收集软可及的对象,可能解决内存吃紧问题,避免内存溢出。何时会被收集取决于gc的算法和gc运行时可用内存的大小。当gc决定要收集软引用时执行如下过程,以上面的softRef为例:
1 首先将softRef的referent(abc)设置为null,再也不引用heap中的new String("abc")对象。
2 将heap中的new String("abc")对象设置为可结束的(finalizable)。
3 当heap中的new String("abc")对象的finalize()方法被运行并且该对象占用的内存被释放, softRef被添加到它的ReferenceQueue(若是有的话)中。
注意:对ReferenceQueue软引用和弱引用能够有可无,可是虚引用必须有。
被 Soft Reference 指到的对象,即便没有任何 Direct Reference,也不会被清除。一直要到 JVM 内存不足且没有Direct Reference 时才会清除,SoftReference 是用来设计 object-cache 之用的。如此一来 SoftReference 不但能够把对象 cache 起来,也不会形成内存不足的错误 (OutOfMemoryError)。
弱引用(WeakReference)
若是一个对象只具备弱引用,那该类就是无关紧要的对象,由于只要该对象被gc扫描到了随时都会把它干掉。弱引用与软引用的区别在于:只具备弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程当中,一旦发现了只具备弱引用的对象,无论当前内存空间足够与否,都会回收它的内存。不过,因为垃圾回收器是一个优先级很低的线程, 所以不必定会很快发现那些只具备弱引用的对象。
弱引用能够和一个引用队列(ReferenceQueue)联合使用,若是弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。
虚引用(PhantomReference)
"虚引用"顾名思义,就是形同虚设,与其余几种引用都不一样,虚引用并不会决定对象的生命周期。若是一个对象仅持有虚引用,那么它就和没有任何引用同样,在任什么时候候均可能被垃圾回收。虚引用主要用来跟踪对象被垃圾回收的活动。
虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,若是发现它还有虚引用,就会在回收对象的内存以前,把这个虚引用加入到与之关联的引用队列中。程序能够经过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。程序若是发现某个虚引用已经被加入到引用队列,那么就能够在所引用的对象的内存被回收以前采起必要的行动。
创建虚引用以后经过get方法返回结果始终为null,经过源代码你会发现,虚引用通向会把引用的对象写进referent,只是get方法返回结果为null。先看一下和gc交互的过程再说一下他的做用。
1 不把referent设置为null, 直接把heap中的new String("abc")对象设置为可结束的(finalizable)。
2 与软引用和弱引用不一样, 先把PhantomRefrence对象添加到它的ReferenceQueue中.而后在释放虚可及的对象。
当咱们的Java须要调用C语言的时候能够经过JNI的方式,Java Native Interface。Android提供了对JNI的支持,所以咱们在Android中能够使用JNI调用C语言。在Android开发目录的libs目录下添加xxx.so文件,不过xxx.so文件须要放在对应的CPU架构名目录下,好比armeabi,x86等。
在Java代码须要经过System.loadLibrary(libName);加载so文件。同时C语言中的方法在java中必须以native关键字来声明。普通Java方法调用这个native方法接口,虚拟机内部自动调用so文件中对应的方法。
1.NDK 是一系列工具的集合
NDK 提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so 和java 应用一块儿打包成apk。NDK 集成了交叉编译器,并提供了相应的mk 文件隔离CPU、平台、ABI 等差别,开发人员只须要简单修改mk 文件(指出“哪些文件须要编译”、“编译特性要求”等),就能够建立出so。
2.NDK 提供了一份稳定、功能有限的API 头文件声明
Google 明确声明该API 是稳定的,在后续全部版本中都稳定支持当前发布的API。从该版本的NDK 中看出,这些API 支持的功能很是有限,包含有:C 标准库(libc)、标准数学库(libm)、压缩库(libz)、Log 库(liblog)。
JNIEnv *env, jobject obj
第一个是指向虚拟机对象的指针,是一个二级指针。里面封装了不少方法和中间变量供咱们使用。
第二个表明着调用该方法的Java对象的C语言表示。
Android提供了org.apache.http.HttpClientConnection和java.net.HttpURLConnection两个链接网络对象。使用哪一个都行,具体要看企业领导的要求了。
除此以外通常我比较喜欢使用xUtils中的HttpUtils功能,该模块底层使用的就是org.apache.http.client.HttpClient,使用起来很是方便。
在Android中内置了JSON的解析API,在org.json包中包含了以下几个类:JSONArray、JSONObject、JSONStringer、JSONTokener和一个异常类JSONException。
一、JSON解析步骤
1)、读取网络文件数据并转为一个json字符串
InputStream in = conn.getInputStream();
String jsonStr = DataUtil.Stream2String(in);//将流转换成字符串的工具类
2)、将字符串传入相应的JSON构造函数中
①、经过构造函数将json字符串转换成json对象
JSONObject jsonObject = new JSONObject(jsonStr);
②、经过构造函数将json字符串转换成json数组:
JSONArray array = new JSONArray(jsonStr);
3)、解析出JSON中的数据信息:
①、从json对象中获取你所须要的键所对应的值
JSONObject json=jsonObject.getJSONObject("weatherinfo");
String city = json.getString("city");
String temp = json.getString("temp")
②、遍历JSON数组,获取数组中每个json对象,同时能够获取json对象中键对应的值
for (int i = 0; i < array.length(); i++) {
JSONObject obj = array.getJSONObject(i);
String title=obj.getString("title");
String description=obj.getString("description");
}
二、生成JSON对象和数组
1)生成JSON:
方法一、建立一个map,经过构造方法将map转换成json对象
Map<String, Object> map = new HashMap<String, Object>();
map.put("name", "zhangsan");
map.put("age", 24);
JSONObject json = new JSONObject(map);
方法二、建立一个json对象,经过put方法添加数据
JSONObject json=new JSONObject();
json.put("name", "zhangsan");
json.put("age", 24);
2)生成JSON数组:
建立一个list,经过构造方法将list转换成json对象
Map<String, Object> map1 = new HashMap<String, Object>();
map1.put("name", "zhangsan");
map1.put("age", 24);
Map<String, Object> map2 = new HashMap<String, Object>();
map2.put("name", "lisi");
map2.put("age", 25);
List<Map<String, Object>> list=new ArrayList<Map<String,Object>>();
list.add(map1);
list.add(map2);
JSONArray array=new JSONArray(list);
System.out.println(array.toString());
Android为咱们提供了原生的XML解析和生成支持。
一、XML解析
获取解析器: Xml.newPullParser()
设置输入流: setInput()
获取当前事件类型: getEventType()
解析下一个事件, 获取类型: next()
获取标签名: getName()
获取属性值: getAttributeValue()
获取下一个文本: nextText()
获取当前文本: getText()
5种事件类型: START_DOCUMENT, END_DOCUMENT, START_TAG, END_TAG, TEXT
示例代码:
public List<Person> getPersons(InuptStream in){
XmlPullParser parser=Xml.newPullParser();//获取解析器
parser.setInput(in,"utf-8");
for(int type=){ //循环解析
}
}
二、XML生成
获取生成工具: Xml.newSerializer()
设置输出流: setOutput()
开始文档: startDocument()
结束文档: endDocument()
开始标签: startTag()
结束标签: endTag()
属性: attribute()
文本: text()
示例代码:
XmlSerializer serial=Xml.newSerializer();//获取xml序列化工具
serial.setOuput(put,"utf-8");
serial.startDocument("utf-8",true);
serial.startTag(null,"persons");
for(Person p:persons){
serial.startTag(null,"persons");
serial.attribute(null,"id",p.getId().toString());
serial.startTag(null,"name");
serial.attribute(null,"name",p.getName().toString());
serial.endTag(null,"name");
serial.startTag(null,"age");
serial.attribute(null,"age",p.getAge().toString());
serial.endTag(null,"age");
serial.endTag(null,"persons");
}
能够经过BitmapFactory.decodeStream(inputStream);方法将图片转换为bitmap,而后经过
imageView.setImageBitmap(bitmap);将该图片设置到ImageView中。这是原生的方法,还能够使用第三方开源的工具来实现,好比使用SmartImageView做为ImageView控件,而后直接设置一个url地址便可。也能够使用xUtils中的BitmapUtils工具。
除了使用Android提供的MediaPlayer和VideoView外一般还能够使用第三方开源万能播放器,VitamioPlayer。该播放器兼容性好,支持几乎全部主流视频格式。
Intent能够传递的数据类型很是的丰富,java的基本数据类型和String以及他们的数组形式均可以,除此以外还能够传递实现了Serializable和Parcelable接口的对象。
1.在使用内存的时候,Parcelable 类比Serializable性能高,因此推荐使用Parcelable类。
2.Serializable在序列化的时候会产生大量的临时变量,从而引发频繁的GC。
3.Parcelable不能使用在要将数据存储在磁盘上的状况。尽管Serializable效率低点,但在这种状况下,仍是建议你用Serializable 。
实现:
1 Serializable 的实现,只须要继承Serializable 便可。这只是给对象打了一个标记,系统会自动将其序列化。
2 Parcelabel 的实现,须要在类中添加一个静态成员变量 CREATOR,这个变量须要继承 Parcelable.Creator 接口。
CREATOR = new Parcelable.Creator() { public MyParcelable createFromParcel(Parcel in) { return new MyParcelable(in); } public MyParcelable[] newArray(int size) { return new MyParcelable[size]; } }; private MyParcelable(Parcel in) { mData = in.readInt(); } } " v:shapes="_x0000_s1054">
Android 中经过 Intent 对象来表示一条消息,一个 Intent 对象不只包含有这个消息的目的地,还能够包含消息的内容,这比如一封 Email,其中不只应该包含收件地址,还能够包含具体的内容。对于一个 Intent 对象,消息“目的地”是必须的,而内容则是可选项。
经过Intent 能够实现各类系统组件的调用与激活.
IntentFilter: 能够理解为邮局或者是一个信笺的分拣系统…
这个分拣系统经过3个参数来识别
Action: 动做 view
Data: 数据uri uri
Category : 而外的附加信息
Action 匹配
Action 是一个用户定义的字符串,用于描述一个 Android 应用程序组件,一个 IntentFilter 能够包含多个 Action。在 AndroidManifest.xml 的 Activity 定义时能够在其 <intent-filter >节点指定一个 Action 列表用于标示 Activity 所能接受的“动做”,例如:
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<action android:name="cn.itheima.action" />
……
</intent-filter>
若是咱们在启动一个 Activity 时使用这样的 Intent 对象:
Intent intent =new Intent();
intent.setAction("cn.itheima.action");
那么全部的 Action 列表中包含了“cn.itheima”的 Activity 都将会匹配成功。
Android 预约义了一系列的 Action 分别表示特定的系统动做。这些 Action 经过常量的方式定义在 android.content. Intent中,以“ACTION_”开头。咱们能够在 Android 提供的文档中找到它们的详细说明。
URI 数据匹配
一个 Intent 能够经过 URI 携带外部数据给目标组件。在 <intent-filter >节点中,经过 <data/>节点匹配外部数据。
mimeType 属性指定携带外部数据的数据类型,scheme 指定协议,host、port、path 指定数据的位置、端口、和路径。以下:
<data android:mimeType="mimeType" android:scheme="scheme"
android:host="host" android:port="port" android:path="path"/>
电话的uri tel: 12345
http://www.baidu.com
本身定义的uri itcast://cn.itcast/person/10
若是在 Intent Filter 中指定了这些属性,那么只有全部的属性都匹配成功时 URI 数据匹配才会成功。
Category 类别匹配
<intent-filter >节点中能够为组件定义一个 Category 类别列表,当 Intent 中包含这个列表的全部项目时 Category 类别匹配才会成功。
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT,textMessage);
sendIntent.setType(HTTP.PLAIN_TEXT_TYEP);//"text/plain" MIME type
content.startActivity(sendIntent);
当Fragment跟Activity绑定以后,在Fragment中能够直接经过getActivity()方法获取到其绑定的Activity对象,这样就能够调用Activity的方法了。在Activity中能够经过以下方法获取到Fragment实例
获取到Fragment以后就能够调用Fragment的方法。也就实现了通讯功能。
Fragment自己并无replace和add方法,这里的理解应该为使用FragmentManager的replace和add两种方法切换Fragment时有什么不一样。
咱们常用的一个架构就是经过RadioGroup切换Fragment,每一个Fragment就是一个功能模块。
实现这个功能能够经过replace和add两种方法。
Fragment的容器一个FrameLayout,add的时候是把全部的Fragment一层一层的叠加到了FrameLayout上了,而replace的话首先将该容器中的其余Fragment去除掉而后将当前Fragment添加到容器中。
一个Fragment容器中只能添加一个Fragment种类,若是屡次添加则会报异常,致使程序终止,而replace则无所谓,随便切换。
由于经过add的方法添加的Fragment,每一个Fragment只能添加一次,所以若是要想达到切换效果须要经过Fragment的的hide和show方法结合者使用。将要显示的show出来,将其余hide起来。这个过程Fragment的生命周期没有变化。
经过replace切换Fragment,每次都会执行上一个Fragment的onDestroyView,新Fragment的onCreateView、onStart、onResume方法。
基于以上不一样的特色咱们在使用的使用必定要结合着生命周期操做咱们的视图和数据。
Fragment的事物管理器内部维持了一个双向链表结构,该结构能够记录咱们每次add的Fragment和replace的Fragment,而后当咱们点击back按钮的时候会自动帮咱们实现退栈操做。
除此以外由于咱们要使用FragmentManger用的是FragmentActivity,所以FragmentActivity的onBackPress方法一定从新覆写了。打开看一下,发现确实如此。
= 0) { //从后退栈中取出当前记录对象 BackStackRecord bss = mBackStack.get(index); if (name != null && name.equals(bss.getName())) { break; } if (id >= 0 && id == bss.mIndex) { break; } index--; } " v:shapes="文本框_x0020_119">
一款App流畅与否安装在本身的真机里,玩几天就能有个大概的感性认识。不过经过专业的分析工具能够使咱们更好的分析咱们的应用。
若是不考虑使用其余第三方性能分析工具的话,咱们能够直接使用ddms中的工具,其实ddms工具已经很是的强大了。ddms中有traceview、heap、allocation tracker等工具均可以帮助咱们分析应用的方法执行时间效率和内存使用状况。
traceview工具在本文章中已经有详细的介绍,所以这里就再也不赘述。
heap
heap工具能够帮助咱们检查代码中是否存在会形成内存泄漏的地方。
用heap监测应用进程使用内存状况的步骤以下:
1. 启动eclipse后,切换到DDMS透视图,并确认Devices视图、Heap视图都是打开的;
2. 点击选中想要监测的进程,好比system_process进程;
3. 点击选中Devices视图界面中最上方一排图标中的“Update Heap”图标;
6. 点击Heap视图中的“Cause GC”按钮;
7. 此时在Heap视图中就会看到当前选中的进程的内存使用量的详细状况。
说明:
a) 点击“Cause GC”按钮至关于向虚拟机请求了一次gc操做;
b) 当内存使用信息第一次显示之后,无须再不断的点击“Cause GC”,Heap视图界面会定时刷新,在对应用的不断的操做过程当中就能够看到内存使用的变化;
c) 内存使用信息的各项参数根据名称便可知道其意思,在此再也不赘述。
如何才能知道咱们的程序是否有内存泄漏的可能性呢。这里须要注意一个值:Heap视图中部有一个Type叫作data object,即数据对象,也就是咱们的程序中大量存在的类类型的对象。在data object一行中有一列是“Total Size”,其值就是当前进程中全部Java数据对象的内存总量,通常状况下,这个值的大小决定了是否会有内存泄漏。能够这样判断:
a) 不断的操做当前应用,同时注意观察data object的Total Size值;
b) 正常状况下Total Size值都会稳定在一个有限的范围内,也就是说因为程序中的的代码良好,没有形成对象不被垃圾回收的状况,因此说虽然咱们不断的操做会不断的生成不少对象,而在虚拟机不断的进行GC的过程当中,这些对象都被回收了,内存占用量会会落到一个稳定的水平;
c) 反之若是代码中存在没有释放对象引用的状况,则data object的Total Size值在每次GC后不会有明显的回落,随着操做次数的增多Total Size的值会愈来愈大,
直到到达一个上限后致使进程被kill掉。
d) 此处以system_process进程为例,在个人测试环境中system_process进程所占用的内存的data object的Total Size正常状况下会稳定在2.2~2.8之间,而当其值超过3.55后进程就会被kill。
总之,使用DDMS的Heap视图工具能够很方便的确认咱们的程序是否存在内存泄漏的可能性。
allocation tracker
运行DDMS,只需简单的选择应用进程并单击Allocation tracker标签,就会打开一个新的窗口,单击“Start Tracing”按钮;
而后,让应用运行你想分析的代码。运行完毕后,单击“Get Allocations”按钮,一个已分配对象的列表就会出现第一个表格中。
单击第一个表格中的任何一项,在表格二中就会出现致使该内存分配的栈跟踪信息。经过allocation tracker,不只知道分配了哪类对象,还能够知道在哪一个线程、哪一个类、哪一个文件的哪一行。
Android的虚拟机是基于寄存器的Dalvik,它的最大堆大小通常是16M,有的机器为24M。所以咱们所能利用的内存空间是有限的。若是咱们的内存占用超过了必定的水平就会出现OutOfMemory的错误。
内存溢出的几点缘由:
程序代码的问题,长期保持某些资源,如Context、Cursor、IO流的引用,资源得不到释放形成内存泄露。
保存了多个耗用内存过大的对象(如Bitmap、XML文件),形成内存超出限制。
static是Java中的一个关键字,当用它来修饰成员变量时,那么该变量就属于该类,而不是该类的实例。因此用static修饰的变量,它的生命周期是很长的,若是用它来引用一些资源耗费过多的实例(Context的状况最多),这时就要谨慎对待了。
public class ClassName {
private static Context mContext;
//省略
}
以上的代码是很危险的,若是将Activity赋值到mContext的话。那么即便该Activity已经onDestroy,可是因为仍有对象保存它的引用,所以该Activity依然不会被释放。
咱们举Android文档中的一个例子。
sBackground是一个静态的变量,可是咱们发现,咱们并无显式的保存Contex的引用,可是,当Drawable与View链接以后,Drawable就将View设置为一个回调,因为View中是包含Context的引用的,因此,实际上咱们依然保存了Context的引用。这个引用链以下:
Drawable->TextView->Context
因此,最终该Context也没有获得释放,发生了内存泄露。
针对static的解决方案
① 应该尽可能避免static成员变量引用资源耗费过多的实例,好比Context。
② Context尽可能使用ApplicationContext,由于Application的Context的生命周期比较长,引用它不会出现内存泄露的问题。
③ 使用WeakReference代替强引用。好比能够使用WeakReference<Context> mContextRef;
线程产生内存泄露的主要缘由在于线程生命周期的不可控。咱们来考虑下面一段代码。
这段代码很日常也很简单,是咱们常用的形式。咱们思考一个问题:假设MyThread的run函数是一个很费时的操做,当咱们开启该线程后,将设备的横屏变为了竖屏,一 般状况下当屏幕转换时会从新建立Activity,按照咱们的想法,老的Activity应该会被销毁才对,然而事实上并不是如此。
因为咱们的线程是Activity的内部类,因此MyThread中保存了Activity的一个引用,当MyThread的run函数没有结束时,MyThread是不会被销毁的,所以它所引用的老的Activity也不会被销毁,所以就出现了内存泄露的问题。
有些人喜欢用Android提供的AsyncTask,但事实上AsyncTask的问题更加严重,Thread只有在run函数不结束时才出现这种内存泄露问题,然而AsyncTask内部的实现机制是运用了ThreadPoolExcutor,该类产生的Thread对象的生命周期是不肯定的,是应用程序没法控制的,所以若是AsyncTask做为Activity的内部类,就更容易出现内存泄露的问题。
针对这种线程致使的内存泄露问题的解决方案:
第1、将线程的内部类,改成静态内部类(由于非静态内部类拥有外部类对象的强引用,而静态类则不拥有)。
第2、在线程内部采用弱引用保存Context引用。
想要避免OOM异常首先咱们要知道什么状况下会致使OOM异常。
Android 中用bitmap时很容易内存溢出,好比报以下错误:Java.lang.OutOfMemoryError : bitmap size exceeds VM budget。
解决方法:
方法1: 等比例缩小图片
以上代码能够优化内存溢出,但它只是改变图片大小,并不能完全解决内存溢出。
方法2:对图片采用软引用,及时地进行recyle()操做
bitmap = new SoftReference(pBitmap); if(bitmap != null){ if(bitmap.get() != null && !bitmap.get().isRecycled()){ bitmap.get().recycle(); bitmap = null; } } " v:shapes="_x0000_s1044">
有时候咱们会发现这样的问题,横竖屏切换N次后 OOM了。
这种问题没有固定的解决方法,可是咱们能够从如下几个方面下手分析。
一、看看页面布局当中有没有大的图片,好比背景图之类的。
去除xml中相关设置,改在程序中设置背景图(放在onCreate()方法中):
在Activity destory时注意,drawable.setCallback(null); 防止Activity得不到及时的释放。
二、跟上面方法类似,直接把xml配置文件加载成view 再放到一个容器里,而后直接调用 this.setContentView(View view);方法,避免xml的重复加载。
三、 在页面切换时尽量少地重复使用一些代码
好比:重复调用数据库,反复使用某些对象等等......
常见的内存使用不当的状况
程序中常常会进行查询数据库的操做,可是常常会有使用完毕Cursor后没有关闭的状况。若是咱们的查询结果集比较小,对内存的消耗不容易被发现,只有在常时间大量操做的状况下才会出现内存问题,这样就会给之后的测试和问题排查带来困难和风险。
在使用ListView的时候一般会使用Adapter,那么咱们应该尽量的使用ConvertView。
有时咱们会手工的操做Bitmap对象,若是一个Bitmap对象比较占内存,当它再也不被使用的时候,能够调用Bitmap.recycle()方法回收此对象的像素所占用的内存,但这不是必须的,视状况而定。
Android应用程序中最典型的须要注意释放资源的状况是在Activity的生命周期中,在onPause()、onStop()、 onDestroy()方法中须要适当的释放资源的状况。
一、自定义一个Application,好比叫MyApplication继承Application实现UncaughtExceptionHandler。
二、覆写UncaughtExceptionHandler的onCreate和uncaughtException方法。
注意:上面的代码只是简单的将异常打印出来。
在onCreate方法中咱们给Thread类设置默认异常处理handler,若是这句代码不执行则一切都是白搭。
在uncaughtException方法中咱们必须新开辟个线程进行咱们异常的收集工做,而后将系统给杀死。
三、在AndroidManifest中配置该Application
四、blog分享
关于异常数据的收集在网上有一篇不错的blog能够推荐给你们。
http://blog.csdn.net/jdsjlzx/article/details/7606423
名词解释:
分辨率:eg:480*800,1280*720。表示物理屏幕区域内像素点的总和。(切记:跟屏幕适配没有任何关系)
由于咱们既能够把1280*720的分辨率作到4.0的手机上面。我也能够把1280*720的分辨率作到5.0英寸的手机上面,若是分辨率相同,手机屏幕越小清晰。
px(pix):像素,就是屏幕中最小的一个显示单元
dpi(像素密度):即每英寸屏幕所拥有的像素数,像素密度越大,显示画面细节就越丰富。
计算公式:像素密度=√{(长度像素数^2+宽度像素数^2)}/ 屏幕尺寸
注:屏幕尺寸单位为英寸 例:分辨率为1280*720 屏幕宽度为6英寸 计算所得像素密度约等于245,屏幕尺寸指屏幕对角线的长度。
在Android手机中dpi分类:
|
Resources for low-density (ldpi) screens (~120dpi). |
|
Resources for medium-density (mdpi) screens (~160dpi). (This is the baseline density.) |
|
Resources for high-density (hdpi) screens (~240dpi). |
|
Resources for extra high-density (xhdpi) screens (~320dpi). |
在咱们的Android工程目录中有以下drawable-*dpi目录,这些目录是用来适配不一样分辨率手机的。
Android应用在查找图片资源时会根据其分辨率自动从不一样的文件目录下查找(这自己就是Android系统的适配策略),若是在低分辨的文件目录中好比drawable-mdpi中没有图片资源,其余目录中都有,当咱们将该应用部署到mdpi分辨率的手机上时,那么该应用会查找分辨率较高目录下的资源文件,若是较高分辨率目录下也没有资源则只好找较低目录中的资源了。
常见手机屏幕像素及对应分别率级别:
ldpi 320*240
mdpi 480*320
hdpi 800*480
xhdpi 1280*720
xxhdpi 1920*1080
dp和px之间的简单换算关系:
ldpi的手机 1dp=0.75px
mdpi的手机 1dp=1.0px
hdpi的手机 1dp=1.5px
xhdpi的手机 1dp=2.0px
xxhdpi的手机 1dp=3.0px
:根据上面的描述咱们得出以下结论,对于mdpi的手机,咱们的布局经过dp单位能够达到适配效果。
跟drawable目录相似的,在Android工程的res目录下有values目录,这个是默认的目录,同时为了适配不一样尺寸手机咱们能够建立一个values-1280x720的文件夹,同时将dimens.xml文件拷贝到该目录下。
在dimens.xml中定义一个尺寸,以下图所示。
在values-1280x720目录中的dimens.xml中定义一样的尺寸名称,可是使用不一样的尺寸,以下图所示。
当咱们在布局文件中使用长或者宽度单位时,好比下图所示,应该使用@dimen/width来灵活的定义宽度。
:在values-1280x720中,中间的是大写字母X的小写形式x,而不是加减乘除的乘号。若是咱们在values-1280x720中放置了dimens常量,必定记得也将该常量的对应值在values目录下的dimens.xml中放一份,由于该文件是默认配置,当用户的手机不是1280*720的状况下系统应用使用的是默认values目录中的dimens.xml。
跟values同样,在Android工程目录中layout目录也支持相似values目录同样的适配,在layout中咱们能够针对不一样手机的分辨率制定不一样的布局,以下图所示。
为了演示用java代码控制适配的效果,所以假设有这样的需求,让一个TextView控件的宽和高分别为屏幕的宽和高的一半。
咱们新建立一个Android工程,修改main_activity.xml,布局文件清单以下:
" v:shapes="_x0000_s1040">
" v:shapes="_x0000_s1039">
在MainActivity.java类中完成用java代码控制TextView的布局效果,其代码清单以下:
其中Constant类是一个常量类,很简单,只有两个常量用来记录屏幕的宽和高,其代码清单以下:
在控件中使用属性android:layout_weight="1"可以起到适配效果,可是该属性的使用有以下规则:
一、只能用在线性控件中,好比LinearLayout。
二、竖直方向上使用权重的控件高度必须为0dp(Google官方的推荐用法)
三、水平方向上使用权重的控件宽度必须为0dp(Google官方的推荐用法)
手机自适应主要分为两种状况:横屏和竖屏的切换,以及分辨率大小的不一样。
一、Android应用程序支持横竖屏幕的切换,Android中每次屏幕的切换动会重启Activity,因此应该在Activity销毁(执行onPause()方法和onDestroy()方法)前保存当前活动的状态;在Activity再次建立的时候载入配置,那样,进行中的游戏就不会自动重启了!有的程序适合从竖屏切换到横屏,或者反过来,这个时候怎么办呢?能够在配置Activity的地方进行以下的配置android:screenOrientation="portrait"(landscape是横向,portrait是纵向)。这样就能够保证是竖屏老是竖屏了。
二、而有的程序是适合横竖屏切换的。如何处理呢?首先要在配置Activity的时候进行以下的配置:
android:configChanges="keyboardHidden|orientation",另外须要重写Activity的onConfigurationChanged方法。实现方式以下:
对于分辨率问题,官方给的解决办法是建立不一样的layout文件夹,这就须要对每种分辨率的手机都要写一个布局文件,虽然看似解决了分辨率的问题,可是若是其中一处或多处有修改了,就要每一个布局文件都要作出修改,这样就形成很大的麻烦。那么能够经过如下几种方式解决:
一)使用layout_weight
目前最为推荐的Android多屏幕自适应解决方案。
该属性的做用是决定控件在其父布局中的显示权重,通常用于线性布局中。其值越小,则对应的layout_width或layout_height的优先级就越高(通常到100做用就不太明显了);通常横向布局中,决定的是layout_width的优先级;纵向布局中,决定的是layout_height的优先级。
传统的layout_weight使用方法是将当前控件的layout_width和layout_height都设置成fill_parent,这样就能够把控件的显示比例彻底交给layout_weight;这样使用的话,就出现了layout_weight越小,显示比例越大的状况(即权重越大,显示所占的效果越小)。不过对于2个控件还好,若是控件过多,且显示比例也不相同的时候,控制起来就比较麻烦了,毕竟反比不是那么好肯定的。因而就有了如今最为流行的0px设值法。看似让人难以理解的layout_height=0px的写法,结合layout_weight,却能够使控件成正比例显示,轻松解决了当前Android开发最为头疼的碎片化问题之一。
二)清单文件配置:【不建议使用这种方式,须要对不一样的界面写不一样的布局】
须要在AndroidManifest.xml文件的<manifest>元素以下添加子元素
<supports-screensandroid:largeScreens="true"
android:normalScreens="true"
android:anyDensity="true"
android:smallScreens="true"
android:xlargeScreens="true">
</supports-screens>
以上是为咱们的屏幕设置多分辨率支持(更准确的说是适配大、中、小三种密度)。
Android:anyDensity="true",这一句对整个的屏幕都起着十分重要的做用,值为true,咱们的应用程序当安装在不一样密度的手机上时,程序会分别加载hdpi,mdpi,ldpi文件夹中的资源。相反,若是值设置为false,即便咱们在hdpi,mdpi,ldpi,xdpi文件夹下拥有同一种资源,那么应用也不会自动地去相应文件夹下寻找资源。而是会在大密度和小密度手机上加载中密度mdpi文件中的资源。
有时候会根据须要在代码中动态地设置某个值,能够在代码中为这几种密度分别设置偏移量,可是这种方法最好不要使用,最好的方式是在xml文件中不一样密度的手机进行分别设置。这里地图的偏移量能够在values-xpdi,values-hpdi,values-mdpi,values-ldpi四种文件夹中的dimens.xml文件进行设置。
三)、其余:
说明:
在不一样分辨率的手机模拟器下,控件显示的位置会稍有不一样
经过在layout中定义的布局设置的参数,使用dp(dip),会根据不一样的屏幕分辨率进行适配
可是在代码中的各个参数值,都是使用的像素(px)为单位的
技巧:
一、尽可能使用线性布局,相对布局,若是屏幕放不下了,能够使用ScrollView(能够上下拖动)
ScrowView使用的注意:
在不一样的屏幕上显示内容不一样的状况,其实这个问题咱们每每是用滚动视图来解决的,也就是ScrowView;须要注意的是ScrowView中使用layout_weight是无效的,既然使用ScrowView了,就把它里面的控件的大小都设成固定的吧。
二、指定宽高的时候,采用dip的单位,dp单位动态匹配
三、因为android代码中写的单位都是像素,全部须要经过工具类进行转化
四、尽可能使用9-patch图,能够自动的依据图片上面显示的内容被拉伸和收缩。其中在编辑的时候,灰色区域是被拉伸的,上下两个点控制水平方向的拉伸,左右两点控制垂直方向的拉伸
dp:是dip的简写,指密度无关的像素。
指一个抽象意义上的像素,程序用它来定义界面元素。一个与密度无关的,在逻辑尺寸上,与一个位于像素密度为160dpi的屏幕上的像素是一致的。要把密度无关像素转换为屏幕像素,能够用这样一个简单的公式:pixels=dips*(density/160)。举个例子,在DPI为240的屏幕上,1个DIP等于1.5个物理像素。
布局时最好使用dp来定义咱们程序的界面,由于这样能够保证咱们的UI在各类分辨率的屏幕上均可以正常显示。
①aidl是Android interface definition Language 的英文缩写,意思Android 接口定义语言。
②使用aidl能够帮助咱们发布以及调用远程服务,实现跨进程通讯。
③将服务的aidl放到对应的src目录,工程的gen目录会生成相应的接口类
咱们经过bindService(Intent,ServiceConnect,int)方法绑定远程服务,在bindService中有一个ServiceConnec接口,咱们须要覆写该类的onServiceConnected(ComponentName,IBinder)方法,这个方法的第二个参数IBinder对象其实就是已经在aidl中定义的接口,所以咱们能够将IBinder对象强制转换为aidl中的接口类。
咱们经过IBinder获取到的对象(也就是aidl文件生成的接口)实际上是系统产生的代理对象,该代理对象既能够跟咱们的进程通讯,又能够跟远程进程通讯,做为一个中间的角色实现了进程间通讯。
自定义控件能够分为两种自定义组合控件和自定义view。
自定义组合控件
自定义组合控件就是把多个控件作为一个总体看待、处理。这样的好处不只能够减轻xml的代码量,也提升了代码的复用性。
在手机卫士项目中咱们第一次接触了自定义组合控件。
1. 声明一个View 对象,继承相对布局,或者线性布局或者其余的ViewGroup。
2. 在自定义的View 对象里面重写它的构造方法,在构造方法里面就把布局都初始化完毕。
3. 根据业务需求添加一些api 方法,扩展自定义的组合控件;
4. 但愿在布局文件里面能够自定义一些属性。
5. 声明自定义属性的命名空间。
xmlns:itheima="http://schemas.android.com/apk/res/com.itheima.mobilesafe"
6. 在res 目录下的values 目录下建立attrs.xml 的文件声明咱们写的属性。
7. 在布局文件中写自定义的属性。
8. 使用这些定义的属性。自定义View 对象的构造方法里面有一个带两个参数的构造方法布局文件里面定义的属性都放在AttributeSet attrs,获取那些定义的属性。
自定义view
自定义View首先要实现一个继承自View的类。添加类的构造方法,一般是三个构造方法,不过从Android5.0开始构造方法已经添加到4个了。override父类的方法,如onDraw,(onMeasure)等。若是自定义的View有本身的属性,须要在values下创建attrs.xml文件,在其中定义属性,同时代码也要作修改。
blog分享:http://blog.csdn.net/lmj623565791/article/details/24252901
整个View树的绘图流程是在ViewRoot.java类(该类位于Android源码下面:D:\AndroidSource_GB\AndroidSource_GB\frameworks\base\core\java\android\view)的performTraversals()函数展开的,该函数作的执行过程可简单概况为根据以前设置的状态,判断是否须要从新计算视图大小(measure)、是否从新须要安置视图的位置(layout)、以及是否须要重绘 (draw),其框架过程以下:
主要做用:为整个View树计算实际的大小,即设置实际的高(对应属性:mMeasuredHeight)和宽(对应属性:
mMeasureWidth),每一个View的控件的实际宽高都是由父视图和自己视图决定的。
具体的调用链以下: ViewRoot根对象的属性mView(其类型通常为ViewGroup类型)调用measure()方法去计算View树的大小,回调View/ViewGroup对象的onMeasure()方法,该方法实现的功能以下:
一、设置本View视图的最终大小,该功能的实现经过调用setMeasuredDimension()方法去设置实际的高(对应属性:mMeasuredHeight)和宽(对应属性:mMeasureWidth)。
2 、若是该View对象是个ViewGroup类型,须要重写该onMeasure()方法,对其子视图进行遍历的measure()过程。对每一个子视图的measure()过程,是经过调用父类ViewGroup.java类里的measureChildWithMargins()方法去实现,该方法内部只是简单地调用了View对象的measure()方法。
主要做用:为将整个根据子视图的大小以及布局参数将View树放到合适的位置上。
具体的调用链以下:
一、layout方法会设置该View视图位于父视图的坐标轴,即mLeft,mTop,mLeft,mBottom(调用setFrame()函数去实现)接下来回调onLayout()方法(若是该View是ViewGroup对象,须要实现该方法,对每一个子视图进行布局)。
二、若是该View是个ViewGroup类型,须要遍历每一个子视图chiildView,调用该子视图的layout()方法去设置它的坐标值。
由ViewRoot对象的performTraversals()方法调用draw()方法发起绘制该View树,值得注意的是每次发起绘图时,并不会从新绘制每一个View树的视图,而只会从新绘制那些“须要重绘”的视图,View类内部变量包含了一个标志位DRAWN,当该视图须要重绘时,就会为该View添加该标志位。
调用流程 :
1 、绘制该View的背景
2 、为显示渐变框作一些准备操做(大多数状况下,不须要改渐变框)
三、调用onDraw()方法绘制视图自己(每一个View都须要重载该方法,ViewGroup不须要实现该方法)
四、调用dispatchDraw ()方法绘制子视图(若是该View类型不为ViewGroup,即不包含子视图,不须要重载该方法)
值得说明的是,ViewGroup类已经为咱们重写了dispatchDraw ()的功能实现,应用程序通常不须要重写该方法,但能够重载父类函数实现具体的功能。
参考blog分享:http://blog.csdn.net/qinjuning/article/details/7110211
Android中主线程也叫UI线程,那么从名字上咱们也知道主线程主要是用来建立、更新UI的,而其余耗时操做,好比网络访问,或者文件处理,多媒体处理等都须要在子线程中操做,之因此在子线程中操做是为了保证UI的流畅程度,手机显示的刷新频率是60Hz,也就是一秒钟刷新60次,每16.67毫秒刷新一次,为了避免丢帧,那么主线程处理代码最好不要超过16毫秒。当子线程处理完数据后,为了防止UI处理逻辑的混乱,Android只容许主线程修改UI,那么这时候就须要Handler来充当子线程和主线程之间的桥梁了。
咱们一般将Handler声明在Activity中,而后覆写Handler中的handleMessage方法,当子线程调用handler.sendMessage()方法后handleMessage方法就会在主线程中执行。
这里面除了Handler、Message外还有隐藏的Looper和MessageQueue对象。
在主线程中Android默认已经调用了Looper.preper()方法,调用该方法的目的是在Looper中建立MessageQueue成员变量并把Looper对象绑定到当前线程中。当调用Handler的sendMessage(对象)方法的时候就将Message对象添加到了Looper建立的MessageQueue队列中,同时给Message指定了target对象,其实这个target对象就是Handler对象。主线程默认执行了Looper.looper()方法,该方法从Looper的成员变量MessageQueue中取出Message,而后调用Message的target对象的handleMessage()方法。这样就完成了整个消息机制。
这两个方法都是在View的dispatchTouchEvent中调用的,onTouch优先于onTouchEvent执行。若是在onTouch方法中经过返回true将事件消费掉,onTouchEvent将不会再执行。
另外须要注意的是,onTouch可以获得执行须要两个前提条件,第一mOnTouchListener的值不能为空,第二当前点击的控件必须是enable的。所以若是你有一个控件是非enable的,那么给它注册onTouch事件将永远得不到执行。对于这一类控件,若是咱们想要监听它的touch事件,就必须经过在该控件中重写onTouchEvent方法来实现。
Android的事件分发机制主要是Touch事件分发,有两个主角:ViewGroup和View。Activity的Touch事件事实上是调用它内部的ViewGroup的Touch事件,能够直接当成ViewGroup处理。
View在ViewGroup内,ViewGroup也能够在其余ViewGroup内,这时候把内部的ViewGroup当成View来分析。
先分析ViewGroup的处理流程:首先得有个结构模型概念:ViewGroup和View组成了一棵树形结构,最顶层为Activity的ViewGroup,下面有若干的ViewGroup节点,每一个节点之下又有若干的ViewGroup节点或者View节点,依次类推。如图:
当一个Touch事件(触摸事件为例)到达根节点,即Acitivty的ViewGroup时,它会依次下发,下发的过程是调用子View(ViewGroup)的dispatchTouchEvent方法实现的。简单来讲,就是ViewGroup遍历它包含着的子View,调用每一个View的dispatchTouchEvent方法,而当子View为ViewGroup时,又会经过调用ViwGroup的dispatchTouchEvent方法继续调用其内部的View的dispatchTouchEvent方法。上述例子中的消息下发顺序是这样的:①-②-⑤-⑥-⑦-③-④。dispatchTouchEvent方法只负责事件的分发,它拥有boolean类型的返回值,当返回为true时,顺序下发会中断。在上述例子中若是⑤的dispatchTouchEvent返回结果为true,那么⑥-⑦-③-④将都接收不到本次Touch事件。
1.Touch事件分发中只有两个主角:ViewGroup和View。ViewGroup包含onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent三个相关事件。View包含dispatchTouchEvent、onTouchEvent两个相关事件。其中ViewGroup又继承于View。
2.ViewGroup和View组成了一个树状结构,根节点为Activity内部包含的一个ViwGroup。
3.触摸事件由Action_Down、Action_Move、Aciton_UP组成,其中一次完整的触摸事件中,Down和Up都只有一个,Move有若干个,能够为0个。
4.当Acitivty接收到Touch事件时,将遍历子View进行Down事件的分发。ViewGroup的遍历能够当作是递归的。分发的目的是为了找到真正要处理本次完整触摸事件的View,这个View会在onTouchuEvent结果返回true。
5.当某个子View返回true时,会停止Down事件的分发,同时在ViewGroup中记录该子View。接下去的Move和Up事件将由该子View直接进行处理。因为子View是保存在ViewGroup中的,多层ViewGroup的节点结构时,上级ViewGroup保存的会是真实处理事件的View所在的ViewGroup对象:如ViewGroup0-ViewGroup1-TextView的结构中,TextView返回了true,它将被保存在ViewGroup1中,而ViewGroup1也会返回true,被保存在ViewGroup0中。当Move和UP事件来时,会先从ViewGroup0传递至ViewGroup1,再由ViewGroup1传递至TextView。
6.当ViewGroup中全部子View都不捕获Down事件时,将触发ViewGroup自身的onTouch事件。触发的方式是调用super.dispatchTouchEvent函数,即父类View的dispatchTouchEvent方法。在全部子View都不处理的状况下,触发Acitivity的onTouchEvent方法。
7.onInterceptTouchEvent有两个做用:1.拦截Down事件的分发。2.停止Up和Move事件向目标View传递,使得目标View所在的ViewGroup捕获Up和Move事件。
在Android系统中,全部安装到系统的应用程序都必有一个数字证书,此数字证书用于标识应用程序的做者和在应用程序之间创建信任关系。
Android系统要求每个安装进系统的应用程序都是通过数字证书签名的,数字证书的私钥则保存在程序开发者的手中。Android将数字证书用来标识应用程序的做者和在应用程序之间创建信任关系,不是用来决定最终用户能够安装哪些应用程序。
这个数字证书并不须要权威的数字证书签名机构认证(CA),它只是用来让应用程序包自我认证的。
同一个开发者的多个程序尽量使用同一个数字证书,这能够带来如下好处。
(1)有利于程序升级,当新版程序和旧版程序的数字证书相同时,Android系统才会认为这两个程序是同一个程序的不一样版本。若是新版程序和旧版程序的数字证书不相同,则Android系统认为他们是不一样的程序,并产生冲突,会要求新程序更改包名。
(2)有利于程序的模块化设计和开发。Android系统容许拥有同一个数字签名的程序运行在一个进程中,Android程序会将他们视为同一个程序。因此开发者能够将本身的程序分模块开发,而用户只须要在须要的时候下载适当的模块。
在签名时,须要考虑数字证书的有效期:
(1)数字证书的有效期要包含程序的预计生命周期,一旦数字证书失效,持有改数字证书的程序将不能正常升级。
(2)若是多个程序使用同一个数字证书,则该数字证书的有效期要包含全部程序的预计生命周期。
(3)Android Market强制要求全部应用程序数字证书的有效期要持续到2033年10月22日之后。
Android数字证书包含如下几个要点:
(1)全部的应用程序都必须有数字证书,Android系统不会安装一个没有数字证书的应用程序
(2)Android程序包使用的数字证书能够是自签名的,不须要一个权威的数字证书机构签名认证
(3)若是要正式发布一个Android ,必须使用一个合适的私钥生成的数字证书来给程序签名,而不能使用adt插件或者ant工具生成的调试证书来发布。
(4)数字证书都是有有效期的,Android只是在应用程序安装的时候才会检查证书的有效期。若是程序已经安装在系统中,即便证书过时也不会影响程序的正常功能。
能够经过Eclipse导出工程时为当前工程设置签名证书。File -> Export ->Export Android Application ->Create New keystore ....
Android中动画分为两种,一种是Tween动画、还有一种是Frame动画。
Tween动画,这种实现方式能够使视图组件移动、放大、缩小以及产生透明度的变化;
Frame动画,传统的动画方法,经过顺序的播放排列好的图片来实现,相似电影。
能够经过两种方式,一是经过定义Activity的主题,二是经过覆写Activity的overridePendingTransition方法。
经过设置主题样式
在styles.xml中编辑以下代码:
@anim/slide_in_left @anim/slide_out_left @anim/slide_in_right @anim/slide_out_right " v:shapes="_x0000_s1034">
添加themes.xml文件:
@style/AnimationActivity true " v:shapes="_x0000_s1033">
在AndroidManifest.xml中给指定的Activity指定theme。
覆写overridePendingTransition方法
overridePendingTransition(R.anim.fade, R.anim.hold);
AsyncTask用于处理异步任务,该类是一个抽象的泛型类。类的签名以下:public abstract class AsyncTask<Params, Progress, Result>。
三种泛型类型分别表明“启动任务执行的输入参数”、“后台任务执行的进度”、“后台计算结果的类型”。在特定场合下,并非全部类型都被使用,若是没有被使用,能够用java.lang.Void类型代替。
一个异步任务的执行通常包括如下几个步骤:
1.execute(Params... params),执行一个异步任务,须要咱们在代码中调用此方法,触发异步任务的执行。
2.onPreExecute(),在execute(Params... params)被调用后当即执行,通常用来在执行后台任务前对UI作一些标记。
3.doInBackground(Params... params),在onPreExecute()完成后当即执行,用于执行较为费时的操做,此方法将接收输入参数和返回计算结果。在执行过程当中能够调用publishProgress(Progress... values)来更新进度信息。
4.onProgressUpdate(Progress... values),在调用publishProgress(Progress... values)时,此方法被执行,直接将进度信息更新到UI组件上。
5.onPostExecute(Result result),当后台操做结束时,此方法将会被调用,计算结果将作为参数传递到此方法中,直接将结果显示到UI组件上。
在使用的时候,有几点须要格外注意:
1.异步任务的实例必须在UI线程中建立。
2.execute(Params... params)方法必须在UI线程中调用。
3.不要手动调用onPreExecute(),doInBackground(Params... params),onProgressUpdate(Progress... values),onPostExecute(Result result)这几个方法。
4.不能在doInBackground(Params... params)中更改UI组件的信息。
5.一个任务实例只能执行一次,若是执行第二次将会抛出异常。
我写一个简单的例子来演示AsyncTask的用法。
asyncTask = new MyAsyncTask(); asyncTask.execute(100); } class MyAsyncTask extends AsyncTask<integer, integer,="" string="">{ /** * 该方法在子线程中运行,所以不能有任何修改UI操做 */ @Override protected String doInBackground(Integer... params) { for(int i=0;i<params[0];i++){ try="" {="" 模拟耗时操做="" thread.sleep(100);="" }="" catch="" (interruptedexception="" e)="" e.printstacktrace();="" 发送进度="" publishprogress(i);="" return="" "任务已经完成";="" **="" *="" 任务执行前在ui线程中调用="" "="">
* @param result 正是doInBackground的返回值 */ @Override protected void onPostExecute(String result) { Toast.makeText(MainActivity.this, result, 0).show(); super.onPostExecute(result); } /** * 在UI线程中执行 * 当doInBackground执行publishProgress时调用该方法 */ @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); tv.setText("当前进度:"+values[0]); } } } " v:shapes="_x0000_s1031">
activity_main.xml