Android基础要点

一、Activity的启动模式
1)4种LaunchMode

(1)standard
(2)singleTop
(3)singleTask
(4)singleInstance

2)taskAffinity可指定任务栈。
3)Activity的Flags

(1)FLAG_ACTIVITY_NEW_TASK
与singleTask一样
(2)FLAG_ACTIVITY_SINGLE_TOP
与singleTop一样
(3)FLAG_ACTIVITY_CLEAR_TOP
清空该Activity和该Activity之上的Activity
(4)FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
该Activity不会出现在历史Activity列表中。

二、Android多进程模式
1)开启多进程模式

(1)四大组件可在AndroidMenifest中指定android:process属性。
(2)通过JNI在native层fork一个进程。

2)多进程运行机制

(1)每个进程都分配一个独立的虚拟机,不同的虚拟机分配的内存地址不同,同一个类对象在不同的进程中有不同的副本。

2)多进程造成的问题:

(1)静态成员和单例模式完全失效。
(2)线程同步机制失效。
(3)SharedPreferences的可靠性下降。
(4)Application会多次创建。

3)实现跨进程的方式:

(1)Intent来传递数据。
(2)共享文件和SharedPreferences
(3)基于Binder的Messenger和AIDL
(4)Socket

3)Serializable和Parcelable对比

(1)Parcelable效率优于Serializable。
(2)Parcelable在不同版本的有差异,不可采用数据持久化。

4)Binder基础

(1)Binder是Android中跨进程通信方式,是ServiceManager连接Manager和相应ManagerService的桥梁。
(2)当客户端发起远程请求时,当前线程会被挂起直至服务端进程返回数据,如果一个远程方法很耗时的,不能再UI线程上发起远程请求。
(3)服务端的Binder运行在Binder线程中,Binder方法不管是否耗时都应同步实现。

三、View基础知识
1)View的位置

(1)View的4个顶点是View的top、left、right、bottom决定。
(2)View的width = right - left;height = bottom - top;

2)MotionEvent

(1)ACTION_DOWN:手指刚接触屏幕
(2)ACTION_MOVE:手指屏幕上移动
(3)ACTION_UP:手指从屏幕松开时。

3)TouchSlop

是系统所能识别出的被认为滑动的最小距离。获得最短滑动距离常量ViewConfiguration.get(getContext()).getScaledTouchSlop()。

4)VelocityTracker

速度追踪,用于追踪手指在滑动过程中的速度包括水平和竖直方向的速度。

//创建 velocityTracker
VelocityTracker velocityTracker = VelocityTracker.obtain();
//在View的onTouchEvent添加追踪事件
velocityTracker.addMovement(event);
...
//设定1000ms内滑动的距离
velocityTracker.computeCurrentVelocity(1000);
//x轴速度
int  xVelocity = velocityTracker.getXVelocity();
//y轴速度
int  yVelocity = velocityTracker.getYVelocity();
5)GestureDetector

手势检查,用于辅助测试用户的单击、滑动、长按、双击等行为。

6)Scroller

弹性滑动对象,用于实现View的弹性滑动。

四、View的事件分发机制
1)事件分发规则的三个重要方法

(1)public boolean dispatchTouchEvent(MotionEvent e)
用来进行事件的分发。如果事件能够当前View,那么此方法一定会被调用,返回结果受当前View的onTouchEvent和子View的dispatchTouchEvent方法的影响,表示是否消耗当前事件。
(2)public boolean onInterceptTouchEvent(MotionEvent e)
在dispatchTouchEvent方法中调用,用来判断是否拦截某个事件,如果当前View拦截某个事件,那么在同一个事件序列当中,此方法不会再次调用,返回结果表示是否拦截当前事件。
(3)public boolean onTouchEvent(MotionEvent e)
在dispatchTouchEvent方法中调用,用来处理点击事件,返回结果表示是否消耗当前事件,如果不消耗,则在同一个事件序列中,当前View无法再次受到事件。

2)分发事件拦截

