• TaskDispatcher源码解析


    资料

    github地址
    git@github.com:AdrianAndroid/TaskDispatcher.git
    图论:有向无环图的排序——拓扑排序

    用法

    TaskDispatcher.init

        public static void init(Application context) {
            if (context != null) {
                sContext = context; // 保存上下文
                mApp = context; // 保存Application
                sHasInit = true; // 已经初始化
                sIsMainProcess = Utils.isMainProcess(sContext); // 是不是主进程
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    createInstance

        /**
         * 注意:每次获取的都是新对象
         *
         * @return
         */
        public static TaskDispatcher createInstance() {
            if (!sHasInit) {
                throw new RuntimeException("must call TaskDispatcher.init first");
            }
            return new TaskDispatcher();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    addTask & start & await

        void runTask() {
            Log.i("MyApp", "step 1");
            Debug.startMethodTracing("runTask" + System.currentTimeMillis());
    
            TaskDispatcher dispatcher = TaskDispatcher.createInstance();
    
            dispatcher
                .addTask(new InitStethoTask())
                .addTask(new InitUmengTask())
                .addTask(new GetDeviceIdTask())
                .start();
    
            Log.i("MyApp", "step 2");
            dispatcher.await();
    
            Log.i("MyApp", "step 3");
    
            DelayInitDispatcher delayInitDispatcher = new DelayInitDispatcher();
            delayInitDispatcher.addTask(new DelayInitTaskA())
                .addTask(new DelayInitTaskB())
                .start();
    
    
            Log.i("MyApp", "step 4");
            LaunchTimer.endRecord();
    
            Debug.stopMethodTracing();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    addTask(new InitStethoTask())

    /**
     * 异步的Task
     */
    public class InitStethoTask extends Task {
    
        @Override
        public boolean needWait() {
            return true;
        }
    
        @Override
        public void run() {
    
            Handler handler = new Handler(Looper.getMainLooper());
            Stetho.initializeWithDefaults(mContext);
            try {
                Thread.sleep(1300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Log.i("MyApp", "InitStethoTask");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    addTask(new InitUmengTask())

    /**
     * 需要在getDeviceId之后执行
     */
    public class InitUmengTask extends Task {
    
        @Override
        public boolean needWait() {
            return super.needWait();
        }
    
        @Override
        public List<Class<? extends Task>> dependsOn() {
            List<Class<? extends Task>> task = new ArrayList<>();
            task.add(GetDeviceIdTask.class);
            return task;
        }
    
        @Override
        public void run() {
            UMConfigure.init(mContext, "58edcfeb310c93091c000be2", "umeng",
                    UMConfigure.DEVICE_TYPE_PHONE, "1fe6a20054bcef865eeb0991ee84525b");
            Log.i("MyApp", "InitUmengTask");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    addTask(new GetDeviceIdTask())

    public class GetDeviceIdTask extends Task {
        private String mDeviceId;
    
        @Override
        public boolean needWait() {
            return true;
        }
    
        @SuppressLint("MissingPermission")
        @Override
        public void run() {
            // 真正自己的代码
            TelephonyManager tManager = (TelephonyManager) mContext.getSystemService(
                    Context.TELEPHONY_SERVICE);
    
    //        MyApp app = (MyApp) mContext;
    //        app.setDeviceId(mDeviceId);
            Log.i("MyApp", "GetDeviceIdTask");
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    DelayInitDispatcher

    
            DelayInitDispatcher delayInitDispatcher = new DelayInitDispatcher();
            delayInitDispatcher.addTask(new DelayInitTaskA())
                .addTask(new DelayInitTaskB())
                .start();
    
    
    /**
     * 延迟初始化分发器
     */
    public class DelayInitDispatcher {
        private Queue<Task> mDelayTasks = new LinkedList<>();
    
        private MessageQueue.IdleHandler mIdleHandler = new MessageQueue.IdleHandler() {
            @Override
            public boolean queueIdle() {
                if(mDelayTasks.size()>0){
                    Task task = mDelayTasks.poll();
                    new DispatchRunnable(task).run();
                }
                return !mDelayTasks.isEmpty();
            }
        };
    
        public DelayInitDispatcher addTask(Task task){
            mDelayTasks.add(task);
            return this;
        }
    
        public void start(){
            Looper.myQueue().addIdleHandler(mIdleHandler);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    DelayInitTaskA

    public class DelayInitTaskA extends MainTask {
    
        @Override
        public void run() {
            Log.i("MyApp", "DelayInitTaskA");
            // 模拟一些操作
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Log.i("DelayInitTaskA finished", "");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    MainTask

    public abstract class MainTask extends Task {
    
        @Override
        public boolean runOnMainThread() {
            return true;
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    源码解析

    addTask

    addTask

        public TaskDispatcher addTask(Task task) {
            if (task != null) {
                collectDepends(task);
                mAllTasks.add(task);
                mClsAllTasks.add(task.getClass());
                // 非主线程且需要wait的,主线程不需要CountDownLatch也是同步的
                if (ifNeedWait(task)) {
                    mNeedWaitTasks.add(task);
                    mNeedWaitCount.getAndIncrement();
                }
            }
            return this;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    collectDepends(task);

        private void collectDepends(Task task) {
            if (task.dependsOn() != null && task.dependsOn().size() > 0) {
                for (Class<? extends Task> cls : task.dependsOn()) {
                    if (mDependedHashMap.get(cls) == null) {
                        mDependedHashMap.put(cls, new ArrayList<Task>());
                    }
                    mDependedHashMap.get(cls).add(task);
                    if (mFinishedTasks.contains(cls)) {
                        task.satisfy();
                    }
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    start

        @UiThread
        public void start() {
            mStartTime = System.currentTimeMillis();
            if (Looper.getMainLooper() != Looper.myLooper()) {
                throw new RuntimeException("must be called from UiThread");
            }
            if (mAllTasks.size() > 0) {
                mAnalyseCount.getAndIncrement();
                printDependedMsg();
                mAllTasks = TaskSortUtil.getSortResult(mAllTasks, mClsAllTasks);
                mCountDownLatch = new CountDownLatch(mNeedWaitCount.get());
    
                sendAndExecuteAsyncTasks();
    
                DispatcherLog.i("task analyse cost " + (System.currentTimeMillis() - mStartTime) + "  begin main ");
                executeTaskMain();
            }
            DispatcherLog.i("task analyse cost startTime cost " + (System.currentTimeMillis() - mStartTime));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    getSortResult

        public static synchronized List<Task> getSortResult(List<Task> originTasks,
            List<Class<? extends Task>> clsLaunchTasks) {
            long makeTime = System.currentTimeMillis();
    
            Set<Integer> dependSet = new ArraySet<>();
            Graph graph = new Graph(originTasks.size());
            for (int i = 0; i < originTasks.size(); i++) {
                Task task = originTasks.get(i);
                if (task.isSend() || task.dependsOn() == null || task.dependsOn().size() == 0) {
                    continue;
                }
                for (Class cls : task.dependsOn()) {
                    int indexOfDepend = getIndexOfTask(originTasks, clsLaunchTasks, cls);
                    if (indexOfDepend < 0) {
                        throw new IllegalStateException(task.getClass().getSimpleName() +
                            " depends on " + cls.getSimpleName() + " can not be found in task list ");
                    }
                    dependSet.add(indexOfDepend);
                    graph.addEdge(indexOfDepend, i);
                }
            }
            List<Integer> indexList = graph.topologicalSort();
            List<Task> newTasksAll = getResultTasks(originTasks, dependSet, indexList);
    
            DispatcherLog.i("task analyse cost makeTime " + (System.currentTimeMillis() - makeTime));
            printAllTaskName(newTasksAll);
            return newTasksAll;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    拓扑排序

    在这里插入图片描述

    初始化线程堵塞

            mCountDownLatch = new CountDownLatch(mNeedWaitCount.get());
    
    • 1

    开始执行任务

        /**
         * 发送去并且执行异步任务
         */
        private void sendAndExecuteAsyncTasks() {
            for (Task task : mAllTasks) {
                if (task.onlyInMainProcess() && !sIsMainProcess) {
                    markTaskDone(task);
                } else {
                    sendTaskReal(task);
                }
                task.setSend(true);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    markTaskDone

        public void markTaskDone(Task task) {
            if (ifNeedWait(task)) {
                mFinishedTasks.add(task.getClass());
                mNeedWaitTasks.remove(task);
                mCountDownLatch.countDown();
                mNeedWaitCount.getAndDecrement();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    sendTaskReal

        /**
         * 发送任务
         */
        private void sendTaskReal(final Task task) {
            if (task.runOnMainThread()) {
                mMainThreadTasks.add(task);
                if (task.needCall()) {
                    task.setTaskCallBack(new TaskCallBack() {
                        @Override
                        public void call() {
                            TaskStat.markTaskDone();
                            task.setFinished(true);
                            satisfyChildren(task);
                            markTaskDone(task);
                            DispatcherLog.i(task.getClass().getSimpleName() + " finish");
                            Log.i("testLog", "call");
                        }
                    });
                }
            } else {
                // 直接发,是否执行取决于具体线程池
                Future future = task.runOn().submit(new DispatchRunnable(task, this));
                mFutures.add(future);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    executeTaskMain

        private void executeTaskMain() {
            mStartTime = System.currentTimeMillis();
            for (Task task : mMainThreadTasks) {
                long time = System.currentTimeMillis();
                new DispatchRunnable(task, this).run();
                DispatcherLog.i("real main " + task.getClass().getSimpleName() + " cost   " +
                        (System.currentTimeMillis() - time));
            }
            DispatcherLog.i("maintask cost " + (System.currentTimeMillis() - mStartTime));
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
        @Override
        public void run() {
            TraceCompat.beginSection(mTask.getClass().getSimpleName());
            DispatcherLog.i(mTask.getClass().getSimpleName()
                    + " begin run" + "  Situation  " + TaskStat.getCurrentSituation());
    
            Process.setThreadPriority(mTask.priority());
    
            long startTime = System.currentTimeMillis();
    
            mTask.setWaiting(true);
            mTask.waitToSatisfy();
    
            long waitTime = System.currentTimeMillis() - startTime;
            startTime = System.currentTimeMillis();
    
            // 执行Task
            mTask.setRunning(true);
            mTask.run();
    
            // 执行Task的尾部任务
            Runnable tailRunnable = mTask.getTailRunnable();
            if (tailRunnable != null) {
                tailRunnable.run();
            }
    
            if (!mTask.needCall() || !mTask.runOnMainThread()) {
                printTaskLog(startTime, waitTime);
    
                TaskStat.markTaskDone();
                mTask.setFinished(true);
                if (mTaskDispatcher != null) {
                    mTaskDispatcher.satisfyChildren(mTask);
                    mTaskDispatcher.markTaskDone(mTask);
                }
                DispatcherLog.i(mTask.getClass().getSimpleName() + " finish");
            }
            TraceCompat.endSection();
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
  • 相关阅读:
    稀碎从零算法笔记Day12-LeetCode:找出字符串中第一个匹配项的下标
    java毕业设计超市管理系统Mybatis+系统+数据库+调试部署
    C语言的冒泡排序
    7判断环的入口结点8输出倒数第k个
    五月刚入职字节跳动,测试开发面试题整理,还热乎的
    算法整理(五)
    移动WEB开发之rem布局--rem适配方案
    CMU - FarPlanning 代码速读
    OSCP系列靶场-Esay-Gaara保姆级
    Python基础学习笔记3
  • 原文地址:https://blog.csdn.net/AdrianAndroid/article/details/126036322