【Demo验证】Service的onStartCommand返回值

本文通过一个Demo详细展示了Service的onStartCommand方法不同返回值的影响,包括START_STICKY_COMPATIBILITY、START_STICKY、START_NOT_STICKY、START_REDELIVER_INTENT四种情况下的行为差异。

一、引言

上一篇文章 【源码解析】Service的onStartCommand返回值 从源码的角度分析了Service的onStartCommand的返回值的意义。

这篇文章承接上面的文章得出的结论,以一个Demo来验证onStartCommand方法不同的返回值会呈现什么效果。

二、Demo代码

1、MainActivity:
/**
 * Created by hwldzh on 2018/10/16
 */
public class MainActivity extends Activity {
    private Intent intent;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);setContentView(R.layout.main_activity);
        findViewById(R.id.startService).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                intent = new Intent(MainActivity.this, MyService.class);
                startService(intent);
            }
        });
    }
}
2、MyService:
/**
 * Created by hwldzh on 2019/1/2
 */
public class MyService extends Service {
    @Override
    public voidonCreate() {
        super.onCreate();
        Log.d("ABC", "MyService onCreate");
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                Integer.parseInt("haha"); //这里故意执行了一个异常
            }
        }, 5000);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("ABC", "MyService onStartCommand");
        Log.d("ABC", "startId=" + startId);
        Log.d("ABC", "intent=" + intent);
        //这里的返回值可以修改为START_STICKY、START_NOT_STICKY、START_REDELIVER_INTENT
        return Service.START_STICKY_COMPATIBILITY;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d("ABC", "MyService onUnbind");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("ABC", "MyService onDestroy");
    }
}

为了让Service进程能够被杀死,这里使用了一个延时执行的Runnable,在Runnable中故意执行了一个异常。

三、结论展示

在onStartCommand方法中分别返回START_STICKY_COMPATIBILITY、START_STICKY、START_NOT_STICKY、START_REDELIVER_INTENT这四个值,并打印出Log,得出下面的结论:

1、START_STICKY_COMPATIBILITY
D/ABC: MyService onCreate
D/ABC: MyService onStartCommand
D/ABC: startId=1
D/ABC: intent=Intent { cmp=com.mucfc.myapplication/.MyService }
D/ABC: MyService onCreate

当返回值为START_STICKY_COMPATIBILITY时,Service被杀死后会重启(执行了onCreate方法),但是onStartCommand方法没有被执行

2、START_STICKY
D/ABC: MyService onCreate
D/ABC: MyService onStartCommand
D/ABC: startId=1
D/ABC: intent=Intent { cmp=com.mucfc.myapplication/.MyService }
D/ABC: MyService onCreate
D/ABC: MyService onStartCommand
D/ABC: startId=2
D/ABC: intent=null

当返回值为START_STICKY时,Service被杀死后会重启(执行了onCreate方法),并且onStartCommand方法会执行。从startId可以看出是Service对象不是同一个,并且onStartCommand方法中的intent值为null

3、START_NOT_STICKY
D/ABC: MyService onCreate
D/ABC: MyService onStartCommand
D/ABC: startId=1
D/ABC: intent=Intent { cmp=com.mucfc.myapplication/.MyService }

当返回值为START_NOT_STICKY时,Service被杀死后并不会重启(Service的onCreate没有被第二次被执行)。

4、START_REDELIVER_INTENT
D/ABC: MyService onCreate
D/ABC: MyService onStartCommand
D/ABC: startId=1
D/ABC: intent=Intent { cmp=com.mucfc.myapplication/.MyService }
D/ABC: MyService onCreate
D/ABC: MyService onStartCommand
D/ABC: startId=1
D/ABC: intent=Intent { cmp=com.mucfc.myapplication/.MyService }

当返回值为START_REDELIVER_INTENT时,Service被杀死后会重启(执行了onCreate方法),并且onStartCommand方法会执行。从startId可以看出两个Service对象是同一个,并且onStartCommand方法中的intent和前一个intent值是一致的

从上述的Demo展示出来的Log,得出的结论和【源码解析】Service的onStartCommand返回值 这篇文章的结论的一致的,从而验证了onStartCommand返回值的结论的正确性。