(1)外部拦截
外部拦截需要重写父容器的onInterceptTouchEvent方法。在需要拦截的事件拦截,不需要拦截的事件不拦截。

public boolean onInterceptTouchEvent(MotionEvent event){
...
  switch(event.getAction()){
    case MotionEvent.ACTION_DOWN:
      intercepted = false;
      break;
    case MotionEvent.ACTION_MOVE:
      if(父容器需要当前点击事件){
        intercepted = true;
      }else{
          intercepted = false;
      }
      break;
    case MotionEvent.ACTION_UP:
      intercepted = false;
      break;
    default:
      break;
  }
...
}

(2)内部拦截
内部拦截需要重写子元素的dispatchTouchEvent方法。MotionEvent.ACTION_DOWN

public boolean dispatchTouchEvent(MotionEvent event){
...
  switch(event.getAction()){
    case MotionEvent.ACTION_DOWN:
      parent.requestDisallowInterceptTouchEvent(true);
      break;
    case MotionEvent.ACTION_MOVE:
      if(父容器需要当前点击事件){
       parent.requestDisallowInterceptTouchEvent(false);
      }
      break;
    case MotionEvent.ACTION_UP:
      break;
    default:
      break;
  }
...
  return super.dispatchTouchEvent(event);
}
五、View的工作原理
1)measure

(1)MeasureSpec.UNSPECIFIED
不限定,父View不限制子View的具体的大小,所以子View可以按自己需求设置宽高(前面说的ScrollView就给子View设置了这个模式,ListView就会自己确认自己高度)。
(2)MeasureSpec.EXACTLY
父View决定子View的确切大小或者math_parent,子View被限定在给定的边界里,忽略本身想要的大小。
(3)MeasureSpec.AT_MOST
最多的,子View最大可以达到的指定大小(当设置为wrap_content时,模式为AT_MOST, 表示子view的大小最多是多少。)

2)layout

(1)Layout的作用是ViewGroup用来确定子元素的位置,当ViewGroup得位置被确定后,它会在onLayout中会遍历所有的子元素并调用其layout,在layout方法中onLayout方法又会被调用。
(2)View的测量宽和最终宽有什么区别?在View的默认实现中,View的宽和最终的宽是相等的。只不过测量宽形成于measure过程,最终宽形成于View的layout过程。高也是一样。

3)draw

(1)绘制背景background.draw(canvas);
(2)绘制自己(onDraw)
(3)绘制children(dispathDraw)
(4)绘制装饰(onDrawScrollBars)

4)自定义View分类

(1)继承View重写onDraw方法
(2)继承ViewGroup派生特殊的Layout
(3)继承特定的View(比如TextView)
(4)继承特定的ViewGroup(比如LinearLayout)

5)自定义View注意点

(1)让View支持wrap_content
(2)让View支持padding
(3)不要在View中使用Handle
(4)View中有线程和动画,需要及时停止,参考View#onDetachedFromWindow
(5)滑动嵌套时,处理好滑动冲突

六、Android消息机制
1)Handler的工作原理

(1)Handler的作用:需要在子线程进行耗时的I/O操作,当操作完成以后需要更新UI数据,由于Android开发上的规范限制,我们不能在子线程上直接更新UI数据,这时候通过Handler就可以将跟新UI的操作切换到主线程上。
(2)当Handler的send方法被调用时,它会调用MessageQueue的enqueueMessage方法并放入消息队列,当Looper发现有新的消息到来时,就会处理这个消息,最终消息中的Runnable或者handleMessage方法被调用.

2)MessageQueue工作原理

(1)MessageQueue不是真正的队列,而是采用单链表的数据结构。
(2)MessageQueue插入和读取方法为enqueueMessage和next

3)ThreadLocal工作原理

