Service 深度解析

通过android:process指定的远程服务是运行在一个独立的进程里,比如说接入消息推送之类的,需要建立长连接。

以下默认是local Service

  • 服务适用于不需要和用户交互,又需要长期运行的任务。

  • 服务的运行不依赖于任何用户界面,即使程序切换到了后台,服务仍能正常运行。

  • 服务并不是运行在一个独立的进程中,而是依赖创建服务时所在的应用程序进程(默认运行在主线程中)。

  • 服务并不会自动创建线程,需要手动开启线程,才能执行耗时操作。

  • 每个服务只会存在一个实例,无论多次startService还是bindService获取到的实例

  • 服务启动了就会一直处于运行状态,除非执行stopService或者stopSelf (调用unbind不会停止service)

  • 需要在AndroidManifest中声明

既然服务和线程没有任何关系,而且服务工作在主线程中,不能执行耗时操作(无论是按键超时、服务超时、广播超时都会造成ANR);那服务有啥用呢?让服务执行耗时操作需要手动开启线程,线程不也可以长时间运行么?

官方解释:

A service is simply a component that can run in the background, even when the user is not interacting with your application, so you should create a service only if that is what you need.
If you must perform work outside of your main thread, but only while the user is interacting with your application, you should instead create a new thread.

If you create a Thread or an Executor in an Activity of your app, this leads to unpredictable results, since a simple screen orientation change will disrupt things, since the Activity will no longer be around when the Thread completes its task.You could use AsyncTask to handle this, but what if your app needs this Background Thread to be started from not just an Activity, but a notification or another component?

In these cases, Android Services are the right Android component to use to match up the Thread’s lifecycle with that of the Service’s lifecycle.

1、Thread 的运行是独立于Activity的,也就是说当一个Activity被finish之后,如果你没有主动停止Thread或者Thread里的run方法没有执行完毕的话,Thread 也会一直执行。在线程执行完毕,我们可以手动stopself让service结束,避免浪费资源。

2、当Activity被finish之后,不再持有该Thread的引用,也就不能在不同的Activity中对同一Thread进行控制。而我们可以在任何有Context的地方调用Context.startService、Context.stopService、Context.bindService,Context.unbindService 来操作service。

Service 深度解析

Android多线程编程

Android的单线程模型

1.不能阻塞UI线程。 所有耗时操作(网络、数据库、大文件等)都应该放在子线程中操作

2.不能在UI线程之外访问Android UI 。因为更新UI的方法不是线程安全的(更新时会进行线程检查)

所以一般在子线程中执行耗时操作,再回到主线程( UI线程 )更新UI。(一般通过Handler进行操作)

Handle模型

Handle/Message/MessageQueue/Looper 实现线程间交互

1、每个线程都只有一个MessageQueue,一个Looper

2、handle.sendMessage()会将message放入当前线程的Messagequeue中,等待执行

3、looper.loop()遍历MessageQueue中的每个message,执行msg.target.handleMessage(),回调handler的handleMessage()

详情请见:

服务的生命周期

  • onCreate() 服务创建的时候调用(只调用一次)

  • onStartCommand() 服务每次启动的时候调用(虽然每次startService都会调用一次,但每个服务都只会存在一个实例)

  • onDestroy() 服务销毁时调用(如果startService & bindService,则要调用stopService & unbindService,才回调onDestroy)

执行1-2 日志:onCreate -> onStartCommand -> onDestroy

执行1-1-2 日志:onCreate -> onStartCommand -> onStartCommand -> onDestroy (onStartCommand会执行多次)

执行3-4 日志:onCreate -> onBind -> onServiceConnected -> onDestroy (直接bindService创建的服务不会执行onStartCommand)

执行1-3-4-2 日志:onCreate -> onStartCommand -> onBind -> onServiceConnected -> onDestroy (既执行了startService,又执行了bindService)

执行4 日志:service not Registed exception (没有bind,不能执行unbind)

执行1-4 日志:service not Registed exception

执行1-3-4-4 日志:onCreate -> onStartCommand -> onBind -> onServiceConnected -> service not Registed exception (已经unbind之后,未bind,也不能unbind)

在activity中执行3,退出activity,报错has leaked ServiceConnection,会执行onDestroy

在activity中执行1,退出activity,不报错,不会执行onDestroy,服务启动了就会一直处于运行状态,除非执行stopService 或者 stopSelf

当activity 和 service 绑定之后,就可以调用该服务中 binder 提供的方法了

  1. startServic
val intent = Intent(this, MyService::class.java)
startService(intent)
  1. stopService
val intent = Intent(this, MyService::class.java)
stopService(intent)
  1. bindService
val intent = Intent(this, MyService::class.java)
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)

4.unbindService

unbindService(serviceConnection)

服务的使用

通过startService 和stopService只是启动和结束服务,但是activity和service并没有建立关联,activity并不能定点让service干什么工作。

由bindService来建立 activity 和 service 之间的联系,onBind返回的IBinder类向上转型,为service中定义的Binder类,得到了Binder实例,就可以调用Binder中定义的方法。

var downloadBinder: MyService.DownLoadBinder? = null

val serviceConnection = object  : ServiceConnection{
    override fun onServiceDisconnected(name: ComponentName?) {
        LogUtils.e(" onServiceDisconnected invoke!!!")
    }

    override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
        LogUtils.e(" onServiceConnected invoke!!!")
        downloadBinder = service as MyService.DownLoadBinder? //向上转型
        downloadBinder?.startDownLoad() //调用bind的方法
        downloadBinder?.getProgress()
    }
}

MyService.java

public class MyService extends Service {

    private DownLoadBinder mBinder = new DownLoadBinder();

    public static class DownLoadBinder extends Binder {

        public void startDownLoad() {
            Log.e("zhen", "startDownLoad");
        }

        public void getProgress() {
            Log.e("zhen", "getProgress");
        }

    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e("zhen", "onCreate");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e("zhen", "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e("zhen", "onBind");
        return mBinder;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e("zhen", "onDestroy");
    }
}

AndroidManifest中注册

android:exported=“true” 表示允许除当前程序之外的其它程序访问这个服务,默认为true

android:enabled=“true” 表示启动这个服务,默认为true

<service android:name=".module.service.MyService"
    android:exported="true"
    android:enabled="true"/>