<think> 我们正在讨论Android ServiceonStartCommand方法返回值。根据提供的引用,有几种不同的返回值: 1. START_STICKY:如果Service被系统杀死,系统会重新创建Service并调用onStartCommand,但此时如果没有任何挂起的Intent,则Intent参数为null。 2. START_REDELIVER_INTENT:与START_STICKY类似,系统也会重新创建Service,但会重新传递之前的Intent(即被杀死时正在处理的Intent)。 3. START_STICKY_COMPATIBILITY:这是START_STICKY的兼容版本,但不保证onStartCommand在被杀死后一定会被再次调用。 此外,还有一个常见的返回值: 4. START_NOT_STICKY:如果Service在执行过程中被系统杀死,系统不会自动重新创建Service,除非有新的Intent需要传递。 现在,我们根据这些信息来整理回答。 注意:在回答中,我们要使用中文,并且按照要求使用行内数学表达式(虽然这里可能用不到数学表达式,但如果有变量或简单表达式,我们会用$...$)。独立公式我们这里可能用不到,所以不需要单独成段的公式。同时,我们要生成相关问题,并在引用的地方添加引用标识。 由于我们引用了两段内容,我们会在相应的位置标注[^1]和[^2]。 </think>### Android Service 的 `onStartCommand()` 返回值详解 在 Android Service 的生命周期中,`onStartCommand()` 方法是关键回调之一。其返回值决定了 Service 被系统杀死后的重建行为,主要有以下几种类型: #### 1. **START_STICKY** - **行为**:系统会重建 Service 并重新调用 `onStartCommand()`。 - **Intent 处理**:若无挂起的 Intent,重建时传入 `onStartCommand()` 的 Intent 为 `null`[^2]。 - **适用场景**:适合不依赖具体 Intent 的后台服务(如音乐播放器),保证服务持续运行。 #### 2. **START_NOT_STICKY** - **行为**:系统**不会自动重建** Service。 - **触发条件**:仅当有新的启动命令(如新 Intent)时才会重建。 - **适用场景**:执行一次性任务(如下载文件),任务完成后无需保留。 #### 3. **START_REDELIVER_INTENT** - **行为**:系统重建 Service 并**重新传递之前的 Intent**。 - **与 START_STICKY 区别**:重建时保证传入原始 Intent,而非 `null`[^1]。 - **适用场景**:需确保任务完整执行的场景(如上传数据),避免中断导致数据丢失。 #### 4. **START_STICKY_COMPATIBILITY** - **行为**:`START_STICKY` 的兼容版本,**不保证** `onStartCommand()` 一定会被重新调用[^1]。 - **适用场景**:旧版本系统兼容,现代开发中较少使用。 #### 代码示例: ```java @Override public int onStartCommand(Intent intent, int flags, int startId) { // 执行任务逻辑(如下载或播放音乐) return START_REDELIVER_INTENT; // 根据需求选择返回值 } ``` #### 行为对比总结: | 返回值 | 是否自动重建 | 重建时 Intent 状态 | 典型场景 | |-------------------------|--------------|--------------------------|------------------------| | `START_STICKY` | ✅ | 可能为 `null`[^2] | 音乐播放、后台监控 | | `START_NOT_STICKY` | ❌ | 依赖新启动命令 | 单次下载、临时任务 | | `START_REDELIVER_INTENT`| ✅ | 保留原始 Intent[^1] | 数据上传、事务型操作 | | `START_STICKY_COMPATIBILITY`| ⚠️ | 不保证调用 | 旧系统兼容 | --- ### 相关问题 1. **Service 被系统杀死后,`START_REDELIVER_INTENT` 如何保证 Intent 不丢失?** > 系统会将未完成的 Intent 加入待处理队列,重建时重新传递[^1]。 2. **使用 `START_NOT_STICKY` 时,如何手动重建 Service?** > 需通过 `Context.startService()` 发送新 Intent 触发重建。 3. **`onStartCommand()` 的 `flags` 参数有哪些作用?** > 如 `START_FLAG_RETRY` 表示系统在失败后重试启动。 4. **前台服务(Foreground Service)是否受返回值影响?** > 是,重建行为同样遵循上述规则,但前台服务被杀死概率更低。 [^1]: 系统重建时重新传递原始 Intent。 [^2]: 重建时若无挂起 Intent 则传入 `null`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值