Android 系统源码分析之View(一)

View类两万一千多行,在这里逐步分析。建议这篇blog对照Android View源码观看!!

/*     <tr>
 *         <td><code>{@link #onFinishInflate()}</code></td>
 *         <td>Called after a view and all of its children has been inflated
 *         from XML.</td>
 *     </tr>
 *
 *     <tr>
 *         <td rowspan="3">Layout</td>
 *         <td><code>{@link #onMeasure(int, int)}</code></td>
 *         <td>Called to determine the size requirements for this view and all
 *         of its children.
 *         </td>
 *     </tr>
 *     <tr>
 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
 *         <td>Called when this view should assign a size and position to all
 *         of its children.
 *         </td>
 *     </tr>
 *     <tr>
 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
 *         <td>Called when the size of this view has changed.
 *         </td>
 *     </tr>
 *
 *     <tr>
 *         <td>Drawing</td>
 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
 *         <td>Called when the view should render its content.
 *         </td>
 *     </tr>
 *
 *     <tr>
 *         <td rowspan="4">Event processing</td>
 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
 *         <td>Called when a new hardware key event occurs.
 *         </td>
 *     </tr>
 *     <tr>
 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
 *         <td>Called when a hardware key up event occurs.
 *         </td>
 *     </tr>
 *     <tr>
 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
 *         <td>Called when a trackball motion event occurs.
 *         </td>
 *     </tr>
 *     <tr>
 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
 *         <td>Called when a touch screen motion event occurs.
 *         </td>
 *     </tr>
 *
 *     <tr>
 *         <td rowspan="2">Focus</td>
 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
 *         <td>Called when the view gains or loses focus.
 *         </td>
 *     </tr>
 *
 *     <tr>
 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
 *         <td>Called when the window containing the view gains or loses focus.
 *         </td>
 *     </tr>
 *
 *     <tr>
 *         <td rowspan="3">Attaching</td>
 *         <td><code>{@link #onAttachedToWindow()}</code></td>
 *         <td>Called when the view is attached to a window.
 *         </td>
 *     </tr>
 *
 *     <tr>
 *         <td><code>{@link #onDetachedFromWindow}</code></td>
 *         <td>Called when the view is detached from its window.
 *         </td>
 *     </tr>
 *
 *     <tr>
 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
 *         <td>Called when the visibility of the window containing the view
 *         has changed.
 *         </td>
 *     </tr>
 */

View通过构造方法创建,onMeasure测量,Layout方法测量需要测量自身和子View,onLayout方法分配子View,onSizeChanged方法当视图大小发生改变时调用,onDraw方法用于Canvas的绘制内容,onTouchEvent触屏时调用,onFocusChanged焦点改变时调用,onWindowFocusChanged同理,onWindowVisibilityChanged视图可见性onDetachedFromWindow取消监听和相关事件,onAttachedToWindow绑定相关事件监听。

/*     android:id="@+id/my_button"
 *     android:layout_width="wrap_content"
 *     android:layout_height="wrap_content"
 *     android:text="@string/my_button_text"
 */

XML引用View控件,并分配ID

public class View implements Drawable.Callback, KeyEvent.Callback,
        AccessibilityEventSource {
              .......
        }

这里实现的三个接口,先来看Drawable.Callback

 /**
     * Implement this interface if you want to create an animated drawable that
     * extends {@link android.graphics.drawable.Drawable Drawable}.
     * Upon retrieving a drawable, use
     * {@link Drawable#setCallback(android.graphics.drawable.Drawable.Callback)}
     * to supply your implementation of the interface to the drawable; it uses
     * this interface to schedule and execute animation changes.
     */
    public static interface Callback {
        /**
         * Called when the drawable needs to be redrawn.  A view at this point
         * should invalidate itself (or at least the part of itself where the
         * drawable appears).
         *
         * @param who The drawable that is requesting the update.
         */
        public void invalidateDrawable(Drawable who);

        /**
         * A Drawable can call this to schedule the next frame of its
         * animation.  An implementation can generally simply call
         * {@link android.os.Handler#postAtTime(Runnable, Object, long)} with
         * the parameters <var>(what, who, when)</var> to perform the
         * scheduling.
         *
         * @param who The drawable being scheduled.
         * @param what The action to execute.
         * @param when The time (in milliseconds) to run.  The timebase is
         *             {@link android.os.SystemClock#uptimeMillis}
         */
        public void scheduleDrawable(Drawable who, Runnable what, long when);

        /**
         * A Drawable can call this to unschedule an action previously
         * scheduled with {@link #scheduleDrawable}.  An implementation can
         * generally simply call
         * {@link android.os.Handler#removeCallbacks(Runnable, Object)} with
         * the parameters <var>(what, who)</var> to unschedule the drawable.
         *
         * @param who The drawable being unscheduled.
         * @param what The action being unscheduled.
         */
        public void unscheduleDrawable(Drawable who, Runnable what);
    }

