首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Service初涉

Service 初涉

作者:向阳逐梦

  • 2023-04-03四川
  • 本文字数:3591 字 阅读完需:约 12 分钟

本节开始我们继续来学习 Android 中的第二个组件:Service(服务),开始本节内容!

1.线程的相关概念

在开始学习 Service 之前我们先来了解下线程的一些概念!

1)相关概念:

  • 程序:为了完成特定任务,用某种语言编写的一组指令集合(一组静态代码)
  • 进程运行中的程序,系统调度与资源分配的一个独立单位,操作系统会为每个进程分配一段内存空间!程序的依次动态执行,经历代码的加载,执行,执行完毕的完整过程!
  • 线程:比进程更小的执行单元,每个进程可能有多条线程,线程需要放在一个进程中才能执行,线程由程序负责管理,而进程则由系统进行调度!
  • 多线程的理解并行执行多个条指令,将 CPU 时间片按照调度算法分配给各个线程,实际上是分时执行的,只是这个切换的时间很短,用户感觉到"同时"而已!

2)线程的生命周期:

3)创建线程的三种方式:

  1. 继承 Thread 类
  2. 实现 Runnable 接口
  3. 实现 Callable 接口如果:使用的是 2 创建的线程的话,可以直接这样启动:
代码语言:javascript
复制
new Thread(myThread).start();

复制代码

当更多的时候我们喜欢使用匿名类,即下面这种写法:

代码语言:javascript
复制
new Thread(new Runnable(){     public void run();         }).start();

复制代码

2.Service 与 Thread 线程的区别

其实他们两者并没有太大的关系,不过有很多朋友经常把这两个混淆了!Thread 是线程,程序执行的最小单元,分配 CPU 的基本单位!而 Service 则是 Android 提供一个允许长时间留驻后台的一个组件,最常见的用法就是做轮询操作!或者想在后台做一些事情,比如后台下载更新!记得别把这两个概念混淆!

3.Service 的生命周期图

4.生命周期解析

好的,从上图的生命周期,我们可以知道,Android 中使用 Service 的方式有两种:

1)StartService()启动 Service

2)BindService()启动 ServicePS:还有一种,就是启动 Service 后,绑定 Service!

1)相关方法详解:

  • onCreate():当 Service 第一次被创建后立即回调该方法,该方法在整个生命周期中只会调用一次!
  • onDestory():当 Service 被关闭时会回调该方法,该方法只会回调一次!
  • onStartCommand(intent,flag,startId):早期版本是 onStart(intent,startId),当客户端调用 startService(Intent)方法时会回调,可多次调用 StartService 方法,但不会再创建新的 Service 对象,而是继续复用前面产生的 Service 对象,但会继续回调 onStartCommand()方法!
  • IBinder onOnbind(intent):该方法是 Service 都必须实现的方法,该方法会返回一个 IBinder 对象,app 通过该对象与 Service 组件进行通信!
  • onUnbind(intent):当该 Service 上绑定的所有客户端都断开时会回调该方法!

2)StartService 启动 Service

首次启动会创建一个 Service 实例,依次调用 onCreate()和 onStartCommand()方法,此时 Service 进入运行状态,如果再次调用 StartService 启动 Service,将不会再创建新的 Service 对象,系统会直接复用前面创建的 Service 对象,调用它的 onStartCommand()方法!

但这样的 Service 与它的调用者无必然的联系,就是说当调用者结束了自己的生命周期,但是只要不调用 stopService,那么 Service 还是会继续运行的!

无论启动了多少次 Service,只需调用一次 StopService 即可停掉 Service

3)BindService 启动 Service

当首次使用 bindService 绑定一个 Service 时,系统会实例化一个 Service 实例,并调用其 onCreate()和 onBind()方法,然后调用者就可以通过 IBinder 和 Service 进行交互了,此后如果再次使用 bindService 绑定 Service,系统不会创建新的 Sevice 实例,也不会再调用 onBind()方法,只会直接把 IBinder 对象传递给其他后来增加的客户端!

如果我们解除与服务的绑定,只需调用 unbindService(),此时 onUnbind 和 onDestory 方法将会被调用!这是一个客户端的情况,假如是多个客户端绑定同一个 Service 的话,情况如下当一个客户完成和 service 之间的互动后,它调用 unbindService() 方法来解除绑定。当所有的客户端都和 service 解除绑定后,系统会销毁 service。(除非 service 也被 startService()方法开启)

