当前位置:  操作系统>andriod

Android开发需要的几点注意事项总结

 
分享到:
    发布时间:2014-1-13  


    本文导语:  Android应用程序运行的移动设备受限于其运算能力,存储空间,及电池续航。由此,它必须是高效的。电池续航可能是一个促使你优化程序的原因,即使他看起来已经运行的足够快了。由于续航对用户的重要性,...

     Android应用程序运行的移动设备受限于其运算能力,存储空间,及电池续航。由此,它必须是高效的。电池续航可能是一个促使你优化程序的原因,即使他看起来已经运行的足够快了。由于续航对用户的重要性,当电量耗损陡增时,意味这用户迟早会发现是由于你的程序。
   虽然这份文档主要包含着细微的优化,但这些绝不能成为你软件成败的关键。选择合适的算法数据结构永远是你最先应该考虑的事情,但这超出这份文档之外。
  
 1. 介绍
   写出高效的代码有两条基本的原则
    不作没有必要的工作
    尽量避免内存分配
  
 2. 明智的优化
   这份文档是关于Android规范的细微优化,所以先确保你已经了解哪些代码需要优化,并且知道如何去衡量你所做修改所带来的效果(好或坏)。用开投资开发时间是有限的,所以明智的时间规划很重要。
   这份文档同时确保你在算法和数据结构上作出最佳选择,同时考虑了API选择所带来的潜在影响。使用恰当的数据结构和算法比这里的任何建议都有价值,考虑API版本带来的影响会如实你选择更好的实现。
   当你优化Android程序时会遇到的一个棘手问题是确保你的程序能在不同的硬件平台上运行。不同版本的虚拟机在不同处理器上的运行速度各不相同。并且不是简单的设备A比设备B快或者,并针对一个设备与其他设备之间做出排列。特别的,模拟器上只能评测小部分可以在设备上体现的东西。有无JIT的设备间也有着巨大差异:对于有JIT设备好的代码有时对无JIT的设备并不是最好的。
   如果你想知道程序在设备上的表现,就必须在上面进行测试
   
3. 避免创建不必要的对象
   对象创建永远不会免费的。每个线程的分代GC给临时对象分配一个地址池能降低分配开销,但分配内存往往需要比不分配内存高的代价。
   如果在用户界面周期内分配对象,会强制一个周期性的垃圾回收,给用户体验造成小小的停顿间隙。Gingerbread中介绍的并发回收也许有用,但应该避免不必要的工作。
   因此,避免创建不需要的对象实例。下面是几个例子:
   ◆ 如果有一个返回String方法,他的返回值通常附加在一个StringBuffer上,改变声明和实现,这样函数直接在其后面附加,而非创建一个短暂存在的临时变量
   ◆ 当从输入的数据集合中读取数据时,考虑返回原始数据的子串,而非新建一个拷贝。这样你会创建一个新的对象,但是他们共享该数据的char数组。换来的是即使你仅仅使用原始输入的一部分,你也需要保证它一直存在于内存中。
   一个更彻底的观点是将多维数组切割成一维数组:
   ◆ Int类型的数组比Integer类型的好。推而广之,两个平行的int数组要比一个(int,int)型的对象数组高效。这个定理对于任何基本数据类型组合都通用。
   ◆ 如果需要实现存放元组(Foo,Bar)对象的容器,记住两个平行数组Foo[], Bar[]会优于一个(Foo,Bar)对象的数组。(例外情况是:当你设计API给其他代码调用时,最好用好的API设计来换取小的速度提升。但在自己的内部代码中,尽量尝试高效的实现。)
   通常来说,尽量避免创建短时临时对象。少的对象创建意味着低频的垃圾回收。这对于用户体验产生直接的影响。
  
 4. 性能之谜
   一个版本的文档给出了好多误导人的主张,这里做一些澄清:
   ◆ 在没有JIT的设备上,调用方法所传递的对象采用具体的类型而非接口类型会更有效(比如,传递HashMap map比传递Map map调用一个方法耗费的开销小,尽管两种情况下的map都是HashMap)。但这并不是两倍慢的情形,事实上,只相差6%,而JIT使这两种调用的效率不分伯仲。
   ◆ 在没有JIT的设备上,访问缓存后的字段比直接访问字段快大概20%。在有JIT的情况下,字段访问和局部访问耗费是一样的 。所以这里不值得优化,除非你觉得他会让你的代码更易读(对于final,static,及static final 变量同样适用).
  
 5. 用静态代替虚拟
   如果不需要访问某对象的字段,将方法设置为静态,调用会加速15%到20%。这也是一种好的做法,因为你可以通过方法声明知晓调用该方法不需要更新此对象的状态
  
 6. 避免内部的Getters/Setters
   在源生语言c++中,通常做法是用getters(i=getcount())代替直接访问字段(i=mcount)。这是c++中一个好的习惯,因为编译器内联这些访问,如果需要约束或者调试这些域的访问,你可以在任何时间添加代码。
   在Android中,这是个不好的想法。虚方法调用代价比直接存取字段高昂的多。按照通常面向对象语言的做法在公共接口中使用Getters和Setters是有原因的,但应该在一个经常访问其字段的中采用直接访问。
   无JIT时,直接字段访问大约比调用无关紧要的getter来访问快3倍。有JIT时(直接访问字段开销和访问局部变量是一样的),要快7倍。在Froyo版本中确实如此,但以后会在JIT中改进Getter方法的内联。
   