View内部对外公开两个方法setCallback 、getCallback

 /**
     * Bind a {@link Callback} object to this Drawable.  Required for clients
     * that want to support animated drawables.
     *
     * @param cb The client's Callback implementation.
     *
     * @see #getCallback()
     */
    public final void setCallback(Callback cb) {
        mCallback = new WeakReference<Callback>(cb);
    }

    /**
     * Return the current {@link Callback} implementation attached to this
     * Drawable.
     *
     * @return A {@link Callback} instance or null if no callback was set.
     *
     * @see #setCallback(android.graphics.drawable.Drawable.Callback)
     */
    public Callback getCallback() {
        if (mCallback != null) {
            return mCallback.get();
        }
        return null;
    }

如果你想扩展View动画,可以实现Drawable.Callback,然后调用setCallback传入Callback的实现类即可invalidateDrawable()方法,在drawable重画时触发,展示Drawable部分将不可用。scheduleDrawable()用于控制动画的下一帧,用户可以通过mHandler.postAtTime(Runnable,Object)调用,unscheduleDrawable()方法则是取消scheduleDrawable()该方法定义的下一帧动画。这里的setCallback并不是我们常用的this.mCallback=mCallBack而是通过弱引用(引用类型:强引用 、软引用、弱引用、虚引用)引用,以便于GC回收,避免了内存泄露。getCallback()方法通过软引用调用抽象父类的get方法间接的调用native方法getReferent()。下面再来看KeyEvent.Callback接口定义。

 public interface Callback {
        /**
         * Called when a key down event has occurred.  If you return true,
         * you can first call {@link KeyEvent#startTracking()
         * KeyEvent.startTracking()} to have the framework track the event
         * through its {@link #onKeyUp(int, KeyEvent)} and also call your
         * {@link #onKeyLongPress(int, KeyEvent)} if it occurs.
         *
         * @param keyCode The value in event.getKeyCode().
         * @param event Description of the key event.
         *
         * @return If you handled the event, return true.  If you want to allow
         *         the event to be handled by the next receiver, return false.
         */
        boolean onKeyDown(int keyCode, KeyEvent event);

        /**
         * Called when a long press has occurred.  If you return true,
         * the final key up will have {@link KeyEvent#FLAG_CANCELED} and
         * {@link KeyEvent#FLAG_CANCELED_LONG_PRESS} set.  Note that in
         * order to receive this callback, someone in the event change
         * <em>must</em> return true from {@link #onKeyDown} <em>and</em>
         * call {@link KeyEvent#startTracking()} on the event.
         *
         * @param keyCode The value in event.getKeyCode().
         * @param event Description of the key event.
         *
         * @return If you handled the event, return true.  If you want to allow
         *         the event to be handled by the next receiver, return false.
         */
        boolean onKeyLongPress(int keyCode, KeyEvent event);

        /**
         * Called when a key up event has occurred.
         *
         * @param keyCode The value in event.getKeyCode().
         * @param event Description of the key event.
         *
         * @return If you handled the event, return true.  If you want to allow
         *         the event to be handled by the next receiver, return false.
         */
        boolean onKeyUp(int keyCode, KeyEvent event);

        /**
         * Called when multiple down/up pairs of the same key have occurred
         * in a row.
         *
         * @param keyCode The value in event.getKeyCode().
         * @param count Number of pairs as returned by event.getRepeatCount().
         * @param event Description of the key event.
         *
         * @return If you handled the event, return true.  If you want to allow
         *         the event to be handled by the next receiver, return false.
         */
        boolean onKeyMultiple(int keyCode, int count, KeyEvent event);
    }

