Android 多线程之 IntentService 源码分析

Python OpenCV基于颜色通道分离法去除图片中的红色印章 最近一段时间的工作都是研究如何去除图片中的红色印章,在网上查找了大量的大佬写过的方法,发现大多数是采取颜色通道分离法来做,并且效果还不错。站在前人的肩膀上,我又做了些许调整,谈不上是改进,但是能应对更对的情况总还是好的,特此记录。 拿发票做例子,印章相较于其它部分最大的不同就是印章是红色的,而其它部分不是(这是一句废话)。 那么第一步当然就是将红色分离出来,这一步可以采用Python第三方库OpenCV里的 cv2.split()方法,该方法是把RGB图像的三个通道拆分开来,得... 阅读详情

Android 多线程之 IntentService 源码分析

一、前言

这主要是一个讲解 Android 中多线程的系列,全部文章如下:

IntentService 从名字可以看出是一个 Service,我们知道 Service 是没有前台页面的,主要用于长时间的后台任务,比如播放音乐等场景。

正常情况下,我们使用 Service 已经足够了,为什么官方又提供了一个 IntentService呢?

这是因为如果我们只使用 Service 的话,Service 默认是运行在主线程的,如果我们需要在 Service 中处理一些耗时任务,那么我们还需要去手动的创建线程或者使用线程池去处理耗时任务,然后在处理完以后手动关闭Service,而 IntentService 已经帮我们做好了这些工作,我们只需要在 onHandleIntent 中写上耗时任务的代码,就可以在子线程中去执行,因为 onHandleIntent 是运行在子线程中的,并且在任务执行完以后,IntentService 会自己执行stopSelf(startId)方法,自行关闭。

二、初识IntentService

2.1 API 文档定义

老规矩,先看下官方文档关于IntentService的介绍

意思是说:

IntentService 继承于 Service,并且在需要的时候处理一些异步请求。客户端根据需要通过调用Context.startService(Intent)发送请求来启动,使用工作线程(一般指的是子线程)来依次处理任务,并且在出错的时候自行关闭
这种“工作队列处理器”模式一般用于从主线程拆解任务,IntentService的存在简化了这种模式和处理机制,如果要使用它,只需要继承与 IntentService 并且实现onHandleIntent(Intent)方法,就可以接收到 Intent 、开启一个工作线程并且在合适的时机关闭。
所有的请求都运行在同一个工作线程,可能需要更多的时间,但是不会阻塞组线程,一次只处理一个线程

上面是官方 API 对IntentService 的描述,我的理解:

IntentService 本质上是一个 Service,自身封装了异步任务的方法,不需要手动开启子线程去处理异步任务,所有异步任务运行在一个线程中,按照启动顺序串行有序处理,处理完所有任务或者出错后会自动关闭。

2.1 使用时需要关注的方法 onHandleIntent(Intent intent)

onHandleIntent 是运行在子线程的,IntentService自身已经帮助我们封装好了,所以我们使用的时候只需要新建类继承于 IntentService ,并且在onHandleIntent方法里面写上异步任务代码以及处理完任务的操作就可以了。

三、基本使用

下面通过模拟加载本地图片的方式来进行演示

首先新建 UploadImageService:

public class UploadImageService extends IntentService {

    public static String IMG_PATH_KEY = "imgPath";

    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     */
    public UploadImageService() {
        super("UploadImageService");
    }

    public static void startUpload(Context context, String imgPath) {
        Intent intent = new Intent(context, UploadImageService.class);
        intent.putExtra(IMG_PATH_KEY, imgPath);
        context.startService(intent);
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        if (intent != null && intent.hasExtra(IMG_PATH_KEY)) {
            String path = intent.getStringExtra(IMG_PATH_KEY);
            upload(path);
        }
    }