7. 对常量使用Static Final修饰符
   考虑下面类首的声明:
  static int intVal = 42;  
  static String strVal = "Hello, world!";
   编译器生成一个类初始化方法clinit, 当类初次被使用时执行,这个方法将42存入intVal中,并得到类字符串常量strVal的引用。当这些值在后面被引用时,他们通过字段查找进行访问。
   我们改进实现,采用 final关键字:
  static final int intVal = 42;    
  static final String strVal = "Hello, world!";    
    类不再需要clinit方法,因为常量进入了dex文件中的静态字段初始化器中。引用intVal的代码,直接调用整形值42,而访问strVal时也会采用相对开销较小的 string constant(字符串常量)指令替代字段查找。(这种优化仅仅是针对基本数据类型和String类型常量的,而非任意的引用类型。但尽可能的将常量声明为static final类型是一种好的做法。
  
 8. 使用改进的For循环语法
   改进的for循环(有时被称为for-each循环)能够用于实现了iterable接口的集合类及数组中。在集合类中,迭代器促使接口访问hasNext()和next()方法,在ArrayList中,计数循环迭代要快3倍(无论有没有JIT),但其他集合类中,改进的for循环语法和迭代器具有相同的效率。
   这里有一些迭代数组的实现:

static class Foo {
  int mSplat;
}
  Foo[] mArray = ...
public void zero() {
  int sum = 0;
  for (int i = 0; i mArray.length; ++i) {
    sum += mArray.mSplat;
  }
}
public void one() {
  int sum = 0;
  Foo[] localArray = mArray;
  int len = localArray.length;
  for (int i = 0; i len; ++i) {
    sum += localArray.mSplat;
  }
}
public void two() {
  int sum = 0;
  for (Foo a : mArray) {
    sum += a.mSplat;
  }
}

    zero()是当中最慢的,因为对于这个遍历中的历次迭代,JIT不能优化获取数组长度的开销。
   One()稍快,将所有东西都放进局部变量中,避免了查找。但仅只有数组长度促使了性能的改善。
   two()是在无jit的设备上运行最快的,对于有jit的设备则和one()不分上下。他采用了jdk1.5中的改进for循环语法。
   结论:优先采用改进的for循环,但在性能要求苛刻的ArrayList迭代中考虑采用手写计数循环。
 
9. 在私有内部内中,考虑用包访问权限替代私有访问权限    

 10.  andriod多线程开发

    我们都知道Android是单线程模型,这意味着Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行,所以你单纯的new一个Thrad并且start()不行的,因为这违背了Android的单线程模型。

    很幸运的是Android为我们提供了在其他线程中访问UI线程的方法,相信大家都见过,这几个就是Activity的runOnUiThread方法,ViewpostpostDelayed方法,以及最常用的Hanlder和AsyncTask,这里我推荐使用Hanlder和AsyncTask,尤其是AsyncTask,因为使用他们你会发现你的代码很容易被理解,因为他们都有一些具有特定职责的方法,尤其是AsyncTask,有预处理的方法onPreExecute,有后台执行任务的方法doInBackground,有更新进度的方法publishProgress,有返回结果的方法onPostExecute等等,这就不像post这些方法,把所有的操作都一大坨的写在一个Runnable里。

    有了Android为我们提供了这些方法我们就可以很好的解决一些长时间处理的任务了,但是在使用的时候我们还必须注意以下几点:

   1) 这些方法或者类必须在在UI线程中创建和调用

   2)其实这些方法和类最终的实现都是Android的Message、MessageQueue和Looper的机制,所以不要期待你会马上看到结果(效果),因为这是一个Loop一直循环出MessageQueue中的Message执行的过程,如果你没有看到效果,那么等等吧,因为还没有轮到你。

   3)有线程(多个)的地方就会有并发,会有资源共享冲突,所以在使用的时候谨慎点吧,说不准你的一个线程中使用的变量已经被另一个线程改的面目全非了。。


  • 本站(WWW.169IT.COM)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.169IT.COM)站内文章除注明原创外,均为转载,整理或搜集自网络.欢迎任何形式的转载,转载请注明出处.
    转载请注明:文章转载自:[169IT-IT技术资讯]
    本文标题:Android开发需要的几点注意事项总结
相关文章推荐:
  • 申请Android Map 的API Key(v2)的最新申请方式(SHA1密钥)
  • Android瀑布流实例 android_waterfall
  • android 4.0 托管进程介绍及优先级和回收机制
  • Android系统自带样式 (android:theme)
  • Android访问与手机通讯相关类的介绍
  • Android 图标库 Android GraphView
  • Android 2.3 下StrictMode介绍
  • 轻量级Android开发工具 Android Tools
  • Android网络共享软件 Android Wifi Tether
  • Android 开发环境 Android Studio
  • IDEA的Android开发插件 idea-android
  • Android手机事件提醒 Android Notifier
  • XBMC的Android客户端 android-xbmcremote
  • Android小游戏 Android Shapes
  • Android电池监控 Android Battery Dog
  • android开发:“android:WindowTitle”没有对应项no resource
  • Android 上类似IOS 的开关控件。 Android ToggleButton
  • Android 将 android view 的位置设为右下角的解决方法
  • Android 2D游戏引擎 Android Angle
  • Android的UI工具包 android-ui-utils
  • 白宫Android客户端 wh-app-android


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2017,169IT.COM,E-mail:www_169it_com#163.com(请将#改为@)

    浙ICP备11055608号