KeyEnvent类继承自InputEvent,该类定义了许多keyCode值,例如:

 public static final int KEYCODE_SOFT_LEFT       = 1;
    /** Key code constant: Soft Right key.
     * Usually situated below the display on phones and used as a multi-function
     * feature key for selecting a software defined function shown on the bottom right
     * of the display. */
    public static final int KEYCODE_SOFT_RIGHT      = 2;
    /** Key code constant: Home key.
     * This key is handled by the framework and is never delivered to applications. */
    public static final int KEYCODE_HOME            = 3;
    /** Key code constant: Back key. */
    public static final int KEYCODE_BACK            = 4;
    /** Key code constant: Call key. */
    public static final int KEYCODE_CALL            = 5;

用户操作是只执行相应的回调函数,例如按住返回键,那么就会执行KeyEvent.Callback 的onKeyDown(KEYCODE_BACK,KeyEvent),在我们开发时,判断KeyEvent.getAction判断Action类型和keyCode值选择执行相应函数,return boolean 如果返回值为true代表处理该事件不在向下分发,false则不处理该事件。(Action是在KeyEvent构造参数时传入)Action在KeyEvent的定义如下:

 /**
     * {@link #getAction} value: the key has been pressed down.
     */
    public static final int ACTION_DOWN             = 0;
    /**
     * {@link #getAction} value: the key has been released.
     */
    public static final int ACTION_UP               = 1;
    /**
     * {@link #getAction} value: multiple duplicate key events have
     * occurred in a row, or a complex string is being delivered.  If the
     * key code is not {#link {@link #KEYCODE_UNKNOWN} then the
     * {#link {@link #getRepeatCount()} method returns the number of times
     * the given key code should be executed.
     * Otherwise, if the key code is {@link #KEYCODE_UNKNOWN}, then
     * this is a sequence of characters as returned by {@link #getCharacters}.
     */
    public static final int ACTION_MULTIPLE         = 2;
    //..........................此处略....................................

KeyEvent.Callback的onKeyUp方法也onKeyDown差别不大,区别在于事件的响应时间,一个是按下一个是抬起。View和Activity同时重写onKeyDown onkeyUp方法会先执行View的。


/**
 * This interface is implemented by classes source of {@link AccessibilityEvent}s.
 *
 * <div class="special reference">
 * <h3>Developer Guides</h3>
 * <p>For more information about making applications accessible, read the
 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
 * developer guide.</p>
 * </div>
 */
public interface AccessibilityEventSource {

    /**
     * Handles the request for sending an {@link AccessibilityEvent} given
     * the event type. The method must first check if accessibility is on
     * via calling {@link AccessibilityManager#isEnabled() AccessibilityManager.isEnabled()},
     * obtain an {@link AccessibilityEvent} from the event pool through calling
     * {@link AccessibilityEvent#obtain(int) AccessibilityEvent.obtain(int)}, populate the
     * event, and send it for dispatch via calling
     * {@link AccessibilityManager#sendAccessibilityEvent(AccessibilityEvent)
     * AccessibilityManager.sendAccessibilityEvent(AccessibilityEvent)}.
     *
     * @see AccessibilityEvent
     * @see AccessibilityManager
     *
     * @param eventType The event type.
     */
    public void sendAccessibilityEvent(int eventType);

    /**
     * Handles the request for sending an {@link AccessibilityEvent}. The
     * method does not guarantee to check if accessibility is on before
     * sending the event for dispatch. It is responsibility of the caller
     * to do the check via calling {@link AccessibilityManager#isEnabled()
     * AccessibilityManager.isEnabled()}.
     *
     * @see AccessibilityEvent
     * @see AccessibilityManager
     *
     * @param event The event.
     */
    public void sendAccessibilityEventUnchecked(AccessibilityEvent event);
}

sendAccessibilityEventUnchecked() (API级别4)当调用代码需要直接控制检查辅助功能设备的启用时,调用该方法。 sendAccessibilityEvent()(API级别4)当用户在一个视图操作时调用此方法。事件是按照用户操作类型分类,如TYPE_VIEW_CLICKED。你通常不需要实现该方法,除非你是创建一个自定义视图。

  private static final boolean DBG = false;

定义全局final变量DBG,如果是调试模式,在调用某些方法调试时输出日志,例如:

 protected boolean setFrame(int left, int top, int right, int bottom) {
        boolean changed = false;

        if (DBG) {
            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
                    + right + "," + bottom + ")");
        }
        //.......................此处略.......................
  }

Log.i/e/w(TAG,”“)方法中TAG定义:

 /**
     * The logging tag used by this class with android.util.Log.
     */
    protected static final String VIEW_LOG_TAG = "View";

