android知识点.docx
《android知识点.docx》由会员分享,可在线阅读,更多相关《android知识点.docx(28页珍藏版)》请在冰点文库上搜索。
android知识点
Android编程下Touch事件的分发和消费机制
Android中与Touch事件相关的方法包括:
dispatchTouchEvent(MotionEventev)、onInterceptTouchEvent(MotionEventev)、onTouchEvent(MotionEventev);能够响应这些方法的控件包括:
ViewGroup、View、Activity。
方法与控件的对应关系如下表所示:
Touch事件相关方法
方法功能
ViewGroup
View
Activity
publicbooleandispatchTouchEvent(MotionEventev)
事件分发
Yes
Yes
Yes
publicbooleanonInterceptTouchEvent(MotionEventev)
事件拦截
Yes
Yes
No
publicbooleanonTouchEvent(MotionEventev)
事件响应
Yes
Yes
Yes
从这张表中我们可以看到ViewGroup和View对与Touch事件相关的三个方法均能响应,而Activity对 onInterceptTouchEvent(MotionEventev) 也就是事件拦截不进行响应。
另外需要注意的是View对 dispatchTouchEvent(MotionEventev) 和 onInterceptTouchEvent(MotionEventev) 的响应的前提是可以向该View中添加子View,如果当前的View已经是一个最小的单元View(比如TextView),那么就无法向这个最小View中添加子View,也就无法向子View进行事件的分发和拦截,所以它没有 dispatchTouchEvent(MotionEventev) 和 onInterceptTouchEvent(MotionEventev),只有onTouchEvent(MotionEventev)。
一、Touch事件分析
▐ 事件分发:
publicbooleandispatchTouchEvent(MotionEventev)
Touch事件发生时 Activity的 dispatchTouchEvent(MotionEventev)方法会以隧道方式(从根元素依次往下传递直到最内层子元素或在中间某一元素中由于某一条件停止传递)将事件传递给最外层View的dispatchTouchEvent(MotionEventev)方法,并由该View的dispatchTouchEvent(MotionEventev)方法对事件进行分发。
dispatchTouchEvent 的事件分发逻辑如下:
∙如果 returntrue,事件会分发给当前View并由dispatchTouchEvent方法进行消费,同时事件会停止向下传递;
∙如果 returnfalse,事件分发分为两种情况:
1.如果当前View获取的事件直接来自Activity,则会将事件返回给Activity的onTouchEvent进行消费;
2.如果当前View获取的事件来自外层父控件,则会将事件返回给父View的 onTouchEvent进行消费。
∙如果返回系统默认的 super.dispatchTouchEvent(ev),事件会自动的分发给当前View的onInterceptTouchEvent方法。
▐ 事件拦截:
publicbooleanonInterceptTouchEvent(MotionEventev)
在外层View的dispatchTouchEvent(MotionEventev)方法返回系统默认的super.dispatchTouchEvent(ev)情况下,事件会自动的分发给当前View的onInterceptTouchEvent方法。
onInterceptTouchEvent 的事件拦截逻辑如下:
∙如果onInterceptTouchEvent返回 true,则表示将事件进行拦截,并将拦截到的事件交由当前View的onTouchEvent进行处理;
∙如果onInterceptTouchEvent返回 false,则表示将事件放行,当前View上的事件会被传递到子View上,再由子View的dispatchTouchEvent来开始这个事件的分发;
∙如果onInterceptTouchEvent返回 super.onInterceptTouchEvent(ev),事件默认会被拦截,并将拦截到的事件交由当前View的onTouchEvent进行处理。
▐ 事件响应:
publicbooleanonTouchEvent(MotionEventev)
在dispatchTouchEvent返回super.dispatchTouchEvent(ev)并且onInterceptTouchEvent返回true或返回super.onInterceptTouchEvent(ev)的情况下onTouchEvent会被调用。
onTouchEvent 的事件响应逻辑如下:
∙如果事件传递到当前View的onTouchEvent方法,而该方法返回了false,那么这个事件会从当前View向上传递,并且都是由上层View的onTouchEvent来接收,如果传递到上面的onTouchEvent也返回false,这个事件就会“消失”,而且接收不到下一次事件。
∙如果返回了true则会接收并消费该事件。
∙如果返回super.onTouchEvent(ev)默认处理事件的逻辑和返回false时相同。
到这里,与Touch事件相关的三个方法就分析完毕了。
下面的内容会通过各种不同的的测试案例来验证上文中三个方法对事件的处理逻辑。
Android性能优化
性能低下的现象
-游戏:
界面很卡,FPS低
-界面无响应
-服务器响应速度慢
性能低下的后果:
降低用户体验
-用户流失
-项目失败
-引发灾难
容易引发性能问题的点
-硬件
-IO操作
-数据库
-网络
-函数调用
-数据结构
-程序逻辑
从全局考虑
-硬件性能
-架构设计
-核心数据结构
从微观考虑
-小规模修改程序,提高性能:
程序的性能是可以累加的
-简单代码设计
-类和函数设计:
合适的数据类型和算法
-用快速排序代替冒泡排序
-用二分查找代替线性查找
-业务逻辑的实现
一些观点
-高效代码≠更好代码≠高质量代码(易修改,易扩充,易维护)
-80/20法则:
4%的代码占用了50%以上的运行时间
-随时随地进行优化**==>**将陷入无休止的优化泥潭
-开发阶段前期:
功能都未实现,何谈优化,但在设计的时候,需要考虑到对应风险。
-开发阶段中后期:
功能部分完善,通过现象进行模块优化
-开发阶段后期:
功能完善,充分考虑整体性,通过现象进行系统优化
-后期优化无法满足性能要求----架构先天不足,只能大批量重构
-过分提高性能会损害程序的可读性和可维护性
-优先实现功能,然后再进行优化
-程序功能的正确性比性能更重要
-真正高性能的程序设计:
方法论
在进行性能优化前,确保该功能是否已基本完整。
优化步骤
-是否考虑通过修改需求来提高性能?
-是否考虑通过修改整体设计提高性能?
-是否考虑通过来修改类的设计提高性能?
-在开始修改前,程序是完全正确的么?
-是否在修改前是否进行性能评估?
-是否记录了每次修改后的性能的变化?
-如果没有带来预期的性能提高,是否完全放弃所做的代码调整?
-是否对每个性能瓶颈进行不止一次的尝试?
-是否反复进行代码调整,直到最优?
性能瓶颈的发现
找出瓶颈,集中火力对付占用绝大部分资源的少量代码。
途径:
1. CodeReview
通过最基本优化策略优化代码
2. 代码性能测量
a)通过性能Log记录函数调用时间,找出瓶颈点
b)使用性能分析工具:
∙Traceview(参考:
Android性能调优工具TraceView介绍)
∙Monkey
∙MonkeyRunner
注:
后两个我个人没有使用过,不做介绍,优先推荐使用TraceView工具
如何优化?
优化本身是一个很大的主题,我这是主要是针对于Android平台来说的。
个人认为,优化可以分成好几部分:
∙一是JAVA语法层次通用的优化,如尽量使用局部变量(栈变量),IO缓冲等。
∙二是通用的Android性能优化,如同步改异步,各种缓存的使用等
∙三是应用程序内部的性能优化,如内部逻辑、数据插入及查找、数据结构的安排与组织等
以下部分针对于上述3种类型,分别进行简要说明:
1.基本优化策略:
JAVA语法层次的优化
类和对象使用技巧
-尽量少用new生成新对象
-使用clone方法生成新对象
-尽量使用局部变量栈变量
-减少方法调用
-使用final类和final/static/private方法
-让访问实例内变量的getter/setter方法变成final
-避免不需要的instanceof操作
-避免不需要的造型操作
-尽量重用对象
-不要重复初始化变量
-不要过分创建对象
JavaIO技巧
-使用缓冲提高IO性能
-InputStream比Reader高效,OutputStream比Writer高效
-在适当的时候用byte替代char
-有缓冲的块操作IO要比缓冲的流字符IO快
-序列化时使用原子类型
-在finally块中关闭stream
-SQL语句
-尽早释放资源
-异常Exceptions使用技巧
-避免使用异常来控制程序流程
-尽可能重用异常
-将try...catch块移出循环
线程使用技巧
-在使用大量线程Threading的场合使用线程池管理
-防止过多的同步
-同步方法而不要同步整个代码段
-在追求速度的场合用ArrayList和HashMap代替Vector和Hashtable
-使用notify而不是notifyAll
-不要在循环中调用synchronized同步方法
-单线程应尽量使用HashMap,ArrayList
其它常用技巧
-使用移位操作替代乘除法操作可以极大地提高性能
-对Vector中最后位置的添加删除操作要远远快于埘第一个元素的添加删除操作
-当复制数组时使用System.arraycop方法
-使用复合赋值运算符
-用int而不用其它基本类型
-在进行数据库连接和网络连接时使用连接池
-用压缩加快网络传输速度一种常用方法是把相关文件打包到一个jar文件中
-在数据库应用程序中使用批处理功能
-消除循环体中不必要的代码
-为vectors和hashtables定义初始大小
-如果只是查找单个字符的话用charat代替startswith
-在字符串相加的时候使用charat()代替startswith()如果该字符串只有一个字符的话
-对于boolean值避免不必要的等式判断
-对于常量字符串用String代替Stringbuffer
-用Stringtokenizer代替indexof和substring
-使用条件操作符替代ifcondelse结构
-不要在循环体中实例化变量
-确定Stringbuffer的容量
-不要总是使用取反操作符
-与一个接口进行instanceof操作
-采用在需要的时候才开始创建的策略
-通过StringBuffer的构造函数来设定他的初始化容量可以明显提升性能
-合理使用java.util.Vector
-不要将数组声明为publicstaticfinal
-HaspMap的遍历
-Array数组和ArrayList的使用
-StringBuffer和StringBuilder的区别
-尽量使用基本数据类型代替对象
-用简单的数值计算代替复杂的函数计算比如查表方式解决三角函数问题
-使用具体类比使用接口效率高但结构弹性降低了但现代IDE都可以解决这个问题
-考虑使用静态方法
-应尽可能避免使用内在的GET/SET方法
-避免枚举浮点数的使用
-二维数组比一维数组占用更多的内存空间大概是10倍计算
-SQLite
-奇偶判断
实际上,Android本身的Training文档也提供给我们很多可参考的内容,以下仅枚举一些KeyPoint,当然,有的内容是与上面的策略是重复的。
总体上来说,想要写出高效代码,我们要遵循两条基本的原则:
∙不作没有必要的工作。
∙尽量避免内存分配。
KeyPoint
-避免创建不必要的对象
-用静态代替虚拟
-避免内部的Getters/Setters
-对常量使用StaticFinal修饰符
-使用改进的For循环语法(for-each)
-在有内部类的情况考虑使用包权限来替代私有访问
-避免使用浮点数
-了解并使用类库
-合理利用Native方法
2.通用Android性能优化
布局优化
∙尽量减少Android程序布局中View的层次,View层次越多,效率就越低
∙使用复用布局
∙使用ViewStub懒加载布局
∙使用ViewHolder、Thread使ListView滚动更加流畅
其它优化点
∙合理使用异步操作
∙懒加载:
当前不需要的数据,不要加载,即按需加载。
懒加载的范围是广泛的,可以是数据,可以是View,或者其它
∙使用缓存
o图片缓存:
包括MemoryCache和DiskCache,可以使用官方DEMO中的Cache
o单例数据缓存:
建立一个管理数据的类,管理所有数据,当主界面消失后,由于Application本身没有实际退出,因此,数据本身也没有释放掉,下次启动时,省去了加载数据的时间,当然,这并不是一个好的行为。
o使用ListView、GridView的View缓存
o使用Message自身的缓存,避免重复创建Message实例
o线程池
o数据池(可参考MessagePool的实现方式)
∙数据库优化
oSQL优化
o建立索引
o使用事务
∙算法优化
o用快速排序代替冒泡排序
o用二分查找代替线性查找
∙数据结构使用
o不要全部使用ArrayList,合理使用LinkedList等易于插入和删除的集合
o合理使用HashMap、HashSet来提高查找性能
o使用SparseArray、SparseIntArray、SparseBooleanArray来替代某些特定的HashMap
∙其它策略
o可以考虑延迟处理,避免在同一时间干过多的事情
3.应用程序内部的性能优化
该部分的优化应该是依据程序的不同而不同,没有万般皆准的法则,目前从我做过的程序来看,实际上,上述的性能优化点基本上已经能够解决很多性能问题了。
在我所做的程序中,主要的优化手段是:
∙程序逻辑简化:
分析代码,去掉冗余逻辑
∙数据结构的优化:
对集合类的灵活使用,特别是HashMap的使用,极大的提高查找性能。
∙批量处理原则:
对于需要循环调用地方,采用批量处理
Fragments(Android官方文档中文版)
Fragment表现Activity中用UI的一个行为或者一部分.可以组合多个fragment放在一个单独的activity中来创建一个多界面区域的UI,并可以在多个activity里重用某一个fragment.把fragment想象成一个activity的模块化区域,有它自己的生命周期,接收属于它的输入事件,并且可以在activity运行期间添加和删除.
Fragment必须总是被嵌入到一个activity中,它们的生命周期直接被其所属的宿主activity的生命周期影响.例如,当activity被暂停,那么在其中的所有fragment也被暂停;当activity被销毁,所有隶属于它的fragment也被销毁.然而,当一个activity正在运行时(处于resumed状态),我们可以独立地操作每一个fragment,比如添加或删除它们.当处理这样一个fragment事务时,也可以将它添加到activity所管理的backstack--每一个activity中的backstack实体都是一个发生过的fragment事务的记录.backstack允许用户通过按下BACK按键从一个fragment事务后退(往后导航).
将一个fragment作为activity布局的一部分添加进来时,它处在activity的viewhierarchy中的ViewGroup中,并且定义有它自己的view布局.通过在activity的布局文件中声明fragment来插入一个fragment到你的activity布局中,或者可以写代码将它添加到一个已存在的ViewGroup.然而,fragment并不一定必须是activity布局的一部分;也可以将一个fragment作为activity的隐藏的后台工作者.
本文档描述了如何使用fragment创建你的应用程序,包括:
当被添加到activity的backstack后,fragment如何维护他们的状态.在activity中,与activity和其他fragment共享事件.构建到activity的actionbar.以及更多内容.
设计哲学
Android在3.0中引入了fragments的概念,主要目的是用在大屏幕设备上--例如平板电脑上,支持更加动态和灵活的UI设计.平板电脑的屏幕要比手机的大得多,有更多的空间来放更多的UI组件,并且这些组件之间会产生更多的交互.Fragment允许这样的一种设计,而不需要你亲自来管理viewhierarchy的复杂变化.通过将activity的布局分散到fragment中,你可以在运行时修改activity的外观,并在由activity管理的backstack中保存那些变化.
例如,一个新闻应用可以在屏幕左侧使用一个fragment来展示一个文章的列表,然后在屏幕右侧使用另一个fragment来展示一篇文章–2个fragment并排显示在相同的一个activity中,并且每一个fragment拥有它自己的一套生命周期回调方法,并且处理它们自己的用户输入事件.因此,取代使用一个activity来选择一篇文章,而另一个activity来阅读文章的方式,用户可以在相同的activity中选择一篇文章并且阅读,如图所示:
fragment在你的应用中应当是一个模块化和可重用的组件.即,因为fragment定义了它自己的布局,以及通过使用它自己的生命周期回调方法定义了它自己的行为,你可以将fragment包含到多个activity中.这点特别重要,因为这允许你将你的用户体验适配到不同的屏幕尺寸.举个例子,你可能会仅当在屏幕尺寸足够大时,在一个activity中包含多个fragment,并且,当不属于这种情况时,会启动另一个单独的,使用不同fragment的activity.
继续之前那个新闻的例子--当运行在一个特别大的屏幕时(例如平板电脑),app可以在ActivityA中嵌入2个fragment.然而,在一个正常尺寸的屏幕(例如手机)上,没有足够的空间同时供2个fragment用,因此,ActivityA会仅包含文章列表的fragment,而当用户选择一篇文章时,它会启动ActivityB,它包含阅读文章的fragment.因此,应用可以同时支持图1中的2种设计模式.
创建Fragment
要创建一个fragment,必须创建一个Fragment的子类(或者继承自一个已存在的它的子类).Fragment类的代码看起来很像Activity.它包含了和activity类似的回调方法,例如onCreate(),onStart(),onPause,以及onStop().事实上,如果你准备将一个现成的Android应用转换到使用fragment,你可能只需简单的将代码从你的activity的回调函数分别移动到你的fragment的回调方法.
通常,应当至少实现如下的生命周期方法:
onCreate()
当创建fragment时,系统调用此方法.
在实现代码中,应当初始化想要在fragment中保持的必要组件,当fragment被暂停或者停止后可以恢复.
∙onCreateView()
fragment第一次绘制它的用户界面的时候,系统会调用此方法.为了绘制fragment的UI,此方法必须返回一个View,这个view是你的fragment布局的根view.如果fragment不提供UI,可以返回null.
∙onPause()
用户将要离开fragment时,系统调用这个方法作为第一个指示(然而它不总是意味着fragment将被销毁.)在当前用户会话结束之前,通常应当在这里提交任何应该持久化的变化(因为用户有可能不会返回).
大多数应用应当为每一个fragment实现至少这3个方法,但是还有一些其他回调方法你也应当用来去处理fragment生命周期的各种阶段.全部的生命周期回调方法将会在后面章节HandlingtheFragmentLifecycle中讨论.
除了继承基类Fragment,还有一些子类你可能会继承:
DialogFragment
显示一个浮动的对话框.
用这个类来创建一个对话框,是使用在Activity类的对话框工具方法之外的一个好的选择,
因为你可以将一个fragment对话框合并到activity管理的fragmentbackstack中,允许用户返回到一个之前曾被摒弃的fragment.
∙ListFragment
显示一个由一个adapter(例如SimpleCursorAdapter)管理的项目的列表,类似于ListActivity.
它提供一些方法来管理一个listview,例如onListItemClick()回调来处理点击事件.
∙PreferenceFragment
显示一个Preference对象的层次结构的列表,类似于PreferenceActivity.
这在为你的应用创建一个"设置"activity时有用处.
添加一个用户界面
fragment通常用来作为一个activit