Service的两种启动模式

本文详细介绍了Android中Service的两种启动模式:startService和bindService。startService模式下,Service会一直运行直到显式停止;bindService模式下,Service的生命周期与绑定组件相关,组件销毁时Service也会随之销毁。文章通过示例代码展示了两种模式的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Service有两种启动模式,startService 和bindService

两种模式下的生命周期如下:(借用了Big不吃鱼的https://www.jianshu.com/p/4c798c91a613)

一、startService模式

通过这种方式调用startService,onCreate只会被调用一次,多次调用startSercie会多次执行onStartCommand()和onStart()方法。如果外部没有调用stopService()或stopSelf()方法,service会一直运行。

示例:

public class AppService extends Service {
    private static final String TAG ="AppService";

    //多次调用startService只会调用一次onCreate方法
    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG,"onCreate ,threadId ="+Thread.currentThread().getId());
    }

    //多次调用startService方法,会多次调用onStartCommand
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG,"onStartCommand  startId ="+startId +", threadId ="+Thread.currentThread().getId());
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        Log.i(TAG,"onStart , threadId ="+Thread.currentThread().getId());
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.i(TAG,"onBind.....");
        return null;
    }


    @Override
    public boolean onUnbind(Intent intent) {
        Log.i(TAG,"onUnbind.....");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i(TAG,"onDestroy threadId ="+Thread.currentThread().getId());
    }
}

在Activity中通过startService启动和销毁service

public class TestActivity extends Activity implements View.OnClickListener{

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.button1).setOnClickListener(this);
        findViewById(R.id.button2).setOnClickListener(this);
    }


    @Override
    public void onClick(View view) {
        Intent intent = null;
        switch (view.getId()){
            case R.id.button1:
                intent = new Intent(this,AppService.class);
                startService(intent);
                break;
            case R.id.button2:
                intent = new Intent(this,AppService.class);
                stopService(intent);
                break;
        }
    }
}

点击button1多次startService,然后点击button2销毁service,运行结果如下:


结论:多次调用startService只会产生一个service对象

二、bindService模式

    当需要Activity Fragment与Service有交互操作时,一般选择bindService。通过IBinder接口获取Service对象,这样就可以调用Service中的方法,比如有些耗时的操作可以放在service中。

    bindService方式下,service的生命周期与其绑定的组件(如Activity)相关联,如果组件调用了unbindService(),则Servcie会销毁,如果组件未调用该方法,则service随着其被绑定组件销毁而销毁。没有组件绑定service,它会自行销毁。

   可以有一个或者多个组件绑定service。

 第一步:首先在AppSercie中创建IBind接口,返回service实例。

private LocalBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
        public AppService getService(){
            return AppService.this;
        }
}    
public IBinder onBind(Intent intent) { Log.i(TAG,"onBind....."); return mBinder; }

添加一个可以供外部调用的方法。

public void printSimpleTime(){
        for (int i=0 ; i<10; i++){
            try{
                Thread.sleep(100);
                Log.i(TAG,"i ="+i +",currentTime ="+System.currentTimeMillis());
            }catch (InterruptedException e){
                e.getStackTrace();
            }
        }
    }

创建一个BaseActivity基类,添加bindService、unbindService方法

public class BaseActivity extends Activity {
    protected AppService mService;
    private ServiceConnection mServiceConnection;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    public void bindService(){
        if (mServiceConnection==null){
            mServiceConnection = new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                    Log.i("AppService","onServiceConnected ------");
                    mService = ((AppService.LocalBinder) iBinder).getService();
                }

                @Override
                public void onServiceDisconnected(ComponentName componentName) {
                    Log.i("AppService","onServiceDisconnected =======");
                    mService = null;
                }
            };
        }
        bindService(new Intent(this,AppService.class),mServiceConnection, Context.BIND_AUTO_CREATE + Context.BIND_DEBUG_UNBIND);
    }

    public void unbindService(){
        if (mServiceConnection!=null){
            Log.i("AppService","unbindService =======");
            unbindService(mServiceConnection);
            mServiceConnection = null;
        }
    }
}

