Startup强化篇

1,150 阅读1分钟

官改

Initializer

public interface Initializer extends Runnable {
    // 返回一些依赖项
    // 决定初始化顺序
    List<Class<? extends Initializer>> dependencies();
}

Startup

void init(Class<? extends Initializer> component) {
    try {
        // 1 通过反射实例化
        Object instance = component.getDeclaredConstructor().newInstance();
        Initializer initializer = (Initializer) instance;
        List<Class<? extends Initializer>> list = initializer.dependencies();

        // 2 遍历依赖,递归初始化
        if (list != null && !list.isEmpty()) {
            for (int i = 0; i < list.size(); i++) {
                init(list.get(i));
            }
        }

        // 3 初始化
        initializer.run();
    } catch (Throwable t) {
        throw new StartupException(t);
    }
}           

1)通过反射实例化

2)遍历依赖,递归初始化

3)初始化

缓存去重

final Set<Class<? extends Initializer>> mInitialized;

void init(Class<? extends Initializer> component) {
    try {
        // 1 检查初始化记录
        if (!mInitialized.contains(component)) {
            Object instance = component.getDeclaredConstructor().newInstance();
            Initializer initializer = (Initializer) instance;
            List<Class<? extends Initializer>> list = initializer.dependencies();

            if (list != null && !list.isEmpty()) {
                for (int i = 0; i < list.size(); i++) {
                    // 2 循环检查依赖的初始化记录
                    if (!mInitialized.contains(list.get(i))) {
                        init(list.get(i));
                    }
                }
            }

            initializer.run();
            // 3 缓存初始化记录
            mInitialized.add(component);
        }
    } catch (Throwable t) {
        throw new StartupException(t);
    }
}

1)检查初始化记录

2)遍历检查依赖的初始化记录

3)缓存初始化记录

循环依赖

public void init(Class<? extends Initializer> component) {
    doInitialize(component, new HashSet<>());
}

void doInitialize(Class<? extends Initializer> component, Set<Class<?>> initializing) {
    // 1 如果 initializing 中存在当前组件,说明存在循环依赖
    if (initializing.contains(component)) {
        String message = String.format(
                "Cannot initialize %s. Cycle detected.", component.getName()
        );
        throw new IllegalStateException(message);
    }
    try {
        if (!mInitialized.contains(component)) {
            // 2 记录正在初始化
            initializing.add(component);

            Object instance = component.getDeclaredConstructor().newInstance();
            Initializer initializer = (Initializer) instance;
            List<Class<? extends Initializer>> list = initializer.dependencies();

            if (list != null && !list.isEmpty()) {
                for (int i = 0; i < list.size(); i++) {
                    if (!mInitialized.contains(list.get(i))) {
                        init(list.get(i));
                    }
                }
            }

            initializer.run();
            // 3 移除正在初始化记录
            initializing.remove(component);
            mInitialized.add(component);
        }
    } catch (Throwable t) {
        throw new StartupException(t);
    }
}

1)如果 initializing 中存在当前组件,说明存在循环依赖

2)记录正在初始化

3)移除正在初始化记录

强化一:异步任务

public interface Initializer extends Runnable {
    List<Class<? extends Initializer>> dependencies();

    // 是否是异步任务
    boolean isAsync();
}
void doInitialize(Class<? extends Initializer> component, Set<Class<?>> initializing) {
    ...
    
    if (initializer.isAsync()) {
        runOnIoThread(initializer);
    } else {
        initializer.run();
    }
    
    ...
}

强化二:等待异步任务

public interface Initializer extends Runnable {
    List<Class<? extends Initializer>> dependencies();

    boolean isAsync();
    
    // 异步的时候,是否等待异步任务
    boolean isAwait();
}
void doInitialize(Class<? extends Initializer> component, Set<Class<?>> initializing) {
    ...
    
    if (initializer.isAsync()) {
        if (initializer.isAwait()) {
            awaitOnIoThread(initializer);
        } else {
            runOnIoThread(initializer);
        }
    } else {
        initializer.run();
    }
    
    ...
}

辅助方法

public static void runOnIoThread(final Initializer action) {
    Observable.just(0)
            .observeOn(Schedulers.io())
            .doOnNext(integer -> action.run())
            .subscribe(new EmptyObserver<>());
}

public static void awaitOnIoThread(final Initializer action) {
    Observable.just(0)
            .observeOn(Schedulers.io())
            .doOnNext(integer -> action.run())
            .blockingSubscribe();
}

demo

InitA 同步任务,依赖BC

public class InitA implements Initializer {
    @Override
    public boolean isAsync() {
        return false;
    }

    @Override
    public boolean isAwait() {
        return false;
    }

    @Override
    public List<Class<? extends Initializer>> dependencies() {
        List<Class<? extends Initializer>> list = new ArrayList<>();
        list.add(InitB.class);
        list.add(InitC.class);
        return list;
    }

    @Override
    public void run() {
        System.out.println("A: +" + Thread.currentThread().getName());
    }
}

InitB 异步且等待任务,依赖C

public class InitB implements Initializer {
    @Override
    public boolean isAsync() {
        return true;
    }

    @Override
    public boolean isAwait() {
        return true;
    }

    @Override
    public List<Class<? extends Initializer>> dependencies() {
        List<Class<? extends Initializer>> list = new ArrayList<>();
        list.add(InitC.class);
        return list;
    }

    @Override
    public void run() {
        System.out.println("B: start");
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("B: +" + Thread.currentThread().getName());
        System.out.println("B end");
    }
}

InitC 异步任务

public class InitC implements Initializer {
    @Override
    public boolean isAsync() {
        return true;
    }

    @Override
    public boolean isAwait() {
        return false;
    }

    @Override
    public List<Class<? extends Initializer>> dependencies() {
        return null;
    }

    @Override
    public void run() {
        System.out.println("C: start");
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("C: +" + Thread.currentThread().getName());
        System.out.println("C end");
    }
}

App

public class MainApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        System.out.println("startup: start");
        Startup.getInstance(this).init(InitA.class);
        System.out.println("startup: end");
    }
}