IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 根据JobIntentService的android8以下版本实现AutoStopService -> 正文阅读

[移动开发]根据JobIntentService的android8以下版本实现AutoStopService

承接JobIntentService深入研读1上一篇文章,那么,我们就有了一个新的需求了:
我有个Service,他需要根据startService进来的intent做如下几类活儿:

  1. Action1 拉起我的FragmentA界面;
  2. Action2 拉起我的FragmentB界面;
  3. Action3 执行一段网络请求拿到一份xx数据;

而上一篇文章,已经搞清楚JobIntentService的含义,他代表着顺序的,一个一个排队执行;而且是可以进行耗时操作的。
因此一个耗时操作会等待着上一个操作的完成。
因此JobIntentService系列的逻辑是onStartCommand中接收到了workIntent,
按照startId按顺序来,一个一个"慢慢"执行;
直到最后一个活儿干完了,stopSelf(startId)就是最后一个id。

但是现在我们的需求是,来一个onStartCommand,我们立刻就要去执行;并不能让他排队
(当然,如果有顺序的概念的话,也只是说约定某些状态逻辑切换顺序,而某些内部操作是不用排队的)。

显然,如果我们使用JobIntentService当有Action3来工作的时候,我们将无法及时响应Action1,2;
而Action1,2确是希望有排队的需求。

你或者会想,我直接JobIntentService里面不在他的onHandleWork卡住,开启子线程跑就好了呀? 这样就错误了。因为如果你提前onHandlerWork return掉,就会stopSelf掉就会导致代码游离在Service的生命周期之外。
极度容易被oom_obj memKiller杀掉进程。

因此,设计这个类来满足上述需求。
尤其适合应用就是给系统应用做(原厂、有system app、加入了修改framework白名单的)等应用:
github传送门

package com.allan.services;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;

import java.util.ArrayList;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 与JobIntentService的区别:
 * 搞清楚JobIntentService的含义,他代表着顺序的,一个一个排队执行;而且是可以进行耗时操作的。
 * 因此一个耗时操作会等待着另外一个操作的完成。
 * 因此JobIntentService系列的逻辑是onStartCommand中接收到了workIntent,
 * 按照startId按顺序来,一个一个"慢慢"执行;
 * 直到最后一个活儿干完了,stopSelf(startId)就是最后一个id。
 *
 * 但是现在我们的需求是,来一个onStartCommand,我们立刻就要去执行;并不能让他排队
 * (当然,如果有顺序的概念的话,也只是说约定某些状态逻辑切换顺序,而某些内部操作是不用排队的)。
 * 举例:
 * 我有个Service,他需要根据startService进来的intent做如下几类活儿:
 * 1. Action1 拉起我的FragmentA界面;
 * 2. Action2 拉起我的FragmentB界面;
 * 3. Action3 执行一段网络请求拿到一份xx数据;
 *
 * 显然,如果我们使用JobIntentService当有Action3来工作的时候,我们将无法及时响应Action1,2;
 * 而Action1,2确是希望有排队的需求。
 *
 * 你或者会想,我直接JobIntentService里面不在他的onHandleWork卡住,开启子线程跑就好了呀?
 * 这样就错误了。因为如果你提前onHandlerWork return掉,就会stopSelf掉就会导致代码游离在Service的生命周期之外。
 * 极度容易被oom_obj memKiller杀掉进程。
 *
 * 因此,设计这个类来满足上述需求。
 */
public abstract class AutoStopService extends Service {
    protected static final String TAG = "AutoStopService";

    static final boolean DEBUG = true;
    public static final String EXCUTE_TYPE_DIRECT = "type_direct";
    public static final String EXCUTE_TYPE_MAIN = "type_main";
    public static final String EXCUTE_TYPE_SUB = "type_thread";
    public static final String EXCUTE_TYPE_ASYNC = "type_async";