下面的再来看一组变量定义:

   /**
     * When set to true, apps will draw debugging information about their layouts.
     *
     * @hide
     */
    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";


   /**
     * Show where the margins, bounds and layout bounds are for each view.
     */
    boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);

SystemProperties类位置在framework层,查看请点击SystemProperties,这里面的内容简单的封装了set get 方法,set get方法内部分别调用了native 方法代码如下:


/**
 * Gives access to the system properties store.  The system properties
 * store contains a list of string key-value pairs.
 *
 * {@hide}
 */
public class SystemProperties
{
    public static final int PROP_NAME_MAX = 31;
    public static final int PROP_VALUE_MAX = 91;

    private static final ArrayList<Runnable> sChangeCallbacks = new ArrayList<Runnable>();

    private static native String native_get(String key);
    private static native String native_get(String key, String def);
    private static native int native_get_int(String key, int def);
    private static native long native_get_long(String key, long def);
    private static native boolean native_get_boolean(String key, boolean def);
    private static native void native_set(String key, String def);
    private static native void native_add_change_callback();

      /**
     * Get the value for the given key, returned as a boolean.
     * Values 'n', 'no', '0', 'false' or 'off' are considered false.
     * Values 'y', 'yes', '1', 'true' or 'on' are considered true.
     * (case sensitive).
     * If the key does not exist, or has any other value, then the default
     * result is returned.
     * @param key the key to lookup
     * @param def a default value to return
     * @return the key parsed as a boolean, or def if the key isn't found or is
     *         not able to be parsed as a boolean.
     * @throws IllegalArgumentException if the key exceeds 32 characters
     */
    public static boolean getBoolean(String key, boolean def) {
        if (key.length() > PROP_NAME_MAX) {
            throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);
        }
        return native_get_boolean(key, def);
    }
    //.......................其他略...............................
}

该类的作用是获取设置系统属性,进行系统属性设置的程序也必须有system或root权限,
如何将android程序的权限提升到system权限?方法是这样的:
1.在AndroidManifest.xml中,在manifest加入android:sharedUserId=”android.uid.system”。
2.在Android.mk中,將LOCAL_CERTIFICATE := XXX修改成LOCAL_CERTIFICATE :=platform。
该类参考资料:http://blog.csdn.net/ameyume/article/details/8056492

 /**
     * Used to mark a View that has no ID.
     */
    public static final int NO_ID = -1;

NO_ID变量让属性的初始值引用,代码实例如下:

public View(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    //.............此处略.......................
     case com.android.internal.R.styleable.View_id:
       mID = a.getResourceId(attr, NO_ID);
       break;
     case com.android.internal.R.styleable.View_tag:
       mTag = a.getText(attr);
       break;
}

再来看一下三个变量定义:sCompatibilityDone 、sUseBrokenMakeMeasureSpec 、sIgnoreMeasureCache

   /**
     * Signals that compatibility booleans have been initialized according to
     * target SDK versions.
     */
    private static boolean sCompatibilityDone = false;
     /**
     * Use the old (broken) way of building MeasureSpecs.
     */
    private static boolean sUseBrokenMakeMeasureSpec = false;

    /**
     * Ignore any optimizations using the measure cache.
     */
    private static boolean sIgnoreMeasureCache = false;

这三个参数在构造方法里面进行了初始化赋值

 public View(Context context) {

  //..............此处略..................

  if (!sCompatibilityDone && context != null) {      
    final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
     // Older apps may need this compatibility hack for measurement.
     sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;

     // Older apps expect onMeasure() to always be called on a layout pass, regardless
     // of whether a layout was requested on that View.
     sIgnoreMeasureCache = targetSdkVersion < KITKAT;
     sCompatibilityDone = true;
     }
  }

sCompatibilityDone 有何意义我还没发现,待后续研究,sUseBrokenMakeMeasureSpec 变量用于判断使用哪一种方式(老版本的方法还是新版本的方法)构建MeasureSpec,MeasureSpec是测量相关,稍后再提。

 public static int makeMeasureSpec(int size, int mode) {
            if (sUseBrokenMakeMeasureSpec) {
                return size + mode;
            } else {
                return (size & ~MODE_MASK) | (mode & MODE_MASK);
            }
        }