    private void upload(String path) {
        try {
            // 模拟上传 3 秒结束
            Thread.sleep(3000);
            sendBroadcastToCaller(path);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void sendBroadcastToCaller(String path) {
        Intent intent = new Intent(UPLOAD_RESULT);
        intent.putExtra(IMG_PATH_KEY, path);
        sendBroadcast(intent);
    }
}

在 manifests.xml 中注册

<service android:name=".ui.a.activity.intentservice.UploadImageService" />

Activity代码

public class IntentServiceActivity extends BaseActivity {

    public static final String UPLOAD_RESULT = "com.sean.demo.ui.a.activity.UPLOAD_RESULT";
    private int i = 0;
    private LinearLayout mLyTaskContainer;
    private BroadcastReceiver uploadImgReceiver;
    private List<String> mUploadPaths;
    private AlertDialog mDialog;

    private void handleResult(String path) {
        TextView tv = mLyTaskContainer.findViewWithTag(path);
        mUploadPaths.remove(path);
        if (mUploadPaths.size() < 1) {
            mDialog.dismiss();
        }
        tv.setText(path + " upload success ~~~ ");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentLayout(R.layout.activity_intent_service);
        setBackArrow();
        uploadImgReceiver = new UploadBroadcastReceiver();
        mDialog = new AlertDialog.Builder(this).setView(new ProgressBar(this)).create();
        mLyTaskContainer = findViewById(R.id.id_ll_taskcontainer);
        registerReceiver();
        findViewById(R.id.add_task).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                addTask();
            }
        });
    }

    private void registerReceiver() {
        IntentFilter filter = new IntentFilter();
        filter.addAction(UPLOAD_RESULT);
        registerReceiver(uploadImgReceiver, filter);
    }

    public void addTask() {
        //模拟路径
        String path = "/sdcard/imgs/" + (++i) + ".png";
        if (null == mUploadPaths) {
            mUploadPaths = new ArrayList<>();
        }
        mUploadPaths.add(path);
        UploadImageService.startUpload(this, path);
        mDialog.show();
        TextView tv = new TextView(this);
        mLyTaskContainer.addView(tv);
        tv.setText(path + " is uploading ...");
        tv.setTag(path);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(uploadImgReceiver);
    }

    class UploadBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent != null && intent.getAction() != null && intent.getAction().equals(UPLOAD_RESULT)) {
                String successPath = intent.getStringExtra(IMG_PATH_KEY);
                handleResult(successPath);
            }
        }
    }

}

xml代码

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_intent_service"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context="com.sean.demo.ui.a.activity.intentservice.IntentServiceActivity">


    <Button
        android:id="@+id/add_task"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="addTask" />

    <LinearLayout
        android:id="@+id/id_ll_taskcontainer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/add_task"
        android:orientation="vertical" />
</RelativeLayout>

效果图:

下面来看下 IntentService的源码:

三、源码分析

其实IntentService源码不是很长,先大体上看下(删除了方法的注释):

public abstract class IntentService extends Service {
    private volatile Looper mServiceLooper;
    private volatile ServiceHandler mServiceHandler;
    private String mName;
    private boolean mRedelivery;

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }

    public IntentService(String name) {
        super();
        mName = name;
    }

       public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }

    @Override
    public void onCreate() {
        // TODO: It would be nice to have an option to hold a partial wakelock
        // during processing, and to have a static startService(Context, Intent)
        // method that would launch the service & hand off a wakelock.

        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }

    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }

    @Override
    @Nullable
    public IBinder onBind(Intent intent) {
        return null;
    }

    @WorkerThread
    protected abstract void onHandleIntent(@Nullable Intent intent);
}

3.1 成员变量

先看下成员变量,主要有:

  • Looper 当前IntentService 工作线程的 Looper
  • ServiceHandler 封装的一个继承于 Handler的子类
  • mName 名称(不重要)
  • mRedelivery 用来设置进程被杀掉以后会执行什么样的操作(控制异常关闭后是否重新启动服务的方式)

3.2流程解析

先看onCreate()(只有在第一次创建服务的时候调用)方法看起:

HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);

首先,会先创建一个HandlerThread对象,前面的文章已经介绍过了,HandlerThread 主要是为我们提供一个带有Looper的子线程,更加方便的让我们使用。

创建好以后执行 thread.start();去开启线程。
结合 HandlerThread的 run 方法:

@Override
public void run() {
    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
}

我们可以知道,这个时候,已经创建好了Looper,并且开启了循环。

然后通过 HandlerThread 的 getLooper() 拿到创建好的 Looper对象,用这个Looper来创建ServiceHandler对象。

总的来说:onCreate里面开启了一个带有Looper对象的子线程,并且通过这个Looper对象创建一个 ServiceHandler对象与之绑定。

接着看onStartCommand(在每次启动服务的时候调用)方法:

 @Override
 public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
     onStart(intent, startId);
     return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
 }

onStartCommand接收了三个参数:

  1. intent:

启动 Service 时传递进来的 Intent对象

  1. flags

