Android开发艺术探索小总结
1. IPC机制
组件在androidmenifest中指定androidprocess来创建多进程shareduid线程id">1.1四大组件在AndroidMenifest中指定android:process来创建多进程、sharedUID(线程ID)
1.2多进程的问题
1.2.1 静态成员和单例模式完全失效
1.2.2 线程同步机制失效
1.2.3 SharedPreferences的可靠性下降
1.2.4 Application会多次创建
1.3多进程通信方式
Intent、共享文件、基于Binder的Message、AIDL、Socket等
1.4数据序列化及Binder
1.4.1 Serializable接口
例如:
bean继承Serializable接口
然后序列化:
Bean bean = new Bean(,);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(“test.txt”));
out.writeObject(bean);
out.close();
反序列化:
ObjectInputStream in = new ObjectInputStream(new FileInputStream(“test.txt”));
Bean bean = (Bean)in.readObject();
In.close();
1.4.2 Parcelable接口
例如:
bean继承Parcelable接口,并且实现内部序列化、反序列化
序列化用内部的writeToParcel来实现
反序列化用内部的CREATOR并通过Parcel的一系列read方法来完成反序列化
1.4.3
Binder是ServiceManager链接各种Manager和相应的ManagerService的桥梁,主要用于Service中。
2. View的一些特殊操作
系统识别被认为滑动的最小距离">2.1 TouchSlop系统识别被认为滑动的最小距离
获取方式:ViewConfiguration.get(getContext()).getScledTouchSlop().
2.2 VelocityTracker速度追踪
获取方式:VelocityTracker vt = VelocityTracker.obtain();
vt.addMovement(event);
vt.computCurrentVelocity(1000);//一段时间内手指划过的像素数,举例子1000ms
int xVelocity = (int)vt.getXVelocity();//注意速度可以为负数
int yVelocity = (int)vt.getYVelocity();
vt.clear();
vt.recycle();//回收
2.3 手势检测GestureDetector
获取方式:GestrueDetector gd = new GestrueDetector(this);
gd.setIsLongpressEnabled(false);//解决长按屏幕无法拖动
boolean consume =gd.OnTouchEvent(event);//接管目标View的OnTouchEvent方法
return consume;
2.4 动画库nineoldandroids
2.5 RemoteViews(跨进程更新界面,使用场景:通知栏和桌面小部件)
它的各种set方法设置样式
3 Android的Drawable
3.1 BitmapDrawable 对应标签 bitmap
表示一张图片,可以直接引用原始图片,也可以用xml描述
3.2 ShapeDrawable对应标签 shape
android:shape代表形状,属性有rectangle(矩形)、oval(椭圆)、line(横线)、ring(圆环);
corners表示四个角的角度只适用于矩形shape
gradient表示渐变效果
solid表示纯色填充
stroke表示描边
padding表示内部空白
size表示shape的宽高
3.3 LayerDrawable 对应标签layer-list–item
表示 层次的Drawable集合,类似于ps图层
3.4 StateListDrawable 对应标签selector
一般按钮点击状态
3.5 LevelListDrawable 对应标签level-list–item
表示 有等级的Drawable集合,根据不同等级切换对应的Drawable
3.6 TransitionDrawable 对应标签transition–item
表示两个Drawable淡入淡出的效果
3.7 InsetDrawable 对应的标签inset
表示可以将其他的Drawable内嵌到自己当中
3.8 ScaleDrawable 对应标签scale
表示根据自己的等级缩放到一定比例
3.9 ClipDrawable 对应标签clip
表示根据自己的等级裁剪另一个Drawable
4 消息机制
4.1 Handler的几个概念
4.1.1 MessageQueue消息队列,以队列的形式插入和删除,实际采用单链表的数据结构来存储消息队列;enqueueMessage方法是插入消息;next方法是取出消息
4.1.2 Looper 循环,MessageQueue存储数据,Looper有新消息就处理消息,没有就一直阻塞;其中 Looper的prepare方法创建Looper对象;Looper.getMainLooper在任何地方得到主线程的Looper;quit直接退出;quitSafely消息处理完退出;注意子线程中创建Looper,消息处理完后,一定要quit;loop方法调用后消息系统才起作用,它就是一个死循环,只有MessageQueue的next返回null的时候会跳出
4.1.3 ThreadLocal作用是在每个线程中存储数据,可以再不同线程中互不干扰的的存储并提供数据,通过ThreadLocal可以轻松的获取每个线程的Looper,主线程ActivityThread被创建时就初始化Looper。
4.1.4运行机制:Handler的send调用,它调用MessageQueue的enqueueMessage方法将消息放入消息队列中,然后Loop方法会调用MessageQueue的next方法来获取新消息,然后Looper去处理(最终是交给了Handler的对象的dispatchMessage方法),最终消息中的Runnable或者Handler的HandlerMessage方法会被调用
5线程和线程池
5.1线程
主线程处理与界面相关操作,子线程处理耗时操作。常见线程有IntentServer、HandlerThread、Thread等
5.2线程池AsyncTask 它封装了Handler和Thread
5.2.1AsyncTask是一个泛型类有三个参数:Params(表示参数的类型)、Progress(表示后台任务执行进度的类型)、Result(后台任务返回结果类型),如果不需要传递参数,可以用Void代替
5.2.2核心方法
(1)onPreExecute():在主线程中执行,在异步任务之前,会被调用
(2)doInBackground(Params…params):在线程池中执行,用于执行异步任务,params表示异步任务输入参数,在此方法中可以通过publishProgress方法更新进度,publishProgress会调用onProgressUpdate方法,并将返回结果传递给onPostExecute.
(3)onProgressUpdate(Progress…values):在主线程中执行,当后台任务执行进度发生改变时会被调用
(4)onPostExecute(Result result)在主线程中执行,在异步执行之后会被调用,result是后台返回值,即(2)中返回的值
(5)onCancelled()在主线程中 执行,异步任务被取消的时候被调用,此时onPostExecute不会被调用
5.2.3 AsyncTask有两个线程池和一个Handler
SerialExecutor可以分析AsyncTask的排队执行过程;
THREAD_POOL_EXECUTOR用于执行任务;
IntentHandler用于将执行环境充线程池切换到主线程;
核心线程数等于CPU核心数+1;
线程池最大线程数CPU核心数*2+1;
5.3线程池ThreadPoolExecutor
5.3.1优点
重用线程,减少开销;控制最大并发,防止阻塞
5.3.2分类(创建ExecutorService x=Executors.newXXXThreadPool)
(1)FixedThreadPool:固定线程数的线程池,只有核心线程并且不会被回收,没有超时限制;
(2)CacheThreadPool:线程数量不固定的线程池,有超时限制,60秒闲置会被回收;
(3)ScheduleThreadPool:核心线程数固定,非核心线程没有限制,当非核心限制时就会回收;
(4)SingleThreadPool:只有一个核心线程,所有任务在这一个线程中顺序执行;
6 Bitmap
6.1加载方法
BitmapFactory加载图四个方法decodeFile、decodeResource、decodeStream、decodeByteArray
BitmapFactory.Options来缩放图片,主要使用inSampleSize参数,即采样率;还有inJustDecodeBounds参数,当它为true时只解析图片信息(宽高),不加载图片。
6.2缓存策略(Lru是Least Recently Used最近最少使用算法)
核心思想:当缓存快满时,会淘汰近期最少使用的缓存
LruCache(是一个泛型,内部使用 LinkedHashMap以强引用的方式存储对象)
DiskLruCache(磁盘缓存 利用open方法来创建,一般存在应用的cache目录,内部使用Editor来操作数据)
7综合技术
7.1当出现crash时,会调用CrashHandler的uncaughtException方法,在这个方法里我们可以获取crash的信息。
7.2对于方法个数的限制(整个应用不超过65536个方法),可以使用Google的multidex的方案;也可以动态加载dex
8.JNI和NDK
8.1JNI(Java Native Interface java本地接口)
操作步骤:
(1) java中声明native方法,并加载so库static{System.loadLibrary(“jni-test”);}
(2) 编译Java源文件得到class,然后通过javah命令导出JNI的头文件
(3) 实现JNI方法(主目录新建jni文件夹放入(2)中生成的.h文件,然后用C++或者C实现方法)
(4) 编译so库并在java中调用(so库编译用gcc,切换到jni目录,对于C++编译命令
C++:gcc -shared -I /usr/lib/jvm/java-7-openjdk-amd64/include -fPIC test.cpp
-o libjni-test.so
C:gcc -shared -I /usr/lib/jvm/java-7-openjdk-amd64/include -fPIC test.c
-o libjni-test.so)
其中/usr/lib/jvm/java-7-openjdk-amd64是JDK的路径;
8.2NDK
操作步骤:
(1) 下载并配置NDK,配置路径
(2) 创建Android项目,声明所需native方法并加载so库
(3) 实现声明的native方法,创建jni文件目录下创建三个文件:test.cpp、Android.mk和Application.mk。其中Android.mk中LOCAL_MODULE表示模块名称,LOCAL_SRC_FILES表示参与编译的源文件;Application.mk中APP_ABI表示CPU的架构平台类型(常见有armeabi、x86、mips)
(4) 切换到jni目录的父目录,利用ndk-build命令生成so库
(5) 在app/src/main中创建jniLibs目录,将so复制进去,运行即可
9性能优化
9.1布局优化
尽量减少布局文件的层级,优先等级LinearLayout和FrameLayout比RelativeLayout简单
标签include、merge(减少层级)、ViewStub(按需加载)
9.2绘制优化
OnDraw中不要创建局部对象、不要做耗时任务
9.3内存泄漏
(1)静态变量持有activity不能释放
(2)单例模式对象持有activity不能释放
(3)属性动画一定要在onDestory中停止
9.4其他优化
(1)响应速度,主要主线程中做些耗时任务
(2)ListView和Bitmap优化
(3)线程优化,要是可以尽量使用线程池
(4)不要使用过多的枚举,使用一些Android特有的数据结构,适当使用弱引用和软引用,采用缓存策略等