sIgnoreMeasureCache 忽略任何优化使用缓存,在measure测量方法里会用到该参数,稍后再细说measure方法。接着来看一组焦点相关的变量定义:

  /**
     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
     * calling setFlags.
     */
    private static final int NOT_FOCUSABLE = 0x00000000;

    /**
     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
     * setFlags.
     */
    private static final int FOCUSABLE = 0x00000001;

    /**
     * Mask for use with setFlags indicating bits used for focus.
     */
    private static final int FOCUSABLE_MASK = 0x00000001;

在我们平时控制View的焦点响应方法setFocusable(boolean focusable)其本质就是在根据传入参数获取一个int 型 flag值,随后调用了setFlags隐藏方法;

 /**
     * Set whether this view can receive the focus.
     *
     * Setting this to false will also ensure that this view is not focusable
     * in touch mode.
     *
     * @param focusable If true, this view can receive the focus.
     *
     * @see #setFocusableInTouchMode(boolean)
     * @attr ref android.R.styleable#View_focusable
     */
    public void setFocusable(boolean focusable) {
        if (!focusable) {
            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
        }
        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
    }

View.setVisibility也是如此(同时还判断选择调用Drawale的setVisibilty,通过回调接口Drawable.Callback的 invalidateDrawable(this)方法控制重绘)

 /**
     * Set the enabled state of this view.
     *
     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
     * @attr ref android.R.styleable#View_visibility
     */
    @RemotableViewMethod
    public void setVisibility(@Visibility int visibility) {
        setFlags(visibility, VISIBILITY_MASK);
        if (mBackground != null) mBackground.setVisible(visibility == VISIBLE, false);
    }

隐藏方法setFlag对我来说无疑是神秘的,位运算搞得我头大,查了一番资料,马马虎虎明白其原理,位运算相关知识链接点击这里,该方法的具体实现如下:

 /**
     * Set flags controlling behavior of this view.
     *
     * @param flags Constant indicating the value which should be set
     * @param mask Constant indicating the bit range that should be changed
     */
    void setFlags(int flags, int mask) {
        final boolean accessibilityEnabled =
                AccessibilityManager.getInstance(mContext).isEnabled();
        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
        //old保存mViewFlags之前的值, (mViewFlags在构造方法里初始化了)     
        int old = mViewFlags;
        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
        //old和mViewFlags异或后得到一个新的changed 凡是为1 说明发送了变化, 就需要View系统进行调整了!
        int changed = mViewFlags ^ old;
        if (changed == 0) {




         /*********
            什么时候能有中文版注释的系统源码,偶滴神啊,头大了
            flags = 0x0000000100 
            int old = mViewFlags; //旧的flag  = 0x00000000  
            mViewFlags = (mViewFlags & ~mask) | (flags & mask); //新的flag   
            0x00000000  & ~(00000001100) | & 00000001100   =   0x0000000100 

            int changed = mViewFlags ^ old;  = 0x0000000100 
            if (changed == 0) { 
            return; //hey ! 没有变化! 直接return!

           ************/



            return;
        }

        //...............此处略..................

        /* Check if the GONE bit has changed */
        if ((changed & GONE) != 0) {
            needGlobalAttributesUpdate(false);
            requestLayout();

            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {

                //清除view的cache
                if (hasFocus()) clearFocus();
                clearAccessibilityFocus();
                destroyDrawingCache();

                if (mParent instanceof View) {
                    // GONE views noop invalidation, so invalidate the parent
                    //重绘
                    ((View) mParent).invalidate(true);
                }
                // Mark the view drawn to ensure that it gets invalidated properly the next
                // time it is visible and gets invalidated
                mPrivateFlags |= PFLAG_DRAWN;
            }
            if (mAttachInfo != null) {
                mAttachInfo.mViewVisibilityChanged = true;
            }
        }

          //........此处略....方法说明requestLayout():重新布局;invalidate(true):重绘..........
    }

半天多时间已去,第一篇View blog也出来了,我也先学先写,差了一些资料发现了很多以前不懂的知识,向下等看完View的所有源代码,对自己会有一个很大的提升,逗比的一天接近尾声,看会儿爱哥的设计模式去,坐等下班。