flags有三个值,分别是0,START_FLAG_REDELIVERY,START_FLAG_RETRY。 分别标志Service在什么时候被启动。
当调用startService来启动服务的时候,这里的值是 0,如果Service发生重启行为,flags 就不会是 0 了。(比如你的onStartCommand返回值是START_STICKY 或 START_REDELIVER_INTENT,则Service终止后会重新启动)。他们的区别在于,如果Service重新启动了,当Service在onStartCommand返回之前就被终止了,那么下次重启时flags的值为START_FLAG_RETRY,当Service在onStartCommand返回后并且在stopSelf(int)还没执行前被终止,那么下次启动时flags的值为START_FLAG_REDELIVERY。

  1. startId:

每次调用startService向Service传递任务请求时都会生成一个startId,用来代表这一次请求,这个值是唯一的,不管startService调用多少次,每一次的startId的值都是不一样的,这个值和stopSelfResult(int)或者stopSelf(int)一起使用,主要是为了确保Service中的所有任务都已经完成。

方法里面首先调用 onStart方法,

@Override
public void onStart(@Nullable Intent intent, int startId) {
    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;
    msg.obj = intent;
    mServiceHandler.sendMessage(msg);
}

在 onStart 方法中,会创建一个 Message对象,然后通过mServiceHandler发送出去,然后在 mServiceHandler 的 handleMessage中接收:

private final class ServiceHandler extends Handler {
    public ServiceHandler(Looper looper) {
        super(looper);
    }
    @Override
    public void handleMessage(Message msg) {
        onHandleIntent((Intent)msg.obj);
        stopSelf(msg.arg1);
    }
}
protected abstract void onHandleIntent(@Nullable Intent intent);

在这里就看到我们要实现的抽象方法:onHandleIntent,由于创建 ServiceHandler 时候使用的 Looper是在 HandlerThread中创建的,HandlerThread是一个子线程,所以HandlerThread的Looper也是子线程的。

那么与之绑定的ServiceHandler也是子线程绑定的Handler对象,它的 handleMessage 也是运行在子线程的,所以这就解释了为什么onHandleIntent是运行在子线程中了。

再来看下如何自动关闭的。

代码中可以看到,当我们执行完onHandleIntent((Intent)msg.obj);以后,会立即调用 stopSelf(msg.arg1);这里的 msg.arg1 就是在 onStart方法里面组装的startId。

msg.arg1 = startId;

这个 startId 前面在讲onStartCommand参数的时候讲了:

我们都知道,当我们多次调用startService来启动同一个service时,只有第一次创建服务会执行onCreate,然后会多次调用onStartCommand,从而生成不同的startId,一般是从 1 开始,依次递增,这个值是唯一的,不管startService调用多少次,每一次的startId的值都是不一样的,这个值和stopSelfResult(int)或者stopSelf(int)一起使用,当我们调用stopSelf(int startId)时,系统会检测当前服务是否还有其它的startId存在,有的话就不销毁当前service,没有的话则销毁当前服务,这个机制主要是为了确保Service中的所有任务都已经完成才去销毁服务。

而stopSelf()则是立即销毁该 Service。

这里为什么不去掉用 stopSelf(),而要调用 stopSelf(int startId)呢?

因为 stopSelf(msg.arg1); 这行代码是在 onHandleIntent 后面的,那如果我们开启了两个服务来执行上传文件的操作,第一个服务运行结束,如果是使用 stopSelf()那么就直接结束掉Service了,第二个服务就得不到运行,那么如果使用stopSelf(startId)就可以保证在第所有服务运行结束后再关闭Service,能够保证我们的代码能够正确的运行。

最后在 onDestroy()方法里面mServiceLooper.quit();对Looper进行了释放。

3.3 为什么多次启动IntentService 会在一个线程串行执行,执行完才会关闭

3.3.1运行在一个线程
@Override
public void onCreate() {
    super.onCreate();
    HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
    thread.start();
    mServiceLooper = thread.getLooper();
    mServiceHandler = new ServiceHandler(mServiceLooper);
}

其实这个前面已经讲了,IntentService 在 onCreate() 的时候创建了 一个HandlerThread,并且使用HandlerThread对象的 Looper创建了一个 ServiceHandler对象,所以所有的Service实例都是在HandlerThread这个子线程中执行任务的。

3.3.2 按照顺序有序执行

所以当多次启动服务的时候,所有的启动服务传递进来的Intent和启动时生成startId会被封装成 Message对象,由IntentService的成员变量 mServiceHandler发送到mServiceLooper的 MessageQueue中,然后由mServiceLooper的 loop()方法中不断取出 Message交给 mServiceHandler 去处理,这样就保证了任务能够按照启动Service的顺序去执行。

3.3.3 所有任务执行完毕以后再关闭服务

再结合前面分析的 stopSelf(startId),系统会在等待所有Service执行完毕以后才会最终结束服务,在 onDestory()方法中执行mServiceLooper.quit();去释放掉Looper对象。

四、最后

到这里IntentService就算是分析完了,虽然代码不是很多,但是牵扯的内容还是不少的。

在日常开发中,还是要不断的发散思维,在合适的地方用不同的解决方案去解决问题,寻求解决问的最优解。

同花顺Supermind量化交易 风险控制建模--海龟交易法则 A.市场与标的海龟交易法则应用于流动性高的市场中,选择交易量较大的标的进行交易。本文以沪深300指数ETF为标的,构建海龟交易法则。B、仓位:仓位是海龟交易系统最核心的部分,通过ATR真实波幅指标来管理仓位。第一步:计算True Range,简称TR。TR = Max ( H−L , H−P , P−L ) ,其中H为当日日内最高价,L为当日日内最低价,P为前一日收盘价。第二步:计算ATRATR = mean ( TR , 20 ) , 即计算过去20天的TR的平均值,ATR是TR的移动平均值。 阅读详情

相关推荐

Flink CDC 1.18.1 Oracle 数据同步到postgresql

8、修改Flink的配置文件,主要是各种服务的绑定地址,默认为localhost,统统改为0.0.0.0,如:rest.address: 0.0.0.0 #localhost。将flink-sql-connector-oracle-cdc-3.0.1.jar复制到flink-1.18.1/lib目录中。6、下载 flink-connector-jdbc-3.1.1-1.17.jar,postgresql-42.7.3.jar。7、安装postgresql就不说了,相信你已经有了数据库了。

ynzhangyao的专栏 1799

android四大组件之Service

Service 主要用于在后台处理一些耗时的逻辑,或者去执行某些需要在后台长期运行的任务。必要的时候我们甚至可以在程序退出的情况下,让Service在后台继续保持运行状态 常用系统服务 后台service由系统启动时被SystemService服务启动 通过当前活动.getSystemService(name)并存于相应类的变量中 这些变量再调用一些方法 比如 WIFI连接查看 系统...

5ingwings(SiHao)的博客 4510

OpenClaw Docker 安装问题解决全记录

控制面板无法加载(WebSocket 错误) | 确认 Nginx 配置中的 `Upgrade` 和 `Connection` 头正确 || 网关容器无法启动 | `docker compose logs openclaw-gateway`,检查权限、镜像名 |如需消除,使用 Let's Encrypt |- `<your-token>`:你的 OpenClaw 网关令牌(如 `b0e5ab...`)将 `<nas-ip>` 替换为你的群晖内网 IP(例如 `192.168.1.100`)。

u014490376的博客 2308

Android中Service的两种启动方式区别与适用场景

