【Android】Service

文章目录

1.service

在Android开发中,Service 是一个可以在后台长时间运行的组件,用于执行耗时操作或执行那些不需要与用户界面直接交互的任务。Service 不依赖于用户界面,即使用户切换到其他应用,Service 仍然可以继续运行。

Service 的主要用途

  • 后台任务:执行耗时操作,如下载文件、播放音乐等。
  • 跨进程通信:通过 AIDL 实现跨进程通信(IPC)。
  • 定时任务:定期执行某些任务,如定时同步数据。
  • 保持连接:维持与服务器的长连接,如实时聊天应用。

Service生命周期

  • onCreate():当 Service 第一次被创建时调用。
  • onStartCommand(Intent intent, int flags, int startId):每当通过 startService() 方法启动 Service 时调用。
  • onBind(Intent intent):每当通过 bindService() 方法绑定到 Service 时调用。
  • onUnbind(Intent intent):当所有客户端都解除绑定时调用。
  • onDestroy():当 Service 被销毁时调用。

2.startService

循环打印日志Service:

java 复制代码
public class MyService extends Service {

    private static final String TAG = "ning";
    private ExecutorService executorService;

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "MyService onCreate");

        // 创建一个单线程的ExecutorService
        executorService = Executors.newSingleThreadExecutor();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "MyService onStartCommand");

        // 提交一个任务到线程池,周期性地打印日志
        executorService.submit(() -> {
            while (true) {
                Log.d(TAG, "MyService logging at " + System.currentTimeMillis());
                try {
                    Thread.sleep(1000); // 每秒打印一次日志
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        return START_STICKY; // 服务被系统杀死后自动重启
    }

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

        // 关闭线程池
        if (executorService != null) {
            executorService.shutdownNow();
        }
    }

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

3.bindService

java 复制代码
public class ServiceBindActivity extends AppCompatActivity {

    private Button btn_bind;

    private Button btn_cancel;

    private Button btn_status;

    private static final String TAG = "ning";


    private MyBindService myBindService;

    private boolean isBound = false;

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "onServiceConnected");
            MyBindService.LocalBinder binder = (MyBindService.LocalBinder) service;
            myBindService = binder.getService();
            isBound = true;
            // 调用 Service 的方法
            myBindService.doSomething();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "onServiceDisconnected");
            isBound = false;
        }
    };



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_service_bind);
        btn_bind = findViewById(R.id.btn_bind);
        btn_cancel = findViewById(R.id.btn_cancel);
        btn_status = findViewById(R.id.btn_status);

        Intent intent = new Intent(this, MyBindService.class);
        btn_bind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 绑定 Service
                bindService(intent, connection, Context.BIND_AUTO_CREATE);
            }
        });

        btn_cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 解绑 Service
                unbindService(connection);
            }
        });

        btn_status.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 获取 Service 状态
                Log.d(TAG, "Service status: " + (myBindService == null ? "null" : "not null"));
            }
        });




    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 解绑 Service
        if (isBound) {
            unbindService(connection);
            isBound = false;
        }
    }
}
java 复制代码
public class MyBindService extends Service {


    private static final String TAG = "ning";
    private final IBinder binder = new LocalBinder();

    public class LocalBinder extends Binder {
        MyBindService getService() {
            return MyBindService.this;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "MyBoundService onCreate");
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "MyBoundService onBind");
        return binder;
    }

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

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

    public void doSomething() {
        Log.d(TAG, "MyBoundService doSomething called");
    }
}

4.区别

在 Android 中,startServicebindService 都是用来启动和管理 Service 的方法,但它们的使用场景和行为有所不同。下面是它们的主要区别和使用场景:

startService

功能

  • 启动型 Service :通过 startService 方法启动的 Service 是启动型 Service,主要用于执行一次性的后台任务,如下载文件、上传数据等。
  • 生命周期Service 会一直运行,直到它自己调用 stopSelf 方法或者外部调用 stopService 方法将其停止。
  • 回调方法 :主要使用 onStartCommand 方法来处理启动请求。

使用场景

  • 后台任务:执行耗时操作,如下载文件、上传数据、处理大量数据等。
  • 定时任务:定期执行某些任务,如定时同步数据。
  • 无需与 Service 交互 :不需要与 Service 进行持续的通信,只需要启动 Service 并让它完成任务。

示例代码

java 复制代码
// 启动 Service
Intent intent = new Intent(this, MyStartedService.class);
startService(intent);

// 停止 Service
stopService(intent);

bindService

功能

  • 绑定型 Service :通过 bindService 方法启动的 Service 是绑定型 Service,主要用于组件之间的交互,如 ActivityService 之间的数据交换。
  • 生命周期Service 会一直运行,直到所有绑定的客户端都解除绑定。当最后一个客户端解除绑定时,Service 会调用 onUnbind 方法,并最终调用 onDestroy 方法。
  • 回调方法 :主要使用 onBind 方法来返回一个 IBinder 对象,用于客户端与 Service 之间的通信。

使用场景

  • 持续交互 :需要与 Service 进行持续的通信,如播放音乐、实时数据更新等。
  • 跨进程通信 :通过 AIDL 实现跨进程通信。
  • 资源共享 :多个组件共享同一个 Service 的资源。

示例代码

java 复制代码
// 定义 ServiceConnection
private ServiceConnection connection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.d("TAG", "onServiceConnected");
        LocalBinder binder = (LocalBinder) service;
        myBoundService = binder.getService();
        isBound = true;
        // 调用 Service 的方法
        myBoundService.doSomething();
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        Log.d("TAG", "onServiceDisconnected");
        isBound = false;
    }
};

// 绑定 Service
Intent intent = new Intent(this, MyBoundService.class);
bindService(intent, connection, Context.BIND_AUTO_CREATE);

// 解绑 Service
if (isBound) {
    unbindService(connection);
    isBound = false;
}

总结

  • startService

    • 用于启动一次性的后台任务。
    • Service 会一直运行,直到显式停止。
    • 主要使用 onStartCommand 方法处理任务。
    • 适用于不需要与 Service 进行持续通信的场景。
  • bindService

    • 用于组件之间的持续交互。
    • Service 的生命周期与绑定的客户端相关,当所有客户端解除绑定时,Service 会停止。
    • 主要使用 onBind 方法返回 IBinder 对象进行通信。
    • 适用于需要与 Service 进行持续通信的场景。
相关推荐
super_lzb5 分钟前
mybatis拦截器ParameterHandler详解
java·数据库·spring boot·spring·mybatis
程序之巅6 分钟前
VS code 远程python代码debug
android·java·python
我是Superman丶18 分钟前
【异常】Spring Ai Alibaba 流式输出卡住无响应的问题
java·后端·spring
墨雨晨曦8818 分钟前
Nacos
java
invicinble27 分钟前
seata的认识与实际开发要做的事情
java
乌日尼乐1 小时前
【Java基础整理】Java多线程
java·后端
2501_941870561 小时前
从配置频繁变动到动态配置体系落地的互联网系统工程实践随笔与多语言语法思考
java·前端·python
恋猫de小郭1 小时前
罗技鼠标因为服务器证书过期无法使用?我是如何解决 SSL 证书问题
android·前端·flutter
yongui478342 小时前
MATLAB中回归模型常用误差指标(MSE、RMSE、MAPE等)的实现方法
android·matlab·回归
她说..2 小时前
Spring 核心工具类 AopUtils 超详细全解
java·后端·spring·springboot·spring aop