Zygote进程启动过程
上篇文章《浅析Android系统启动过程》简要讲解了Android系统整体启动过程,今天我们看一下其中一个重要的过程:Zygote进程是如何启动的。
文中源码基于Android 8.0
概览Zygote进程是通过init进程启动起来的,我们直接看Zygote进程的入口函数,位于ZygoteInit类中的main方法:
1234567891011121314public class ZygoteInit { public static void main(String argv[]) { ZygoteServer zygoteServer = new ZygoteServer(); //创建Socket zygoteServer.registerServerSocket(socketName); //预加载类和资源 preload(bootTimingsTraceLog); //启动SystemServer进程 startSyst ...
设计模式(三)工厂方法模式
简单工厂、工厂方法原理比较简单,在实际的项目中也比较常用。而抽象工厂的原理稍微复杂点,在实际的项目中相对也不常用。上篇文章《设计模式(二)简单工厂模式》讲了简单工厂模式,我们今天就来看一下工厂方法模式。
工厂方法模式工厂方法模式的结构图如下所示:
AbstractFactory:抽象工厂类,提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品。
Factory:工厂类,负责实现创建所有实例的内部逻辑。创建产品类的方法可以被外界直接调用,创建所需的产品对象。
AbstractProduct:抽象产品类,这是简单工厂模式所创建的所有对象的父类。
Product:具体产品类,继承自抽象产品类。
下面用代码来实现一下:
创建抽象产品
123abstract class Phone { public abstract void start();}
创建具体产品
1234567891011121314151617181920class OppoPhone extends Phone { @Overr ...
设计模式(二)简单工厂模式
一般情况下,工厂模式分为三种更加细分的类型:简单工厂、工厂方法和抽象工厂。不过,在 GoF 的《设计模式》一书中,它将简单工厂模式看作是工厂方法模式的一种特例,所以工厂模式只被分成了工厂方法和抽象工厂两类。实际上,前面一种分类方法更加常见,所以,在今天的讲解中,我们沿用第一种分类方法。
简单工厂、工厂方法原理比较简单,在实际的项目中也比较常用。而抽象工厂的原理稍微复杂点,在实际的项目中相对也不常用。我们今天就来看一下简单工厂模式。
简单工厂(Simple Factory)定义:定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。
简而言之就是在使用一个具体对象的时候,我们不直接new一个对象,而是通过一个单独的工厂类来new这个对象。
简单工厂模式的结构图如下所示:
Factory:工厂类,负责实现创建所有实例的内部逻辑。创建产品类的方法可以被外界直接调用,创建所需的产品对象。
AbstractProduct:抽象产品类,这是简单工厂模式所创建的所有对象的父类。
Product:具体产品类,继承自抽象 ...
Java高级特性(二)注解处理 之 3分钟写半个Retrofit框架
上篇文章《Java高级特性(一)注解的分类及使用》讲了注解相关的基础知识,但是基本的注解声明和使用,并不能发挥注解的真正效果。如果要让注解产生实际的作用,就需要搭配注解处理器来使用。至于为什么说写半个Retrofit框架,因为本文只涉及到Retrofit框架中关于注解处理的内容(大佬轻喷)。
我们先回顾一下Retrofit是怎么用的?(代码摘自Retrofit官网)
第一步:定义一个接口,接口里面定义方法,使用@GET、@POST等注解标注我们定义的方法;
1234public interface GitHubService { @GET("users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user);}
第二步:创建retrofit实例,然后调用retrofit.create()方法,将我们定义的接口.class传入create方法。通过create方法生成实现了我们定义的接口的代理对象;
...
Java高级特性(一)注解的分类及使用
注解分类注解分为标准注解和元注解
标准注解标准注解有以下几种:
@Override:对覆盖超类中的方法进行标注,如果被标注的方法并没有实际覆盖超类中的方法,编译器会发错错误警告。
@Deprecated:对不鼓励使用或已过时的方法进行标注,当开发人员对这些被标注的方法进行调用时,会显示该方法已过时的提示信息。
@SuppressWarnings:选择性的取消特定代码段中的警告。
@SafeVarargs:JDK 7 新增的注解,用来声明使用了可变长度参数的方法,其在与泛型类一起使用时会出现类型安全问题。
元注解元注解是用来标注注解的注解,在注解定义时使用。有以下几种:
@Targe:标注所修饰的对象范围。
@Inherited:表示注解可以被继承。
@Documented:表示注解应该被JavaDoc工具记录。
@Retention:用来声明注解的保留策略。
@Repeatable:JDK 8 新增的注解,允许一个注解在同一声明类型(类、属性或方法)中多次使用。
下面重点介绍下@Targe注解及@Retention注解:
@Targe注解其中@Targe注解的取值是一个Elem ...
Java多线程(二)Java内存模型
Java 内存模型(JMM)是一种抽象的概念,并不真实存在,它描述了一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段、静态字段和构成数组对象的元素)的访问方式。JVM中的堆内存用来存储对象实例,堆内存是被所有线程共享的运行时内存区域,因此它存在可见性问题。Java内存模型定义了线程和主存间的抽象关系:线程之间的共享变量存储在主存中,每个线程有一个私有的本地内存,本地内存中存储了该线程共享变量的副本。需要注意的是本地内存是Java内存模型的一个抽象概念,并不真实存在,它涵盖了缓存、写缓冲区、寄存器等区域。Java内存模型的抽象示意图如下所示:
线程A与线程B要通信的话,要经历下面两个步骤:
线程A把线程A本地内存中更新过的内存共享变量刷新到主存;
线程B到主存中取线程A之前更新过的共享变量。
所以我们在执行下面语句:
1int i = 0;
语句所在的线程会对变量i所在的缓存进行赋值操作,然后再写入主存中,而不是直接将数值0写入主存。
为了有个直观的感受,我们用一段代码来实现一下。先定义一个类VolatileDemo,包含一个running字段和一个stop方法:
1 ...
Java多线程(一)线程状态及线程创建方式
Java多线程编程作为每一个Android Coder都必须掌握的技术,今天我们就来聊一聊关于Java多线程的点点滴滴。Android沿用了Java的线程模型,一个Android应用创建时会开启一个线程,这个线程就是我们熟知的主线程,也叫UI线程。如果我们在主线程直接进行网络请求,系统会直接报错,提示不能在主线程请求网络,至于问什么,是因为网络访问是一个耗时的操作,如果网络访问很慢,就会导致ANR(Application Not Response),从Android3.0开始,系统就要求网络访问必须在子线程中进行,否则就会抛出异常。
关于线程和进程的描述以及二者的关系,网络上一搜一大把,这里就不再赘述,我们主要来看一下线程的各种状态。
线程的状态
New:新创建状态。线程被创建,还没调用start方法。
Runnable:可运行状态。一旦调用了start方法,线程就处于Runnable状态。
Blocked:阻塞状态。线程被锁阻塞。
Waiting:等待状态。线程暂时不活动,也不运行任何代码,直到线程调度器重新激活它。
Timed waiting:超时等待状态。和等待状态不同的是,它可 ...
View体系(十一)View的draw流程
之前的文章《View体系(六)View工作流程入口》提到View的工作流程包括了measure、layout和draw的过程,今天我们就来看一下View的draw流程是怎样的。
(注:文中源码基于 Android 12)
View的draw流程很简单,源码里的注释官方也写的很清楚,我们看View的draw方法:
12345678910111213141516171819202122public void draw(Canvas canvas) { ... // Step 1, draw the background, if needed drawBackground(canvas); ... // skip step 2 & 5 if possible (common case) ... // Step 2, save the canvas' layers ... // Step 3, draw the content onDraw(canvas); ... // Step 4, d ...
View体系(十)从LinearLayout分析View的布局流程
之前的文章《View体系(六)View工作流程入口》提到View的工作流程包括了measure、layout和draw的过程,上两篇文章《View体系(八)深入剖析View的onMeasure方法》和《View体系(九)从LinearLayout分析ViewGroup的测量流程》分别对View和ViewGroup的measure过程做了分析,今天我们就来看一下View的layout过程是怎样的。
(注:文中源码基于 Android 12)
先看View的layout方法:
123456public void layout(int l, int t, int r, int b) { ... boolean changed = isLayoutModeOptical(mParent) ? setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);//1 ... onLayout(changed, l, t, r, b);//2
layout方法很长,这里只贴出关键代码。layou ...
View体系(九)从LinearLayout分析ViewGroup的测量流程
之前的文章《View体系(八)深入剖析View的onMeasure方法》我们深入分析了View的onMeasure方法,我们今天就来看一下ViewGroup的测量流程。
(注:文中源码基于 Android 12)
在View做测量时,会调用View的onMeasure方法,但是我们翻看ViewGroup的源码,并没有发现onMeasure方法,难道ViewGroup不用测量?显然不是,我们换一个类来看,LinearLayout继承自ViewGroup,我们从LinearLayout的源码中找到了熟悉的onMeasure方法,我们看一下源码:
1234567891011public class LinearLayout extends ViewGroup { ... @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (mOrientation == VERTICAL) {//1 ...