本手册适合至少有初级经验的开发者查阅或复习相关知识使用,新手可能会看不懂。
dvm:.java->.class->.dex->.apk
斐波那契数列的递推公式是f(n)=f(n-1)+f(n-2),特征方程为:x2=x+1,解该方程得(1+sqrt(5))/2,(1-sqrt(5))/2.所以f(n)=Ax1n+Bx2n,带入f(0)=0,f(1)=1得A=sqrt(5)/5,B=-sqrt(5)/5.则f(n)求出。
用这个类来解决溢出问题。
斐波那契数列有如下性质:
(fn fn-1)=(fn-1 fn-2)*A,可以得出A=(1 1;1 0)
递推可得:(fn fn-1)=(fn-1 fn-2)*A=(fn-2 fn-3)*A2=…=(f1 f0)*An-1
缓存结果:
用HashMap来充当缓存,当键是整数时,用SparseArray效率更高。
LruCache:
适合用来缓存图片,它的主要算法原理是把最近使用的对象用强引用存储在 LinkedHashMap 中,并且把最近最少使用的对象在缓存值达到预设定值之前从内存中移除。
-
private LruCache<integer, string=""> mJsonCache;
/**
* 缓存图片信息
*/
private LruCache<integer, bitmap=""> mBitmapCache;
public Util() {
mJsonCache = new LruCache<integer, string="">(1 * 1024 * 1024);
mBitmapCache = new LruCache<integer, bitmap="">(2 * 1024 * 1024);
}
数据结构:
安卓在这些数据结构中增加了自身的一些实现,一般是为了提高性能,LruCache\SparseArray\SparseBooleanArray\SparseIntArray\Pair
还有Arrays和Collections类。例如使用Arrays.sort对数组排序。
响应能力:熟悉生命周期,例如设备方向变化时,配置Android:configChanges属性
主要由c/c++编写,是安卓原生开发套件。
1、创建本地方法:
public native String encode(String text, int length);
public native String decode(String text, int length);
}
2、实现JNI粘合层:
使用jdk的javah工具自动生成。
在java代码中,创建一个本地方法helloFromC
public native String helloFromC();
在jni中定义函数实现这个方法,函数名必须为
jstring Java_com_zhilinghui_helloworld1_MainActivity_helloFromC(JNIEnv* env, jobject obj)
返回一个字符串,用c定义一个字符串
char* cstr = "hello from c";
把c的字符串转换成java的字符串
jstring jstr = (*env)->NewStringUTF(env, cstr);
return jstr;
前面可以说的有点乱,这里简单概括一下:
步骤二:
实现C代码
方法名 严格按照jni的规范
步骤三:
创建android.mk 告诉编译器 如何把c代码打包成函数库
LOCAL_PATH := $(call my-dir)
步骤四:
把c代码 打包成函数库 用到了安装的环境 到相应目录下使用ndk-build打包
步骤五:
在java代码中 引入库函数
汇编优化:安卓 NDK内置了GCC编译器的功能。
要确保使用正确版本的objdump反编译目标文件和库。
ARM模式和Thumb模式。
java的char是16位(UTF-16),java的long是64位,而c的long是32位,long long是64位。
减少数据缓存读未命中几率的方法:1、在有大量数据存储在数组中时,使用尽可能小的数据类型;2、选择顺序访问而不是随机访问,最大限度的重用已在缓存中的数据。
只有当某个对象不再引用时,它的内存才会被回收,当该被释放的对象引用仍然存在的时候就会发生OOM。
例如:屏幕旋转时。Eclipse中可以在DDMS中的Heap及Allocation Tracker跟踪。
也可以使用StricMode类来检测潜在在内存泄漏.
强引用: 程序中绝大部分是这种引用。就是“正常”引用。
– BigIntegerbi=BigInteger.valueOf(n);//强引用
Integer i=new Integer(n);//强引用
i=null;//Integer对象变成可回收的垃圾。
软、弱、虚引用:
软可及对象,垃圾收集器自己决定想回收旧回收。弱可及对象,基本会被回收。虚引用,几乎很少用,可以用来注册引用队列。
-
ActivityManager am=(ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memInfo=new ActivityManager.MemoryInfo();
am.gettMemoryInfo(memInfo);
Thread对象。run()方法可以被复写,Runnable对象传递给Thread构造函数。记得调用start()。
线程优先级,一般是1-10(最高),默认是5.而Linux的优先级是从-20到19(最低).
AsyncTask启动任务栈执行的输入参数,后台任务执行的百分比,后台任务执行返回iud结果,匿名类。
例如:后台下载文件时刷新前台进度条。
他们是多线程应用线程间通信的基石。
有消息循环的线程。
Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。
MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。
Thread:线程,负责调度整个消息循环,即消息循环的执行场所
7个生命周期
调用AsyncTask.cancel()会在doInbackground()返回后触发onCancelled(),而不是onPoseExecute().
DDMS中的Traceview
查看跟踪代码的执行时间,分析哪些是耗时操作 ;可以用于跟踪方法的调用,尤其是Android Framework层的方法调用关系
TraceView罗列出了是所有监听到的方法,当然也包括Android系统很多方法的耗时,如何在这么多方法里面查找到自己关心的? 可以通过TraceView 底部的find 来查找,通常Android app都是有包名的,可以先针对某些关心的列排序后,在通过包名进行一个个查找,这些就省去自己筛选出自己app 方法耗时排行的时间。
一般屏幕和wifi很耗电。
可以通过检索固定的Intent。在应用启动时就获取电池当前电量,运行一段时间,在退出时再次获取电池电量。但是这个值并不准确,因为还有其他应用运行。
只有在需要时才启用广播接收器。
最终解决问题,AT&T与来自密歇根大学的同事们的工作人员进行了深入的端到端数据传输路径的综合调查,最终发现是在设备和蜂窝网络之间复杂的相互作用的问题的根源,相互作用,是很难看到,给出分层性网络架构,故意隐藏低层协议的开发者在应用层的工作。
更多文章可以参考:http://www.research.att.com/editions/201106_home.html
使用
例如,在用户观看视频或电影时,cpu需要做视频解码,同时保持屏幕开启,让用户能够观看。
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); WakeLock sCpuWakeLock = pm.newWakeLock(
PowerManager.FULL_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP,"okTag");
if (sCpuWakeLock!= null) {
sCpuWakeLock.release();
sCpuWakeLock = null;
}
SCREEN_DIM_WAKE_LOCK:保持CPU 运转,允许保持屏幕显示但有可能是灰的,允许关闭键盘灯
SCREEN_BRIGHT_WAKE_LOCK:保持CPU 运转,保持屏幕高亮显示,允许关闭键盘灯
FULL_WAKE_LOCK:保持CPU 运转,保持屏幕高亮显示,键盘灯也保持亮度
ACQUIRE_CAUSES_WAKEUP:不会唤醒设备,强制屏幕马上高亮显示,键盘灯开启。有一个例外,如果有notification弹出的话,会唤醒设备。
AlarmManage有一个AlarmManagerService,该服务程序主要维护app注册下来的各类Alarm,并且一直监听Alarm设备,一旦有Alarm触发,或者是Alarm事件发生,AlarmManagerService就会遍历Alarm列表,找到相应的注册Alarm并发出广播。
Alarm Manager会维持一个cpu的wake lock。这样能保证电话休眠时,也能处理alarm的广播。一旦alarm receiver的onReceive() 方法执行完,wake lock会迅速被释放。如果在receiver中开启一个service,有可能service还没启动,wake lock已经被释放了。所以此时要实现单独的wake lock策略。
有4种Alarm类型:
1)RTC_WAKEUP
在指定的时刻(设置Alarm的时候),唤醒设备来触发Intent。
2)RTC
在一个显式的时间触发Intent,但不唤醒设备。
3)ELAPSED_REALTIME
从设备启动后,如果流逝的时间达到总时间,那么触发Intent,但不唤醒设备。流逝的时间包括设备睡眠的任何时间。注意一点的是,时间流逝的计算点是自从它最后一次启动算起。
4)ELAPSED_REALTIME_WAKEUP
从设备启动后,达到流逝的总时间后,如果需要将唤醒设备并触发Intent。
这里不做详细的介绍了
调用setContentView()。xml布局的到时候要减少创建对象数量,可以用不同的布局达到同样的视觉效果,消除不必要的对象,或者推迟创建对象。
嵌套线性布局会深化布局层次,从而导致布局和按键处理变慢。当显示10个及以上的项目的时候就需要相对布局。
用<merge />
标签来合并布局
-
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/add"/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/delete"/>
* 使用<include />
标签重用布局
<include layout="@layout/titlebar"/>
<ViewStub
android:id="@+id/viewstub_demo_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip"
android:layout_marginTop="10dip"
android:layout="@layout/viewstub_demo_text_layout"/>
在sdk->tools目录下,有hierarchyviewer和layoutopt,可以查看和分析布局
OpenGL ES (为OpenGL for Embedded System的缩写) 为适用于嵌入式系统的一个免费二维和三维图形库。
任何复杂的2D或是3D图形都是通过这三种几何图形构造而成的。 OpenGL ES提供了两类方法来绘制一个空间几何图形:
public abstract void glDrawArrays(int mode, int first, int count) 使用VetexBuffer 来绘制,顶点的顺序由vertexBuffer中的顺序指定。
public abstract void glDrawElements(int mode, int count, int type, Buffer indices) ,可以重新定义顶点的顺序,顶点的顺序由indices Buffer 指定。
mode列表:GL_POINTS 绘制独立的点、GL_LINE_STRIP绘制一条线段、GL_LINE_LOOP绘制一条封闭线段(首位相连)、GL_LINES绘制多条线段、GL_TRIANGLES绘制多个三角形(两两不相邻)、GL_TRIANGLE_STRIP绘制多个三角形(两两相邻)、GL_TRIANGLE_FAN以一个点为顶点绘制多个相邻的三角形 对应顶点除了可以为其定义坐标外,还可以指定颜色,材质,法线(用于光照处理)等。 glEnableClientState 和 glDisableClientState 可以控制的pipeline开关可以有:GL_COLOR_ARRAY (颜色) ,GL_NORMAL_ARRAY (法线), GL_TEXTURE_COORD_ARRAY (材质), GL_VERTEX_ARRAY(顶点), GL_POINT_SIZE_ARRAY_OES等。 对应的传入颜色,顶点,材质,法线的方法如下: glColorPointer(int size,int type,int stride,Buffer pointer) glVertexPointer(int size, int type, int stride, Buffer pointer) glTexCoordPointer(int size, int type, int stride, Buffer pointer) glNormalPointer(int type, int stride, Buffer pointer) OpenGL ES 内部存放图形数据的Buffer有COLOR ,DEPTH (深度信息)等,在绘制图形只前一般需要清空COLOR 和 DEPTH Buffer。
通用的矩阵变换指令 这里介绍对应指定的坐标系(比如viewmodel, projection或是viewport) Android OpenGL ES支持的一些矩阵运算及操作。 矩阵本身可以支持加减乘除,对角线全为1的4X4 矩阵成为单位矩阵Identity Matrix 。
将当前矩阵设为单位矩阵的指令 为glLoadIdentity().
矩阵相乘的指令glMultMatrix*() 允许指定任意矩阵和当前矩阵相乘。
选择当前矩阵种类glMatrixMode(). OpenGL ES 可以运行指定GL_PROJECTION,GL_MODELVIEW等坐标系,后续的矩阵操作将针对选定的坐标。
将当前矩阵设置成任意指定矩阵glLoadMatrix*()
在栈中保存当前矩阵和从栈中恢复所存矩阵,可以使用glPushMatrix()和glPopMatrix()
特定的矩阵变换平移glTranslatef(),旋转glRotatef() 和缩放glScalef()
具体可以在官网看:http://developer.android.com/training/graphics/opengl/index.html
只有当场景变化才渲染帧。
RenderScript 是一种低级的高性能编程语言,用于3D渲染和处理密集型计算(3D播放等和关于CPU密集型的计算)。一直以来Android 在绘图性能的表现一直差强人意,引入NDK之后才有所改善,而在Honeycomb 中发布了RenderScript 这一杀手级在Framework 后,大大的增加了Android 本地语言的执行能力和计算能力。
RenderScript 在机器上进行第一遍编译,然后在目标设备上进行最后一遍编译(Just-In-Time Compiling),因而带来更高效的原生二进制代码。这也就是意味着,凡是支持RenderScript 的设备都可以运行你的代码。不用管什么架构。
目前 ,RenderScript 带来的代码只能在主处理器上运行,它会自动生成可利用多个核心的代码(如果设备上有多个核心)。就因此,编译出来的程序是针对该机器的最佳优化,这解决了Device Fragmentation,也就是说开发者再也不必担心使用者的手机、平板够不够好、有没有GPU…等等问题,全都交给RenderScript 去担心就好。没有GPU,RenderScript 写好的程序就交由CPU来处理(背后的编译技术其实是使用的LLVM)。