设计模式(一)单例模式
单例设计模式(Singleton Design Pattern)理解起来非常简单。一个类只允许创建一个对象(或者实例),那这个类就是一个单例类,这种设计模式就叫作单例设计模式,简称单例模式。
定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
单例模式结构图如下:
Client为客户端,Singleton为单例类,Client通过调用Singleton.getInstance()方法获取实例对象。
下面介绍常见的6种单例写法:
饿汉式饿汉式的实现方式比较简单。在类加载的时候,instance 静态实例就已经创建并初始化好了,所以,instance 实例的创建过程是线程安全的。不过,这样的实现方式不支持延迟加载(在真正用到 instance 的时候,再创建实例),从名字中我们也可以看出这一点。具体的代码实现如下所示:
12345678910public class Singleton { private static Singleton instance = new Singleton(); private Singleton() { ...
View体系(八)深入剖析View的onMeasure方法
之前的文章《View体系(六)View工作流程入口》介绍了View是从什么地方开始它的工作流程的,《View体系(七)理解 MeasureSpec》介绍了View在measure流程时的一个重要参数。有了上两篇的铺垫,我们就来看一下View的onMeasure方法到底做了什么。
(注:文中源码基于 Android 12)
在View做测量时,会调用View的onMeasure方法:
1234protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));}
这里只调用了一个setMeasuredDimension方法,看它的注释:
This method must ...
浅析Android系统启动过程
Android系统的启动流程是十分复杂的,但是作为应用层的开发人员来说,了解其大致流程即可。
启动流程概览Android系统启动流程大致可以概括为以下的几个步骤:
启动电源及系统启动
引导程序BootLoader启动
Linux内核启动
init进程启动
Zygote进程启动
SystemServer进程启动
Launcher启动
关键进程在介绍启动流程之前,先来了解一下几个关键的进程及其作用:
init进程init进程是Android系统中用户空间的第一个进程,进程号为1,是Android系统启动流程中的一个关键进程。它被赋予很多重要的工作职责,比如创建Zygote(孵化器)和属性服务等。init进程是由多个源文件组成的,这些文件位于源码目录system/core/init中。
Zygote进程在Android系统中,DVM和ART、应用程序进程以及运行系统关键服务的SystemServer进程都是由Zygote进程来创建的,我们也可以将其称为孵化器。它通过fork(复制进程)的形式来创建应用程序进程和SystemServer进程。由于Zygote进程在启动时会创建 ...
View体系(七)理解 MeasureSpec
MeasureSpec是View的内部类,MeasureSpec 封装了从父级传递到子级的测量要求。每个 MeasureSpec 代表对宽度或高度的要求。 MeasureSpec 由大小和模式两部分组成。
更详细的说明请看 Google官方文档
下面是MeasureSpec的源码:(基于Android 12)
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768public static class MeasureSpec { private static final int MODE_SHIFT = 30; private static final int MODE_MASK = 0x3 << MODE_SHIFT; public static final int UNSPECIFIED = 0 << MODE_SHIFT; ...
View体系(六)View工作流程入口
View的工作流程,就是View进行measure、layout和draw的过程,本篇文章我们就来一起看一下View是如何开始他的工作流程的。
(注:文中源码基于 Android 12)
在上篇文章《View体系(五)熟悉又陌生的setContentView》中我们讲过Activity的结构,包括了Activity、PhoneWindow及DecorView。讲了PhoneWindow的创建和DecorView的创建,但此时DecorView还没有加载到PhoneWindow中,下面我们就从源码看一下DecorView是如何加载到PhoneWindow中的。
当我们调用Activity的startActivity时,最终会调用到ActivityThread的handleLaunchActivity,代码如下:
android.app.ActivityThread
12345public Activity handleLaunchActivity(ActivityClientRecord r, PendingTransactionActions pendingAct ...
View体系(五)熟悉又陌生的setContentView
为什么说setContentView熟悉呢?因为该方法是我们从入门Android开发就接触的一个方法,在我们写过的每一个Activity中都有他的身影。但为什么又说setContentView陌生呢?因为我们在日常的开发中只知道用,并没有深入分析该方法是怎么将我们传入的layout资源id变为一个可视的界面的。今天我们就来揭开这层神秘的面纱,扒一扒其中的原理(注:源码基于Android12)。
因为我们日常开发的Activity最终都会继承自android.app.Activity,所以先看Activity类的setContentView方法:
android.app.Activity
1234public void setContentView(@LayoutRes int layoutResID) { getWindow().setContentView(layoutResID); //1 initWindowDecorActionBar();}
可以看到注释1处其实是调用了getWindow()的setContentView方法,我们再看get ...
View体系(四)深入理解事件分发机制
上篇文章《View体系(三)初探View事件分发机制》对View的事件分发机制进行了粗略的讲解,并用代码实际探究了View事件的传递和处理过程。这篇文章就对View的事件分发机制进行一个更深入的讲解。之前提到过事件分发机制中的三个方法:dispatchTouchEvent(MotionEvent event)、onInterceptTouchEvent(MotionEvent ev)和onTouchEvent(MotionEvent event),那么这三个方法到底有什么样的关联呢?他们的关系其实可以用如下的伪代码表示:
123456789public boolean dispatchTouchEvent(MotionEvent event) { boolean result = false; if (onInterceptTouchEvent(event)) { result = onTouchEvent(event); } else { result = child.dispatchTouchEv ...
View体系(三)初探View事件分发机制
事件分发机制,简而言之就是Android对触摸事件的一系列传递和处理的机制。在了解分发机制之前需要对下面三个方法有个大概的了解:
public boolean dispatchTouchEvent(MotionEvent event)
用来进行事件的分发。如果有事件传递给当前View,那么此方法一定会被调用。返回值受当前View的onTouchEvent(MotionEvent event)和子View的dispatchTouchEvent(MotionEvent event)方法的影响,表示是否消耗当前事件。
public boolean onInterceptTouchEvent(MotionEvent ev)
用来判断是否拦截事件,返回值表示是否拦截当前事件。
public boolean onTouchEvent(MotionEvent event)
用来处理事件,返回值表示是否消耗当前事件,如果不消耗,则在同一事件序列中,当前View无法再次接收到事件。
我们知道Android的View结构是树状结构的,View可以放在一个ViewGroup里,这个ViewGro ...
View体系(二)View滑动的六种方式
在日常开发中,有时会遇到需要对View进行滑动处理的情况,今天我们就一起来看一下如何实现View的滑动。
不管采用什么方式,实现思路基本是一致的:当触摸到View时,记下当前触摸点的坐标;当手指移动时,记下移动后触摸点的坐标,然后用两个坐标算出移动的偏移量,再利用偏移量来修改View的坐标。
下面分别来讲解实现View滑动的6种方式。
一、layout()layout()方法是View在进行布局流程时调用的一个方法,我们可以在移动View时调用次方法,不断的进行View的布局,达到滑动View的目的。具体过程如下:
(1)先自定义一个View,重写onTouchEvent(MotionEvent event)方法,在ACTION_DOWN时获取按下时的坐标。代码如下:
1234567891011@Overridepublic boolean onTouchEvent(MotionEvent event) { int x = (int) event.getX(); int y = (int) event.getY(); switch (event.getAct ...
View体系(一)基础知识
View 及ViewGroup在Android中,常用控件可大致分为两大类:View与ViewGroup。ViewGroup可包含多个View及ViewGroup,形成一个树状结构。需要注意的是ViewGroup也继承自View。View及ViewGroup组织结构如下:
坐标系在Android中有两种坐标系:Android坐标系和View坐标系。了解坐标系是对View进行更多操作的基础。
Android坐标系以屏幕左上角为原点,原点向右为X轴正方向,原点向下为Y轴正方向。在触控事件中,getRawX()、getRawY()获取的坐标也是Android坐标系的坐标。
View坐标系View坐标系是以View为基础的坐标系,搞清楚下图的关系也就清楚了View坐标系。
下面解释一下上图中涉及到的各个方法。其中下面4个方法可在View中直接获取:
getTop():获取View顶边到父View顶边的距离
getBottom():获取View底边到父View顶边的距离
getLeft():获取View左边到父View左边的距离
getRight():获取View右边到父View左边的距离
...