Android
Activity
- Activity 生命周期
正常:
onCreate -> onStart -> onResume -> runing -> onPause -> onStop -> onDestory
异常终止:
调用onSavaInstanceState -> onRestoreInstanceState
(onStop 之前调用) (onStart之后调用)
Activity重新创建 设置configChanges可避免重新创建
- Activity 启动模式
LaunchMode : standand singleTop singleTask singleInstance
standand : 启动后Activity 默认进入启动他的Activity的任务栈,非Activity context 启动Activity时会报错,因为没有任务栈。需要指定FLAG_ACTIVITY_NEW_TASK 标记位置。实际上是以singleTask启动的。
singleTop : 位于栈顶不会重新创建,会调用onNewIntent方法。
singleTask : 位于栈中就不会重新创建,会调用onNewIntent方法。
singleInstance : 只能单独的位于一个栈中
两种设置方式:
launchMode指定, intent.addFlags
- Android 多进程
通过android:process指定, 通过调用fork()
Android为每个进程都分配一个独立的虚拟机
Serializable 接口 serialVersionUID
Parcelable 接口
Andriod 进程间通信
Binder Bundle 文件共享 AIDL Messenger ContentProvider Socket
Binder 机制:
主要是client-server机制,底层有ServiceManager 负责管理所有的service,所有的service都需要在ServiceManager中注册,之后client才能在ServiceManager中得到service的引用。client请求service的服务或数据,先在ServiceManager中查询,获取service的binder的引用,调用所需要的方法。由于service 中的binder方法和client中的binder方法是一一对应的,client调用方法时会发送指定方法的标示,service根据方法的标志识别调用哪个方法,此时client端是阻塞的。等待service端方法执行完成后,返回结果,client继续执行。相当于client拥有service的一个引用。
service向ServiceManager注册的时候也需要进程间通信,所以ServiceManager在初始化的时候指定自己的标志为0,service通过0来获取ServiceManager的引用,与其通信,此时service扮演的角色是client。
Andriod View
- view的坐标 是相对与父容器来说的,是相对坐标
- view 平移过程中,top left值不变,表示的是原始位置信息,改变的是x,y,translationX,translationY的值
- view 滑动三种方法:1.scrollTo/scrollBy 2.属性动画 3.修改layoutParams
- Scroller原理: 不断让view重绘,不断调用view的computeScroll方法。
- view 事件分发 : 对MotionEvent事件的分发
dispathTouchEvent
onInterceptTouchEvent
onTouchEvent
onTouchListener
onClickListener
dispathTouchEvent(){
if (onInterceptTouchEvent){
if (onTouchListener){
if (! onTouchListener.onTouch){
self.onTouchEvent(); -> if (onClickListener){listener.onClick}
}
}
}else {
child.dispathTouchEvent();
}
}
onTouchEvent(){
}
- view 滑动冲突处理
- 外部拦截:在父容器的onInterceptTouchEvent中进行拦截,
public boolean onInterceptTouchEvent(MotionEvent event){
boolean intercept = fasle;
int x = (int) event.getX();
int y = (int) event.getY();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
intercept = false;
break;
case MotionEvent.ACTION_MOVE:
if(parentIntercept()){
intercept = true;
}else {
intercept = false;
}
break;
case MotionEvent.ACTION_UP:
intercept = false;
break;
}
return intercept;
}
- 外部拦截:在子容器中进行处理,重写子容器的dispathTouchEvent,需要通过requestDisallowInterceptTouchEvent()设置父容器是否拦截,同时父容器需要重写onInterceptTouchEvent拦截除了ACTION_DOWN以外的事件。
//子容器
public boolean dispathTouchEvent(MotionEvent event){
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_MOVE:
if (parentIntercept()){
requestDisallowInterceptTouchEvent(false);
}
break;
case MotionEvent.ACTION_UP:
break;
}
return super.dispathTouchEvent(event);
}
//父容器
public boolean onInterceptTouchEvent(MotionEvent event){
if (event.getAction() == MotionEvent.ACTION_DOWN){
return false;
}
return true;
}
- view工作原理
DecorView(是一个FrameLayout)作为顶级view,一般包含一个竖直方向的LinearLayout,LinearLayout里有上下两部分,上面为titleBar,下面是android.R.id.content,所以是setContentView,view层事件都先经过DecorView。
MeasureSpec 32bit int值, 前2位代表specMode,后30位代表specSize
specMode 有三种:
UNSPECIFTED — 父容器不对view有任何限制
EXACTLY — 监测出view的精确大小,对应 match_parent 和具体数值
AT_MOST — 父容器指定一个可用的大小,view大小不能大于这个值,对应于 wrap_content
view 工作流程 measure layout draw
1. measure 直接继承view的自定义控件,如果不重写onMeasure,使用wrap_content效果和match_parent效果一样。
对于viewgroup,除了完成自己的measure,还要遍历调用所有子元素的measure。
onMeasure中经过计算,最终调用setMeasuredDimension()。
view 的 onMeasure和activity的onCreate onResume onStart方法不是同步执行的,不能保证执行onCreate等时view已经测量完成。如果没有测量完成,此时获取到的view的宽高为0。
获取view宽高为0解决方法:
1. onWindowFocusChanged() view此时已经初始化完毕,此方法会调用多次
2. view.post(new Runnable(){
public void run(){
int w = view.getMeasuredWidth();
int h = …;
}
})
3. ViewTreeObserver
ViewTreeObserver observer = view.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener(){
public void OnGlobalLayout(){
observer.removeGlobalOnLayoutListener(listener); //因为view树状态改变或者view可见性发生改变时都会调用OnGlobalLayout方法,所以此处注销监听器。
int w = …;
int h = …;
}
});
4. view.measure()中手动测量
layout view的layout中调用onLayout,onLayout中遍历调用子元素的layout。
draw 流程
- 绘制背景
- 绘制自己 onDraw()
- 绘制children dispathDraw()
- 绘制装饰 onDrawScrollBars()
android 消息机制
Handler MessageQueue Looper ThreadLocal
android 缓存图片
LruCache(LinkedHashMap) DiskLruCache
BitmapFactory.Options 加载缩小后的图片
android 性能优化
- 内存泄露优化
- 静态变量导致内存泄露,
例:
static Context context;
onCreate(){
context = this;
}
static View view;
onCreate(){
view = new View(this);
}
单例模式导致内存泄露
属性动画导致内存泄露