每日一言:不积硅步无以至千里,不积小流无以成江海。
欢迎一起讨论和学习,QQ:732258496 QQ群:478720016
目录 |
---|
一、Activity生命周期和启动模式 |
二、IPC机制 |
三、View的事件体系 |
四、View的工作原理 |
五、理解RemoteViews |
六、Android的Drawable |
七、Android动画深入分析 |
八、理解Window和WindowManager |
九、四大组件的工作过程 |
十、Android的消息机制 |
十一、Android的线程和线程池 |
十二、Bitmap的加载和Cache |
十三、综合技术 |
十四、JNI和NDK编程 |
十五、Android性能优化 |
一、Activity生命周期和启动模式
- 1.当前设置的 Configuration 发生改变
- 2.返回桌面时,Activity采用了透明主题,当前Activity不会调用onStop
- 3.从Activity可见 :onStart onStop ;Activity是否前台 :onResume onPause
- 4.ActivityStack (仪表盘) scheduleLaunchActivity(计划)
- 5.onPause 和onStop不能执行耗时操作
- 6.onSaveInstanceState() onRestoreInstanceState() Boundle 对象
- 7.委托思想。Activity-windows-decorView
- 8.当Activity正常销毁的时候,系统不会调用onSaveInstanceState()
- 9.将后台工作放入Service中从而保证进程有一定的优先级
- 10.不想系统重新创建Activity,可以给Activity制定configChanges属性:local,orientation,keyboardHideen
- 11.ApplicationContext启动standard模式的activity 报错
- 12.onNewIntent
- 13.singleTask
- 14.什么是Activity所需要的任务栈"
二、IPC机制
- 1.问题:解决进程间的通讯 ; 私有android:process="":remote"" 全局 com.wph:remote;两个应用相同的ShareId || 签名相同
- 2.序列化 Serializable (读写文件)erialVersionUID (反序列)
- 3.每个进程都分配一个独立的虚拟机,不同虚拟机在内存分配上有不同的地址空间;内存共享-失败
- 4.SharePreference不支持两个进程同时去执行写操作,运行在同一进程中的组件是属于同一虚拟* 机和同一个Application的
- 5.Binder主要用在Service中,包括AIDL和Messenger 代理
- 6.IPC方式1-Bundle 在(Activity/Service/Receiver)的Intent中传递Bundle;实现了Parcelable
- 7.IPC方式2-文件共享--特例:SharePreference 键值对系统对它有一定的缓从策略,所以会丢失数据
- 8.IPC方式3-使用messenger-以串行的方式处理客户端发来的消息
- 9.IPC方式4-AIDL-以大量并非请求, 只用ArrayList 观察者模式
- 10.IPC方式5-contentProvider 唯一表示标示符android:authorities
- 11.IPC方式6-Socket
- 12.Binder连接池:将每个业务模块的Binder请求统一转发到远程service去执行,避免重复创建service的过程"
三、View的事件体系
- 1.View在平移的过程中,top和left表示的是原始左上角的位置信息,其值并不会发生变化,此时发生变化的是 x、y、translationX、translationY这四个参数
- 2.MotionEvent :ACTIONDOWN ACITONMOVE ACTION_UP getX/getY getRawX/getRawY
- 3.TouchSlop 最小滑动距离 ;VelocityTracker 滑动速度;GestureDetector 手持检测;
- 4.如果监听滑动相关 onTouchEvent ;监听双击则使用 GestureDetector
- 5.使用动画来移动View:translationX/Y ,View动画,属性动画:为了兼容3.0以下的版本,需要开源库nineoldandroids
- 6.scrollTo/scrollBy:操作简单,适合对View内容滑动
- 7.Activity - Windows-ViewGroup - View
- 8.dispatchTouchEvent-onInterceptTouchEvent(ViewGroup特有的方法)-onTouchEvent
- 9.滑动冲突 拦截事件 requestDisallowInterceptTouchEvent
四、View的工作原理
- 1.自定义View:直接继承View和ViewGroup 或者直接继承系统控件
- 2.ViewRootImpl连接WindowManager和DecorView
- 3.View的工作流程:measure(测量宽/高)-layout(确定View的最终宽/高和四个顶点的位置)-draw(将View绘制到屏幕上)
- 4.直接继承View,需要重写onMeasure,并设置wrapcontent是的自身大小,否则布局中使用wrapcontent相当于使用match_parent
- 5.ViewGroup是一个抽象类,因此它没有重写View的onMeasure方法,但是提供了measureChildren
- 6.layout首先通过setFrame来设定View的四个顶点的位置--onlayout
- 7.draw过程 background.draw(canvas)绘制背景-onDraw()绘制自己-dispatchDraw 绘制children-onDrawScrollBars 绘制装饰
- 8.自定义View分类:(1)继承View重写onDraw()方法 (2)继承ViewGroup派生特殊的layout (3)继承特定的View(TextView)(4)继承特定的ViewGroup(LinearLayout)
- 9.自定义View须知(1)让View支持wrap_content(2)支持padding (3)不使用Handler(4)如果有线程和动画,要及时停止(5)如有嵌套处理好滑动冲突
四、View的工作原理
- 1.自定义View:直接继承View和ViewGroup 或者直接继承系统控件
- 2.ViewRootImpl连接WindowManager和DecorView
- 3.View的工作流程:measure(测量宽/高)-layout(确定View的最终宽/高和四个顶点的位置)-draw(将View绘制到屏幕上)
- 4.直接继承View,需要重写onMeasure,并设置wrapcontent是的自身大小,否则布局中使用wrapcontent相当于使用match_parent
- 5.ViewGroup是一个抽象类,因此它没有重写View的onMeasure方法,但是提供了measureChildren
- 6.layout首先通过setFrame来设定View的四个顶点的位置--onlayout
- 7.draw过程 background.draw(canvas)绘制背景-onDraw()绘制自己-dispatchDraw 绘制children-onDrawScrollBars 绘制装饰
- 8.自定义View分类:(1)继承View重写onDraw()方法 (2)继承ViewGroup派生特殊的layout (3)继承特定的View(TextView)(4)继承特定的ViewGroup(LinearLayout)
- 9.自定义View须知(1)让View支持wrap_content(2)支持padding (3)不使用Handler(4)如果有线程和动画,要及时停止(5)如有嵌套处理好滑动冲突
五、理解RemoteViews
-
1.Remote Views 在Android中的使用场景有两种:通知栏和桌面小部件,跨进程更新界面
-
2.创建Remote Views:只要提供当前应用的包名和布局文件的资源id即可创建一个RemoteViews对象
-
3.RemoteViews作用:在其它进程中显示并更新View界面
-
4.书上很多东西都过时了或者在Android8.0上会出现问题,下面的总结都是在Android8.0上运行成功的,会有一些需要注意的地方
-
5.由于运行在不同的进程中,所以RemoteViews无法像正常的View一样更新UI。 RemoteViews提供了一系列的set方法,但是这些set方法只是View全部方法的子集。 RemoteView支持的View的类型也是有限的。
-
6.使用 构造方法 最常用的是下面的这个构造方法,第一个参数是包名,第二个是加载的布局资源文件。
public RemoteViews(String packageName, int layoutId) { this(getApplicationInfo(packageName, UserHandle.myUserId()), layoutId); }
-
7.支持的View类型, 只支持以下的View,不支持它们的子类和其他类型的View,所以无法在RemoteViews中自定义View
FrameLayout、LinearLayout、RelativeLayout、GridLayout、AnalogClock、 Button、Chronometer、ImageButton、ImageView、ProgressBar、TextView、 ViewFlipper、ListView、GridView、StackView、AdapterViewFlipper、ViewStub
-
8.提供的方法 RemoteViews没有提供findViewById(),因为无法直接访问View元素,必须通过RemoteView提供的一系列set方法。
六、Android的Drawable
Drawable 表示一种图像概念,但又不全是图片,通过颜色也可以构出各样的图像效果,一般通过xml来定义
优点:首先,它使用简单,比自定义View的成本低;其次,非图片类型的Drawable占用空间小
分类:BitmapDrawable ShapeDrawble。 LayerDrawable StateListDrawable等
使用范围:1.作为ImageView中的图像来显示 2.作为View的背景
核心方法:draw方法
七、Android动画深入分析
- 1.种类:View动画 帧动画和属性动画
- 2.View动画:支持4种动画效果:平移动化(translate) 缩放动化(scale) 旋转动化(rotate) 和透明度动画(alpha) ,自定义View动画很少使用,一般使用xml
- 3.属性动画 api 11 增加,开源动画库nineoldandroids 兼容前后 ,使用代码来实现属性动画
- 4.插值器:Interpolator 影响动画的速度 TimeInterpolator 时间插值器 , 估值器 TypeEvaluator 根据百分比计算改编后的属性
- 5.注意事项:OOM问题、内存泄漏、兼容性问题、不要使用px
八、理解Window和WindowManager
- 1.Android中所有的视图都是通过window来呈现的,附加在window上。
- 2.WindowManager是外界访问window的入口,具体实现方法位于WindowManagerService中
- 3.Window是一个抽象概念,每一个Window都对应着一个View和一个ViewRootImpl,Window和View通过ViewRootImpl来建立联系,因此Window并不是实际存在的,它是以View的形式存在
- 4.Activity和Dialog中的window的创建是通过PolicyManager的makeNewWindow方法来完成的
- 5.Toast具有定时取消这一功能,采用Handler,具有IPC过程
九、四大组件的工作过程
- 1.BroadcastReceiver既可以在AndroidMainfest中注册也可以通过代码来注册。其它三种组件必须在AndroidMainfest中注册
- 2.在调用方式上:Activity/Serivice/BroadcastReceiver需要借助intent,尔ContentProvider无需借助intent
- 3.Activity组件是可以停止的,是一个前台界面角色
- 4.Activity组件只有一种运行模式,即Activity处于启动模式,Service:启动和绑定模式,停止:stopService和unBindService
- 5.广播注册有两种方式:静态注册:安装时会被系统解析;动态注册:Context.registerReceiver(),不需要停止
十、Android的消息机制
- 1.Android的消息机制主要是指Handler的运行机制,它的运行需要底层MessageQueue和Looper的支持。MessageQueue采用单链表的数据结构,只是一个消息存储单元;Looper可以处理消息,无限循环的去查询是否有新消息;
- 2.如果使用Handler就必须为线程创建Looper,我们常说的主线程即ActivityThread,创建时候就会默认创建Looper
- 3.Android的UI控件不是线程安全的,加锁缺点:1.UI访问逻辑变复杂2.降低UI访问效率
- 4.ThreadLocal的好处:通过ThreadLocal就可以实现Looper在线程中的存取。如果不采用它,那么系统就必须提供一个全局的哈希表,这样一来就必须提供一个类似于LooperManager的类了。
十一、Android的线程和线程池
- 1.AsyncTask底层用到了线程池;IntentService和HandlerThread底层直接使用了线程
- 2.不同形式的线程具有不同的特性和使用场景,AsyncTask封装了线程池和Handler,主要是为了方便在子线程中更新UI;IntentService是一种服务;HandlerThread内部使用Handler,具有消息循环的线程
- 3.线程是系统调度的最小单元,但又是一种受限的系统资源,做到线程并发,除非线程数量小于cpu核心数,这是不可能的。通过线程池可以避免频繁创建和销毁线程所带来的系统开销
- 4.AsyncTask封装了Thread和Handler,不适合进行特别耗时的后台任务;
onPreExecute()-doInBackground()-onProgressUpdate()-onPostExecute()
AsyncTask的类必须在主线程中加载 - 5.Android中的线程池来源于Java中的Executor,Exector是一个接口,真正的实现是
ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<runnable> workQueue,ThreadFActory threadFactory)
十二、Bitmap的加载和Cache
-
1.Android对单个应用施加的内存限制,比如16MB,这导致加载Bitmap的时候很容易出现内存泄出
-
2.目前常用的缓冲策略是LruCache(用做内存缓冲)和DiskLruCache(存储缓冲);Lru(Least Recently Used)最近最少使用算法,核心思想是:当缓冲快满时,淘汰最少使用的缓冲目标
-
3.高效的加载图片:BitmapFactory提供了四类方法:decodeFile(文件系统)、decodeResource(资源)、decodeStream(输入流)、 decodeByteArray(字节数组),来加载出Bitmap,最终是在底层实现的
-
4.BitmapFactory.Options来加载所需尺寸的图片,主要参数:insampleSize
十三、综合技术
- 1.使用CrashHandler来获取应用的crash信息,当crash发生的时候,系统就会回调UncaughtException的uncaughtException方法,在uncaughtException方法中就可以获取到异步信息
- 2.使用Multidex来解决方法数越界,Android中的单个dex文件包含的最大方法数时65536,包含Framework、一来的jar包以及应用本身的代码中的所有方法。为了解决这个问题,google提出了multidex的解决方案,5.0之后,默认支持,可以从apk中加载多个dex文件
- 3.Android的动态加载技术必须解决的三个基础问题:资源访问,Activity生命周期的管理和ClassLoader的管理。用到了反射和代理
- 4.反编译:使用dex2jar和jd-gui反编译apk,使用apktool对apk进行二次打包
十四、JNI和NDK编程
- 1.Java JNI的本意是Java Native Interface (Java本地接口),它是为了方便Java调用C、C++等本地代码所封装的一层接口。
- 2.NDK是Android所提供的一个工具集合,通过NDK可以在Android中更加方便地通过JNI来访问本地代码C、C++。NDK还提供了交叉编译器,只需要简单修改mk文件即可以生成特定平台cpu平台的动态库。
- 3.使用NDK好处:提高代码的安全性/很方便的使用目前已有的C/C++开源库/便于平台间的移植
- 4.JNI的开发流程:(1)在Java中申明native方法 (2)编译Java源文件得到class文件,然后通过javah命令到处JNI的头文件(3)实现JNI方法 (4)编译so库并在Java中调用
- 5.JND的开发流程:(1)下载并配置NDK (2)创建一个Android项目,并声明所需的native方法(3)实现Android项目中所声明的native方法(4)切换到jni目录的父目录,然后通过ndk-build命令编译产生的so库
- 6.JNI的数据类型和类型签名 (可百度)
十五、Android性能优化
- 1.OOM:过多的使用内存导致程序内存溢出
- 2.ANR:过多的使用CPU资源,一般指做大量的耗时任务,导致手机变得卡顿甚至出现程序无法响应问题
- 3.性能优化方法:布局优化、绘制优化、内存泄漏优化、响应速度优化、ListView优化、Bitmap优化、线程优化
- 4.内存泄漏:它并不会导致程序功能异常,但是会导致Android程序的内存占用过大,提高内存溢出的发生几率
- 5.代码的可维护性和可扩展性:通过合理的设计原则去完成,如良好的代码风格、清晰的代码层级、代码的可扩展性和合理的设计模式
欢迎交流,互相学习,感谢大家一直以来的关注,谢谢