| 看一下mTraversalRunnable final class TraversalRunnable implements Runnable {  @Override  public void run() {  doTraversal();  }  } final TraversalRunnable mTraversalRunnable = new TraversalRunnable();    void doTraversal() {  if (mTraversalScheduled) {  mTraversalScheduled = false;  mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);  performTraversals();  }  }  
 在TraversalRunnable中,执行doTraversal.并在doTraversal执行performTraversals(),是不是看到了我们熟悉的performTraversals()了?是的,在这里才开始View的绘制工作. 在ViewRootImpl中的performTraversals(),这个方法代码很长(大约800行代码),大致流程是 
    判断是否需要重新计算视图大小,如果需要就执行performMeasure()是否需要重新安置所在的位置,performLayout()是否需要重新绘制performDraw() 那么是什么导致View的重绘呢?这里总结了3个主要原因 
    视图本身内部状态(enable,pressed等)变化,可能引起重绘View内部添加或者删除了ViewView本身的大小和可见性发生了变化 View的绘制流程 在上一小节了,讲述了performTraversals()的是被WMS IPC调用执行的.View的绘制流程一般是 从performTraversals -> performMeasure() -> performLayout() ->  performDraw(). 下面看一下performMeasure() //ViewRootImpl private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {  if (mView == null) {  return;  }  Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure");  try {  mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);  } finally {  Trace.traceEnd(Trace.TRACE_TAG_VIEW);  }  }    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {  MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY  && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;  final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)  && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);  final boolean needsLayout = specChanged  && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);  if (forceLayout || needsLayout) {  mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;  resolveRtlPropertiesIfNeeded();  int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);  if (cacheIndex < 0 || sIgnoreMeasureCache) {  //在这里调用了onMeasure 方法  onMeasure(widthMeasureSpec, heightMeasureSpec);  mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;  }   }  } 
 最终调用了View的measure方法,而View中的measure()方法被定义成final类型,保证整个流程的执行.performLayout()和performDraw()也是类似的过程. 而对于程序员,自定义View只需要关注他提供出来几个对应的方法,onMeasure/onLayout/onDraw.  关于这方面知识的网上介绍的资料很多,也可以很容易的看到View及ViewGroup里面的代码,推荐看LinerLayout的源码理解这部分知识,在这里不详细展开. Android的绘图原理浅析 Android屏幕绘制 关于绘制,就要从performDraw()说起,我们来看一下这个流程到底是怎么绘制的. //ViewRootImpl //1  private void performDraw() {  try {  draw(fullRedrawNeeded);  } finally {  mIsDrawing = false;  Trace.traceEnd(Trace.TRACE_TAG_VIEW);  }  }    //2  private void draw(boolean fullRedrawNeeded) {  Surface surface = mSurface;  if (!surface.isValid()) {  return;  }    if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)) {  return;  }  }    //3  private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,  boolean scalingRequired, Rect dirty) {  Canvas canvas = mSurface.lockCanvas(dirty);  }  
 看代码执行流程,1—>2->3,  最终拿到了Java层的canvas,然后进行一系列绘制操作.而canvas是通过Suface.lockCanvas()得到的. (编辑:宣城站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |