【Android】Service

时间:2024-11-03 22:54:22

文章目录

      • 1.service
      • 2.startService
      • 3.bindService
      • 4.区别

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:

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

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;
        }
    }
}
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 并让它完成任务。

示例代码

// 启动 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 的资源。

示例代码

// 定义 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 进行持续通信的场景。