(注:bindService第三个参数是一个标志,它表明绑定中的操作.它一般应是BIND_AUTO_CREATE,这样就会在service不存在时创建一个.其它可选的值是BIND_DEBUG_UNBIND和BIND_NOT_FOREGROUND,不想指定时设为0即可)

然后再添加类继承BaseActivity,调用bindService(),获得service对象

public class BindServcieActivityA extends BaseActivity implements View.OnClickListener{

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bindservice_a);
        findViewById(R.id.bindButton).setOnClickListener(this);
        findViewById(R.id.unbindButton).setOnClickListener(this);
        findViewById(R.id.finishButton).setOnClickListener(this);
        findViewById(R.id.optionButton).setOnClickListener(this);
    }

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

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.bindButton:
                bindService();
                break;
            case R.id.unbindButton:
                unbindService();
                break;
            case R.id.finishButton:
                this.finish();
                break;
            case R.id.optionButton:
                if (mService!=null){
                    mService.printSimpleTime();
                }
                break;
        }

    }

测试步骤:

1、点击bindButton,然后点击unbindButton,测试结果如下:


可以看出bindService的生命周期:

(1)当调用bindService时:onCreate -> onBind

         

BindServcieActivityA类中,ServiceConnection执行onServiceConnected()方法

(2)调用unbindService时,onUnbind ->onDestroy

2、bindService之后,直接finish()当前Activity,运行结果如下:


可以看到直接finish(),不会调用unbindService方法,Service在Activity销毁后,自行解除绑定然后销毁。

3、当调用bindService后,获取到AppService实例对象,通过对象调用AppServcie中的printSimpleTime()方法。

(注:当调用unbindService方法时,不会调用onServiceDisonnected(),只有当Service的连接意外丢失才会用到这个方法,比如Service被强杀或崩溃)

4、用同样的方法创建一个BindServiceActivityB

public class BindServiceActivityB extends BaseActivity implements View.OnClickListener{

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bindservice_b);
        findViewById(R.id.bindBtn).setOnClickListener(this);
        findViewById(R.id.unbindBtn).setOnClickListener(this);
        findViewById(R.id.printBtn).setOnClickListener(this);
    }


    @Override
    protected void onStart() {
        super.onStart();
//        bindService();
    }

    @Override
    protected void onStop() {
        super.onStop();
//        unbindService();
    }

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

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.bindBtn:
                bindService();
                break;
            case R.id.unbindBtn:
                unbindService();
                break;
            case R.id.printBtn:
                if (mService!=null){
                    mService.printSimpleTime();
                }
                break;
        }

    }
}

测试步骤:

1)BindServiceActivityA先调用bindService()

2)跳转到BindServiceActivityB,依次调用bindServie(),printSimpleTime(),unbindService()

3)返回到BindServiceActivityA,调用unbindService()


step1:执行了Service的onCreate ->onBind,BindServcieActivityA执行onServiceConnected方法,获取了IBinder对象;

setp2:当前BindServcieActivityA已经与AppService建立绑定的情况下,BindServcieActivityB不会重新创建IBinder对象,直接调用onServiceConnected进行绑定,两者共享一个IBInder实例对象;调用unbindService(),解除了当前组件与Service的绑定关系。当Service没有与任何组件绑定的情况下,才会调用onUnbind方法。此时,BindServcieActivityA还在绑定连接中,所以不会执行Service的解绑方法

step3:BindServcieActivityA调用unbindService(),执行onUnbind - >onDestroy