Android系统源代码情景分析》随书光盘内容(源代码) 目录如下: 第1篇 初识Android系统 第1章 准备知识 1.1 Linux内核参考书籍 1.2 Android应用程序参考书籍 1.3 下载、编译和运行Android源代码 1.3.1 下载Android源代码 1.3.2 编译Android源代码 1.3.3 运行Android模拟器 1.4 下载、编译和运行Android内核源代码 1.4.1 下载Android内核源代码 1.4.2 编译Android内核源代码 1.4.3 运行Android模拟器 1.5 开发第一个Android应用程序 1.6 单独编译和打包Android应用程序模块 1.6.1 导入单独编译模块的mmm命令 1.6.2 单独编译Android应用程序模块 1.6.3 重新打包Android系统镜像文件 第2章 硬件抽象层 2.1 开发Android硬件驱动程序 2.1.1 实现内核驱动程序模块 2.1.2 修改内核Kconfig文件 2.1.3 修改内核Makefile文件 2.1.4 编译内核驱动程序模块 2.1.5 验证内核驱动程序模块 2.2 开发C可执行程序验证Android硬件驱动程序 2.3 开发Android硬件抽象层模块 2.3.1 硬件抽象层模块编写规范 2.3.2 编写硬件抽象层模块接口 2.3.3 硬件抽象层模块的加载过程 2.3.4 处理硬件设备访问权限问题 2.4 开发Android硬件访问服务 2.4.1 定义硬件访问服务接口 2.4.2 实现硬件访问服务 2.4.3 实现硬件访问服务的JNI方法 2.4.4 启动硬件访问服务 2.5 开发Android应用程序来使用硬件访问服务 第3章 智能指针 3.1 轻量级指针 3.1.1 实现原理分析 3.1.2 应用实例分析 3.2 强指针和弱指针 3.2.1 强指针的实现原理分析 3.2.2 弱指针的实现原理分析 3.2.3 应用实例分析 第2篇 Android专用驱动系统 第4章 Logger日志系统 4.1 Logger日志格式 4.2 Logger日志驱动程序 4.2.1 基础数据结构 4.2.2 日志设备的初始化过程 4.2.3 日志设备文件的打开过程 4.2.4 日志记录的读取过程 4.2.5 日志记录的写入过程 4.3 运行时库层日志库 4.4 C/C++日志写入接口 4.5 Java日志写入接口 4.6 Logcat工具分析 4.6.1 相关数据结构 4.6.2 初始化过程 4.6.3 日志记录的读取过程 4.6.4 日志记录的输出过程 第5章 Binder进程间通信系统 5.1 Binder驱动程序 5.1.1 基础数据结构 5.1.2 Binder设备的初始化过程 5.1.3 Binder设备文件的打开过程 5.1.4 Binder设备文件的内存映射过程 5.1.5 内核缓冲区管理 5.2 Binder进程间通信库 5.3 Binder进程间通信应用实例 5.4 Binder对象引用计数技术 5.4.1 Binder本地对象的生命周期 5.4.2 Binder实体对象的生命周期 5.4.3 Binder引用对象的生命周期 5.4.4 Binder代理对象的生命周期 5.5 Binder对象死亡通知机制 5.5.1 注册死亡接收通知 5.5.2 发送死亡接收通知 5.5.3 注销死亡接收通知 5.6 Service Manager的启动过程 5.6.1 打开和映射Binder设备文件 5.6.2 注册为Binder上下文管理者 5.6.3 循环等待Client进程请求 5.7 Service Manager代理对象的获取过程 5.8 Service组件的启动过程 5.8.1 注册Service组件 5.8.2 启动Binder线程池 5.9 Service代理对象的获取过程 5.10 Binder进程间通信机制的Java接口 5.10.1 Service Manager的Java代理对象的获取过程 5.10.2 Java服务接口的定义和解析 5.10.3 Java服务的启动过程 5.10.4 Java服务代理对象的获取过程 5.10.5 Java服务的调用过程 第6章 Ashmem匿名共享内存系统 6.1 Ashmem驱动程序 6.1.1 基础数据结构 6.1.2 匿名共享内存设备的初始化过程 6.1.3 匿名共享内存设备文件的打开过程 6.1.4 匿名共享内存设备文件的内存映射过程 6.1.5 匿名共享内存块的锁定和解锁过程 6.1.6 匿名共享内存块的回收过程 6.2 运行时库cutils的匿名共享内存访问接口 6.3 匿名共享内存的C++访问接口 6.3.1 MemoryHeapBase 6.3.2 MemoryBase 6.3.3 应用实例 6.4 匿名共享内存的Java访问接口 6.4.1 MemoryFile 6.4.2 应用实例 6.5 匿名共享内存的共享原理 第3篇 Android应用程序框架 第7章 Activity组件的启动过程 7.1 Activity组件应用实例 7.2 根Activity组件的启动过程 7.3 子Activity组件在进程内的启动过程 7.4 子Activity组件在新进程中的启动过程 第8章 Service组件的启动过程 8.1 Service组件应用实例 8.2 Service组件在新进程中的启动过程 8.3 Service组件在进程内的绑定过程 第9章 Android系统广播机制 9.1 广播机制应用实例 9.2 广播接收者的注册过程 9.3 广播的发送过程 第10章 Content Provider组件的实现原理 10.1 Content Provider组件应用实例 10.1.1 ArticlesProvider 10.1.2 Article 10.2 Content Provider组件的启动过程 10.3 Content Provider组件的数据共享原理 10.3.1 数据共享模型 10.3.2 数据传输过程 10.4 Content Provider组件的数据更新通知机制 10.4.1 注册内容观察者 10.4.2 发送数据更新通知 第11章 Zygote和System进程的启动过程 11.1 Zygote进程的启动脚本 11.2 Zygote进程的启动过程 11.3 System进程的启动过程 第12章 Android应用程序进程的启动过程 12.1 应用程序进程的创建过程 12.2 Binder线程池的启动过程 12.3 消息循环的创建过程 第13章 Android应用程序的消息处理机制 13.1 创建线程消息队列 13.2 线程消息循环过程 13.3 线程消息发送过程 13.4 线程消息处理过程 第14章 Android应用程序的键盘消息处理机制 14.1 键盘消息处理模型 14.2 InputManager的启动过程 14.2.1 创建InputManager 14.2.2 启动InputManager 14.2.3 启动InputDispatcher 14.2.4 启动InputReader 14.3 InputChannel的注册过程 14.3.1 创建InputChannel 14.3.2 注册Server端InputChannel 14.3.3 注册系统当前激活的应用程序窗口 14.3.4 注册Client端InputChannel 14.4 键盘消息的分发过程 14.4.1 InputReader获得键盘事件 14.4.2 InputDispatcher分发键盘事件 14.4.3 系统当前激活的应用程序窗口获得键盘消息 14.4.4 InputDispatcher获得键盘事件处理完成通知 14.5 InputChannel的注销过程 14.5.1 销毁应用程序窗口 14.5.2 注销Client端InputChannel 14.5.3 注销Server端InputChannel 第15章 Android应用程序线程的消息循环模型 15.1 应用程序主线程消息循环模型 15.2 与界面无关的应用程序子线程消息循环模型 15.3 与界面相关的应用程序子线程消息循环模型 第16章 Android应用程序的安装和显示过程 16.1 应用程序的安装过程 16.2 应用程序的显示过程
Android ViewAndroid 中最基本的 UI 构建块之一,负责在屏幕上绘制视图并响应用户的操作。下面是一个简单的 View 源码分析过程: 1. 首先,我们需要了解 View 的继承关系。ViewAndroid 中所有 UI 组件的基类,它的直接子类包括 ViewGroup、TextView、ImageView 等。其中,ViewGroup 又是各种布局容器的基类,例如 LinearLayout、RelativeLayout 等。 2. 接着,我们可以查看 View 的基本属性。这些属性包括 layout_width、layout_height、padding、background 等。其中,layout_width 和 layout_height 决定了 View 在布局中的大小,padding 指定了 View 的内边距,background 则是 View 的背景。 3. View 的绘制过程可以分为两个阶段:测量和绘制。在测量阶段,View 会根据其 layout_width 和 layout_height 等属性计算出自身的尺寸。在绘制阶段,View 会将自身绘制到屏幕上。 4. View 的事件响应机制是 Android 中 UI 开发的重要部分。当用户触摸屏幕时,系统会将事件传递给 ViewView 会根据自身的点击区域判断是否响应该事件,并将事件传递给其父容器或下一个 View 进行处理。 5. 最后,我们可以查看 View源码实现,深入了解 View 的内部实现逻辑。例如,View 的测量和绘制过程是通过 onMeasure 和 onDraw 方法实现的,事件响应机制是通过 onTouchEvent 和 dispatchTouchEvent 方法实现的。 总的来说,理解 Android View源码实现可以帮助我们更好地理解 Android UI 开发的工作原理,从而编写出更高效、更灵活、更具交互性的应用程序。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值