另外,和上面那张情况不同,bindService 模式下的 Service 是与调用者相互关联的,可以理解为"一条绳子上的蚂蚱",要死一起死,在 bindService 后,一旦调用者销毁,那么 Service 也立即终止!通过 BindService 调用 Service 时调用的 Context 的 bindService 的解析

bindService(Intent Service,ServiceConnection conn,int flags)

service:通过该 intent 指定要启动的 Service

conn:ServiceConnection 对象,用户监听访问者与 Service 间的连接情况,连接成功回调该对象中的 onServiceConnected(ComponentName,IBinder)方法;如果 Service 所在的宿主由于异常终止或者其他原因终止,导致 Service 与访问者间断开连接时调用

onServiceDisconnected(CompanentName)方法,主动通过

unBindService()方法断开并不会调用上述方法!

flags:指定绑定时是否自动创建 Service(如果 Service 还未创建),参数可以是 0(不自动创建),BIND_AUTO_CREATE(自动创建)

4)StartService 启动 Service 后 bindService 绑定

如果 Service 已经由某个客户端通过 StartService()启动,接下来由其他客户端再调用 bindService()绑定到该 Service 后调用 unbindService()解除绑定最后在调用 bindService()绑定到 Service 的话,此时所触发的生命周期方法如下:onCreate( )->onStartCommand( )->onBind( )->onUnbind( )->onRebind( )PS:前提是:onUnbind()方法返回 true!!!这里或许部分读者有疑惑了,调用了 unbindService 后 Service 不是应该调用 onDistory()方法么!其实这是因为这个 Service 是由我们的 StartService 来启动的,所以你调用 onUnbind()方法取消绑定,Service 也是不会终止的!得出的结论:假如我们使用 bindService 来绑定一个启动的 Service,注意是已经启动的 Service!!!系统只是将 Service 的内部 IBinder 对象传递给 Activity,并不会将 Service 的生命周期与 Activity 绑定,因此调用 unBindService( )方法取消绑定时,Service 也不会被销毁!

5.生命周期验证

接下来我们写代码来验证下生命周期:

1)验证 StartService 启动 Service 的调用顺序

首先我们自定义一个 Service,重写相关的方法,用户在 logcat 上打印验证:

TestService1.java

代码语言:javascript
复制
public class TestService1 extends Service {      private final String TAG = "TestService1";        //必须要实现的方法      @Override      public IBinder onBind(Intent intent) {          Log.i(TAG, "onBind方法被调用!");          return null;      }        //Service被创建时调用      @Override      public void onCreate() {          Log.i(TAG, "onCreate方法被调用!");          super.onCreate();      }            //Service被启动时调用      @Override      public int onStartCommand(Intent intent, int flags, int startId) {          Log.i(TAG, "onStartCommand方法被调用!");          return super.onStartCommand(intent, flags, startId);      }            //Service被关闭之前回调      @Override      public void onDestroy() {          Log.i(TAG, "onDestory方法被调用!");          super.onDestroy();      }  }

复制代码

AndroidManifest.xml 完成 Service 注册

代码语言:javascript
复制
<!-- 配置Service组件,同时配置一个action -->  <service android:name=".TestService1">              <intent-filter>                  <action android:name="com.jay.example.service.TEST_SERVICE1"/>              </intent-filter>  </service>  

复制代码

再接着是简单的布局文件,两个按钮,再最后是 MainActivity 的编写,在按钮的点击事件中分别调用 startService( )和 stopService( )!

代码语言:javascript
复制
public class MainActivity extends Activity {        private Button start;      private Button stop;            @Override      protected void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.activity_main);                    start = (Button) findViewById(R.id.btnstart);          stop = (Button) findViewById(R.id.btnstop);          //创建启动Service的Intent,以及Intent属性          final Intent intent = new Intent();          intent.setAction("com.jay.example.service.TEST_SERVICE1");          //为两个按钮设置点击事件,分别是启动与停止service          start.setOnClickListener(new OnClickListener() {                          @Override              public void onClick(View v) {                  startService(intent);                             }          });                    stop.setOnClickListener(new OnClickListener() {                       @Override              public void onClick(View v) {                  stopService(intent);                                }          });      }  }

复制代码

运行截图:

点击开始服务:

吃饱饭没事做,点多几下:

最后点击停止服务:

发布于: 17 小时前阅读数: 511

版权声明: 本文为 InfoQ 作者【向阳逐梦】的原创文章。

原文链接:【https://xie.infoq.cn/article/c0f5c8655139a62433d9e60fa】。文章转载请联系作者。

  • 发表于:
  • 本文为 InfoQ 中文站特供稿件
  • 首发地址https://www.infoq.cn/article/c0f5c8655139a62433d9e60fa
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券