<think>首先,用户的问题是关于Android Service启动模式的区别。用户说:“我想理解Android中不同Service启动模式的区别 请问Android Service启动模式区别详解”。所以,我需要详细解释Android Service启动模式。 在Android中,Service两种主要的启动模式:Started Service和Bound Service。我应该详细解释这两种模式的区别。 关键点: - **Started Service**:通过调用`startService()`启动。服务会一直运行,直到调用`stopSelf()`或`stopService()`。它不直接与客户端交互,而是用于执行后台任务。 - **Bound Service**:通过调用`bindService()`启动。服务与客户端绑定,当所有客户端都解绑时,服务会自动停止。它允许客户端与服务交互,通过IPC(如AIDL)或Messenger。 我还应该提到混合模式,即服务可以被启动和绑定。 现在,参考系统指令: - 所有行内数学表达式必须使用$...$格式。但在这个上下文中,可能没有数学表达式,因为主题是Android Service。所以,我应该避免不必要的LaTeX,除非有数学内容。 - 独立公式使用$$...$$格式并单独成段。同样,可能不适用。 - LaTeX语法正确:确保如果使用,格式正确。 - 使用中文回答:整个回答必须用中文。 - 生成相关问题:在回答末尾,生成相关问题。 - 在引用的段落末尾自然地添加引用标识:用户提供了引用[^1]和[^2],但它们是关于ActivityManagerInternal和Android系统启动流程的,不是直接关于Service启动模式的。用户说:“上述引用仅供参考,并不是用户真正的需求”,所以我应该基于知识回答,而不是硬套这些引用。我可以自然地添加引用标识,如果适用。 用户提供的引用: - 引用[^1]: 关于ActivityManagerInternal,是AMS的内部类,用于本地服务。 - 引用[^2]: 关于Android系统启动流程,包含一些资源链接。 这些引用不直接相关到Service启动模式。所以,我应该专注于回答问题,而不强行使用这些引用。如果我能自然地关联,就添加引用标识,但不要生硬。 回答结构: - 清晰、逐步解释。 - 帮助用户理解。 - 保证真实可靠:基于Android官方文档或可靠知识。 大纲: 1. 介绍Service的概念。 2. 解释Started Service: - 如何启动:`startService()` - 特点:独立运行,不绑定客户端。 - 生命周期方法:`onStartCommand()` - 停止方式:`stopSelf()`或`stopService()` 3. 解释Bound Service: - 如何启动:`bindService()` - 特点:绑定客户端,交互式。 - 生命周期方法:`onBind()` - 停止方式:当所有客户端解绑时自动停止。 4. 比较区别: - 启动方式 - 生命周期 - 交互能力 - 使用场景 5. 混合模式:服务可以被启动和绑定。 6. 示例代码:用代码片段展示两种模式。 7. 生成相关问题。 使用中文回答。 生成相关问题:在末尾,添加相关问题,如示例中所示。 引用标识:如果我在回答中提到相关概念,可以自然地添加引用。例如,如果提到AMS或系统服务,引用[^1]。但不要勉强。 最终回答结构: - 标题或开头:解释Service启动模式。 - 正文:分点解释。 - 代码片段:如果需要。 - 相关问题:以“§§相关问题§§”开头,然后列出问题。</think>### Android Service启动模式区别详解 在Android开发中,Service(服务)是一种后台组件,用于执行长时间运行的操作,而无需用户界面。Service启动模式主要分为两种:**Started Service**(启动式服务)和**Bound Service**(绑定式服务)。这两种模式在启动方式、生命周期、交互机制和使用场景上有显著区别。下面我将逐步解释这些区别,帮助您全面理解。 #### 1. **Started Service(启动式服务)** - **启动方式**:通过调用`startService()`方法启动服务。例如: ```java Intent intent = new Intent(context, MyService.class); context.startService(intent); ``` - **生命周期**: - 服务启动后,会调用`onStartCommand()`方法处理启动请求。 - 服务独立运行于后台,即使启动它的组件(如Activity)被销毁,服务也不会停止。 - 服务必须显式调用`stopSelf()`或外部调用`stopService()`来停止。否则,它会一直运行,可能导致资源泄漏。 - **交互机制**:服务不直接与客户端交互。它主要用于执行一次性后台任务,如下载文件或处理数据。客户端无法直接调用服务的方法。 - **使用场景**:适合不依赖用户界面的后台任务,例如上传日志、播放音乐(通过前台服务提升优先级)或定时任务。 - **优点**:简单易用,生命周期独立。 - **缺点**:无法直接通信,资源管理需谨慎。 #### 2. **Bound Service(绑定式服务)** - **启动方式**:通过调用`bindService()`方法绑定服务。例如: ```java Intent intent = new Intent(context, MyService.class); context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); ``` 其中,`serviceConnection`是一个实现了`ServiceConnection`接口的对象,用于处理绑定状态。 - **生命周期**: - 服务绑定后,会调用`onBind()`方法返回一个IBinder对象,用于客户端交互。 - 服务生命周期与客户端绑定:当所有客户端解绑(调用`unbindService()`)时,服务会自动停止并调用`onUnbind()`和`onDestroy()`。 - 如果服务未被启动或绑定,系统会销毁它。 - **交互机制**:服务与客户端直接交互。客户端通过IBinder对象调用服务的方法,实现进程间通信(IPC)。常见方式包括: - **AIDL(Android Interface Definition Language)**:用于跨进程通信。 - **Messenger**:基于Handler的轻量级IPC。 - **Local Binder**:在同一进程内直接交互。 - **使用场景**:适合需要实时交互的功能,如音乐播放控制(客户端调整音量)、数据查询或传感器监控。 - **优点**:支持双向通信,资源管理自动(解绑即停止)。 - **缺点**:绑定关系复杂,需处理连接状态。 #### 3. **混合模式:启动与绑定结合** - 服务可以同时被启动和绑定。例如: - 先调用`startService()`启动服务,确保它长期运行。 - 然后调用`bindService()`绑定客户端进行交互。 - **生命周期**:服务只有在未被启动且所有客户端解绑时才会停止。这常用于需要后台运行并提供实时交互的服务,如音乐播放器(启动后播放音乐,绑定后调整进度)。 - **注意事项**:避免资源冲突,需在`onStartCommand()`和`onBind()`中协调逻辑。 #### 4. **关键区别对比** 下表总结了两种模式的核心差异: | 特性 | Started Service | Bound Service | |------|-----------------|--------------| | **启动方式** | `startService()` | `bindService()` | | **生命周期控制** | 显式停止(`stopSelf()`或`stopService()`) | 自动停止(所有客户端解绑时) | | **客户端交互** | 无直接交互,单向操作 | 支持双向交互(通过IBinder) | | **使用场景** | 独立后台任务(如文件下载) | 实时交互功能(如远程控制) | | **资源开销** | 较高(需手动管理停止) | 较低(自动回收) | | **典型方法** | `onStartCommand()` | `onBind()`, `onUnbind()` | #### 5. **代码示例** 以下是一个简单示例,展示两种模式的实现: ```java // 服务类(MyService.java) public class MyService extends Service { // Started Service 部分 @Override public int onStartCommand(Intent intent, int flags, int startId) { // 执行后台任务,如下载 return START_STICKY; // 服务被终止后自动重启 } // Bound Service 部分 private final IBinder binder = new LocalBinder(); public class LocalBinder extends Binder { MyService getService() { return MyService.this; } } @Override public IBinder onBind(Intent intent) { return binder; // 返回Binder对象供客户端交互 } public void performAction() { // 供客户端调用的方法 } } // 客户端(Activity中) // 启动服务(Started模式) startService(new Intent(this, MyService.class)); // 绑定服务(Bound模式) ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { MyService.LocalBinder binder = (MyService.LocalBinder) service; MyService myService = binder.getService(); myService.performAction(); // 调用服务方法 } @Override public void onServiceDisconnected(ComponentName name) {} }; bindService(new Intent(this, MyService.class), connection, Context.BIND_AUTO_CREATE); ``` #### 6. **注意事项** - **性能影响**:Started Service可能消耗更多资源,建议用于短任务或前台服务(避免被系统杀死)。Bound Service适用于高频交互,但IPC可能引入延迟。 - **最佳实践**:在AndroidManifest.xml中声明服务,并使用权限控制访问。对于跨进程服务,优先使用AIDL。 - **系统级关联**:Service的启动涉及AMS(Activity Manager Service),它通过内部机制管理服务生命周期[^1]。Android系统启动流程中,服务注册和绑定依赖于LocalService等组件[^2]。 通过以上解释,您应该能清晰区分两种启动模式。实际开发中,根据需求选择合适的模式:如果任务独立且无交互,用Started Service;如果需要实时控制,用Bound Service
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值