Service 作为Android中四大组件之一,日常开发中经常会使用到,本文主要讲解Service的两种启动方式,以及两种启动方式的区别,生命周期,以及适用的场景。 Service是运行在主线程上的,是要依托android程序运行的,所以不能做耗时操作。 分别有两种启动方式: 一种startService() ,一种是bindService()。 两种启动方式的生命周期不同: 1、startService() 的生命周期 :onCreate() -> onStartCommand() (.

Anne_Wei的专栏 4600

Matlab实战:用DQN算法让机器人学会自主避障(附完整代码)

本文详细介绍了如何使用Matlab实现DQN(深度Q网络)算法,使机器人在复杂环境中学会自主避障。通过环境建模、网络架构设计、奖励函数优化及实战调试,提供了完整的代码实现和训练策略,帮助开发者快速应用于机器人路径规划项目。

t8u9v0w1x的博客 232

Dobot Magician机械臂二次开发指南:如何利用Python脚本和I/O接口实现自动化任务

本文详细介绍了Dobot Magician机械臂的二次开发方法,重点讲解如何通过Python脚本和I/O接口实现高级自动化任务。内容包括开发环境搭建、运动控制API解析、I/O接口应用以及典型场景实现,帮助开发者充分发挥Dobot Magician的潜力,适用于工业自动化、教育科研等领域。

weixin_26968079的博客 267

Android四大组件之Service使用详解

Service作为安卓的四大组件之一,适合长期在后台运行而不需要用户界面的操作,Service默认运行在UI线程中,因此Service中同样不适合做耗时操作,如果需要做耗时操作需要开启子线程。 常用Service的开启包括start和bind两种启动方式。 创建自定义Service public class ServiceTest extends Service { /** ...

xk7298的博客 537

SAP-QM-质检操作

SAP-QM-质检操作

yanzibing99的博客 8176

Android Service

Service简单概述 Service在清单文件中的声明 Service启动服务实现方式及其详解 Service绑定服务的三种实现方式 关于启动服务与绑定服务间的转换问题 前台服务以及通知发送 服务Service与线程Thread的区别 管理服务生命周期的要点 Android 5.0以上的隐式启动问题及其解决方案 保证服务不被杀死的实现思路 1.Service简单概述 服务时可以长时间在后台运行并且没有界面的应用组件。服务一旦被启动将一只会在后台运行,即使启动它的组件被销毁也不会受.

开发小白的博客 588

IDM更改下载路径的详细指南

Internet Download Manager(IDM)是一款功能全面的下载加速工具,它支持多种浏览器和协议,能够显著提升下载速度,同时提供断点续传、多线程下载等实用功能。IDM的用户界面简洁明了,操作便捷,使得用户能够轻松管理下载任务。此外,IDM还支持自动分类下载文件、定时下载等高级功能,进一步提升了用户的下载体验。通过本文的介绍,相信用户已经掌握了如何在IDM中更改下载路径的方法。这一功能不仅提升了下载效率和文件管理便捷性,还满足了用户的个性化需求。

nntxthml的博客 1761

搜索神器Perplexity的详细使用方法(持续更新)

本文主要介绍了ChatGPT的互补工具Perplexity的详细使用方法,希望对新手有所帮助。需要说明的是,Perplexity不需要上网工具,很方便新手和小白上手使用。Perplexity的官网链接为:https://www.perplexity.ai/ 。 文章目录 1. 为什么要讲Perplexity? 2. 详细使用方法 2.1 使用要点一 2.2 使用要点二 2.3 使用要点三

herosunly的博客 8万+

Android四大组件之——Service学习总结

什么是Service Service提供了两个主要的功能: 可以让程序在后台一直做它想要做的事情,即使当前没有与用户进行交互。(对应context.startService()的启动方式)。 实现了某些功能已供其他程序调用的工具,并可保持长期连接进行交互。(对应context.bindService()的启动方式)。 Service的生命周期(对应两种启动方式) onCreate () 首次创建服务时,系统将调用此方法来执行一次性设置程序(在调用 onStartCommand()..

qq_41390028的博客 380

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

【Android+多线程】IntentService 知识总结:应用场景 / 使用步骤 / 源码分析

IntentService的定义、功能、应用场景、使用步骤、与Service和Thread的对比

qq_30885821的博客 719

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Android多线程:IntentService用法&源码分析

版权声明:本文为博主原创文章,未经博主允许不得转载,更多请继续关注Carson_Ho https://blog.youkuaiyun.com/carson_ho/article/details/53407806 前言 多线程的应用在Android开发中是非常常见的,常用方法主要有: 继承Thread类 实现...

贵公子丶笔记 455

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

IntentService详解

一、定义 IntentService是Android里面的一个封装类,继承自四大组件之一的Service。 二、作用 处理异步请求,实现多线程 三、工作流程 注意:若启动IntentService多次,那么每个耗时操作则是以队列的方式在IntentService的onHandleIntent回调方法中依次执行,执行完自动结束。 四、实现步骤 1. 定义IntentService...

xiaoxu9522的博客 358

Android 多线程编程:IntentService & HandlerThread

因为 Android 是使用 Java 开发的,所以当我们谈及 Android 中的多线程,必然绕不过 Java 中的多线程编程。但在这篇文章中,我们不会过多地分析 Java 中的多线程编程的知识。我们会在以后分析 Java 并发编程的时候分析 Java 中的多线程、线程池和并发 API 的用法。 我们先来总结一下 Android 多线程编程的演变过程:首先是 Java 的 Thread。因为本身...

你好,开发者 925

IntentService 面试详解

前两篇文章介绍了AsyncTask与HandleThread,主要是针对Android的多线程编程。在这里补充下线程的知识。 线程是操作系统调度的最小单元,同时也是一种受限的资源(即不能无限制的创建和销毁,创建和销毁都会占用系统资源)。操作系统是通过时间片轮转的方式调度每个线程,因此不可能做到绝对的并行。 进程一般指一个执行单元,在PC或移动设备上指一个程序或者应用。一个进程可以包含一个或多个...

CoderZJ的博客 473

Android基础-IntentService详解

一、定义 IntentService是Android里面的一个封装类,继承自四大组件之一的Service 二、作用 处理异步请求,实现多线程 三、工作流程 注意:若启动IntentService多次,那么每个耗时操作则以队列的方式在IntentService的onHandleIntent回调方法中依次执行,执行完自动结束。 四、实现步骤 步骤...

weixin_30800807的博客 185

Android多线程全面解析:IntentService用法&源码

前言 多线程的应用在Android开发中是非常常见的,常用方法主要有: 继承Thread类实现Runnable接口AsyncTaskHandlerHandlerThreadIntentService 今天,我将全面解析多线程其中一种常见用法:IntentService 目录 目录 1. 定义 IntentService是Android里面的一个封装

自由人生 314

多线程(四)、Android多线程使用及AsyncTask源码分析

本篇是多线程系列的第四篇,如果对前三篇感兴趣的也可以去看看。 多线程(一)、基础概念及notify()和wait()的使用 多线程(二)、内置锁 synchronized 多线程(三)、线程池 ThreadPoolExecutor 知识点总结 除了前面的线程池的使用外,在Android中,我们除了通过Thread创建线程外,还可以通过 AsyncTask、IntentServi...

Evan的博客 307

Android组件内核之Service内核原理(三)

阿里P7Android高级架构进阶视频免费学习请点击:https://space.bilibili.com/474380680 本篇文章将先从以下三个内容来介绍Service内核原理: [startService与bindService的区别] [多线程IntentService的工作原理 & 源码分析] [前台服务以及通知] 一 startService与bindSe...

AndroidAlvin的博客 733

android intentservice可以绑定吗,Android IntentService使用介绍以及原理分析

简介在Android应用的程序中,普通的Service中的代码是运行在主线程中的,如果想要在Service中做些耗时的操作,就很容易出现ANR的现象(大概是20秒),那么我们经常的做法就是,在onStartCommon方法中开启一个子线程然后内部执行耗时的操作,在执行完毕后如果需要自动停止服务需要在子线程的run方法中调用stopSelf()来停止服务。虽说在Service中执行耗时的代码可以很容...

weixin_36337389的博客 367

Android多线程:深入剖析IntentService源码

前言 多线程的应用在Android开发中是非常常见的,常用方法主要有:继承Thread类 实现Runnable接口 AsyncTask Handler HandlerThread IntentService 今天,我将全面解析多线程其中一种常见用法:IntentService 目录1. 定义IntentService是Android里面的一个封装类,继承自四大组件之一的Service。2. 作用处理

Carson带你学Android 5180

Android 多线程

多线程笔记 线程基础 线程基本使用api 线程池基础 ReentrantLock使用 阻塞分类 死锁定义实现以及解决方式 生产者消费者问题 AsyncTask源码分析

crazyZhangxl的博客 678

内部泄露版!2024 美团 Android 面试真题解析

当我们出去找工作,或者准备找工作的时候,我们一定要想,我面试的目标是什么,我自己的技术栈有哪些,近期能掌握的有哪些,我的哪些短板 ,列出来,有计划的去完成,别看前两天掘金一些大佬在驳来驳去 ,他们的观点是他们的,不要因为他们的观点,膨胀了自己,影响自己的学习节奏。基础很大程度决定你自己技术层次的厚度,你再熟练框架也好,也会比你便宜的,性价比高的替代,很现实的问题但也要有危机意识,当我们年级大了,有哪些亮点,与比我们经历更旺盛的年轻小工程师,竞争。无论你现在水平怎么样一定要。

2301_79098686的博客 1077

IntentService源码分析

目录介绍 1.IntentService的作用 2.IntentService使用场景 3.IntentService使用步骤 4.IntentService源码分析 4.1 整体源码展示及归纳 4.2 如何单独开启1个新的工作线程 4.3 IntentService如何将Intent传递给服务并且依次插入到工作队列中 5.In...

weixin_34167043的博客 172
上一篇: Android 多线程之 AsyncTask使用源码分析
下一篇: Android 事件分发机制
Sean_css
博客等级 码龄11年 32粉丝 84原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值