(1)ThreadLocal是一个线程内部的数据储存类,通过它可以在指定的线程中储存数据,储存之后,只有在指定线程中可以获取到存储的数据,对于其他线程无法取得数据。
(2)在ThreadLocal.Values localValues有一个内部数组table[],使用put方法储存到table中。
(3)ThreadLocal的储存规则:ThreadLocal在table数组中的储存位置总是为ThreadLocal的reference字段标识的对象下一个位置,比如ThreadLocal的reference对象在table数组中的索引为index,那么在table数组中的索引为index+1。

4)Looper工作原理

(1)Looper的退出方法:quit()或者quitSafely()。两者之间的区别:quit会直接退出Looper,quitSafely只是设定一个退出标识,然后把消息队列中已有消息处理完毕后才退出。
(2)Loop工作过程:loop方法是一个死循环,唯一跳出的方式是MessageQueue的next方法返回null。当Looper得quit或者quitSafely方法来通知消息队列退出,当被标识退出时,它的next才会返回null,否则无线循环。

七、Android线程
1)AsyncTask

(1)AsyncTask是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并在主线程中更新UI。
(2)AsyncTask必须在主线程中加载,也就是第一次访问AsyncTask必须在主线程中。
(3)AsyncTask的对象必须在主线程创建。
(4)不要在程序中直接调用onPreExecute()、onPostExecute()、doInBackground和onProgressUpdate()
(5)一个AsyncTask对象只能执行一次,即只能调用一次execute方法,否则会包异常。
(6)Android 1.6之前AsyncTask是串行执行任务,1.6之后采用并行任务,3.0之后又改成串行。线程池总大小128(maximumPoolSize),还有一个缓冲队列(sWorkQueue,缓冲队列可以放10个任务),1个核心线程。

2)HandlerThread

(1)HandlerThread继承了Thread,是一种可以使用Handler的Thread。
(2)使用quit或quitSafely方法。

3)IntentService

(1)IntentService比较适合执行一些高优先级的后台任务,优先级越高越不容易被系统杀死。
(2)IntentService通过stopSelf()和stopSelf(int startId)来停止服务。stopSelf会立即停止服务,stopSelf(int startId)待所有消息处理完毕后才停止服务。

八、Android线程池
1)线程池的优缺点

(1)重用线程池中的线程,避免因为线程的创建和销毁所带来的性能开销。
(2)能有效控制线程池最大并发数,避免大量的线程之间因互相抢占系统资源而导致的阻塞现象。
(3)能够对线程进行简单的管理,并提供定时执行以及指定间隔循环执行等功能。

2)ThreadPoolExecutor

(1)如果线程池中的线程数量并未核心线程的数量,那么会直接启动一
个核心线程来执行任务。
(2)如果线程池中的线程数量已达到或者超过核心线程的数量,那么任务会被插入到任务列中排队执行。
(3)如果任务队列已满,这个时候如果线程数量并未达到线程池规定最大值,那么立刻启动一个非核心线程来执行任务。
(4)线程池已达到线程规定的最大值,那么就拒绝执行此任务,ThreadPoolExecutor会调用RejectedExecutionHandler的rejectedExecution方法来通知调用者。

3)线程池分类

(1)FixedThreadPool
FixedThreadPool是只有核心线程并且这些核心线程没有超时机制,队列也没有大小限制,线程数量固定的线程池。

(2)CachedThreadPool
CachedThreadPool是一种数量不定的线程池,只有非核心线程,最大线程数为Integer.MAX_VALUE。当线程池处于活动状态时,线程池会创建新的线程来处理新的任务,否则就会利用空闲线程来处理任务。空闲线程超时60s会被回收。比较适合执行大量耗时较少的任务。空闲线程几乎不占资源。

(3)ScheduledThreadPool
ScheduledThreadPool的核心线程数量是固定的,而非核心线程没有限制,非核心线程闲置时会被立即回收。主要用于执行定时和具有固定周期的重复任务。

(4)SingleThreadExecutor
SingleThreadExecutor只有一个核心线程,确保所有的任务都在同一个线程中按顺序执行。统一所有的外界任务到一个线程中,这使得任务之间不需要处理线程同步问题。

你可能感兴趣的:(Android基础要点)