    /**
     * 直接在onStartCommand中执行onHandleWork。
     * 并帮你执行stopWrap
     */
    public static final int EXCUTE_TYPE_DIRECTLY_IN_OnStartCmd = 0;
    /**
     * 在本类中的mainHandler中执行onHandleWork。
     * 并帮你执行stopWrap
     */
    public static final int EXCUTE_TYPE_IN_MainHandler = 1;
    /**
     * 在本类中的ThreadPool或者你提供的executeInSubThread中执行onHandleWork。
     * 并帮你执行stopWrap
     */
    public static final int EXCUTE_TYPE_DIRECTLY_IN_SubThread = 2;
    /**
     * 交给了你外部去执行并且适用于比如一些外部框架network的异步请求不容易做到同步的那种
     * *注意*:自行在执行完成后调用stopWrap
     */
    public static final int EXCUTE_TYPE_DIRECTLY_IN_ExecuteAsync = 3;

    private final ArrayList<Integer> mStartIds = new ArrayList<>(2);

    private ThreadPoolExecutor executorService;
    private synchronized void init() {
        if (executorService == null) {
            executorService = new ThreadPoolExecutor(1, 8, 30L,
                    TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
        }
    }

    public void executeRunnable(Runnable r) {
        if (executorService == null) {
            init();
        }

        executorService.execute(r);
    }

    private Handler mMainHandler;
    private Handler getMainHandler() { //不需要做保护sync
        if (mMainHandler == null) {
            mMainHandler = new Handler(Looper.getMainLooper());
        }
        return mMainHandler;
    }

    /**
     * Default empty constructor.
     */
    public AutoStopService() {
    }

    protected final void stopWrap(int startId) {
        if(DEBUG) Log.d(TAG, "stop wrap #" + startId);
        synchronized (mStartIds) {
            if (mStartIds.size() > 1) {
                mStartIds.remove(Integer.valueOf(startId)); //注意一定要转为Integer是元素否则错误当成index
                return;
            }

            if (mStartIds.get(0) == startId) {
                mStartIds.clear();
                stopSelf();
                return;
            }

            //size == 0?
            throw new RuntimeException("impossible when stopWrap!");
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    
    @Override
    public void onDestroy() {
        super.onDestroy();
        if (executorService != null) {
            executorService.shutdown();
            executorService = null;
        }

        if (mMainHandler != null) {
            mMainHandler.removeCallbacksAndMessages(null);
            mMainHandler = null;
        }
        if(DEBUG) Log.d(TAG, "on Destroy!");
    }
    
    @Override
    public int onStartCommand(final Intent intent, int flags, final int startId) {
        if (DEBUG) Log.d(TAG, "onStart Command #" + startId + ": " + intent);

        synchronized (mStartIds) {
            mStartIds.add(startId);
        }

        final int workType = executeType(intent);
        if (workType == EXCUTE_TYPE_DIRECTLY_IN_OnStartCmd) {
            onHandleWork(intent, workType, startId);
            stopWrap(startId);
        } else if (workType == EXCUTE_TYPE_IN_MainHandler) {
            getMainHandler().post(new Runnable() {
                @Override
                public void run() {
                    onHandleWork(intent, workType, startId);
                    stopWrap(startId);
                }
            });
        } else if (workType == EXCUTE_TYPE_DIRECTLY_IN_SubThread) {
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    onHandleWork(intent, workType, startId);
                    stopWrap(startId);
                }
            };
            if (!executeInSubThread(runnable)) {
                executeRunnable(runnable);
            }
        } else if (workType == EXCUTE_TYPE_DIRECTLY_IN_ExecuteAsync) {
            onHandleWork(intent, workType, startId);
        }

        return START_REDELIVER_INTENT;
    }

    /**
     * 子类实现;判断onStartCommand传递的这个Intent需要按照哪种executeType去做。
     */
    protected abstract int executeType(Intent intent);

    /**
     * 不论是哪种ExecuteType执行逻辑;
     * 都将会跑到这里,因此不建议做异步动作。
     *
     * 如果你的executeType针对此Intent返回了EXCUTE_TYPE_DIRECTLY_IN_OtherSubThread,
     * 那么:在异步完成后一定要手动执行stopWrap(startId);
     */
    protected abstract void onHandleWork(Intent intent, int executeType, int startId);
    /**
     * 如果你希望子线程跑在你们自定义的线程池中,就调用并返回true即可。
     * 如果不处理不实现 默认为false,则使用内部的ExecutorService
     * executorService.execute(runnable);
     *
     * 真实的工作还是交给onHandleWork
     */
    protected boolean executeInSubThread(Runnable runnable) {
        return false;
    }
}
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-27 11:58:42  更:2021-08-27 12:01:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/31 6:21:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码