Android组件2——Service详解

149 阅读3分钟

一、Service的应用场景,以及和Thread区别

1.1 Service是什么?

Service(服务)是一个一种可以在后台执行长时间运行操作而没有用户界面的应用组件

1.2 Service和Thread的区别

A 定义:
Thread程序执行的最小单元,它是分配CPU的基本单位。可以用 Thread 来执行一些异步的操作。
Service是Android的一种机制。当它运行的时候如果是Local Service,那么对应的 Service 是运行在主进程的 main 线程上的。
Thread运行相对独立,Service运行是依托它所在的主线程。相比Thread,Service并不独立。

B 实际开发
Service运行在主线程,不可以做耗时操作。 如果要在Service中进行耗时操作,则需要开启单独的线程。
Thread运行在后台线程(也就是工作线程),可以进行耗时操作。

C 应用场景
需要执行耗时的网络,文件数据的查询,以及其他阻塞UI线程,都应该使用工作线程,也就是开启一个子线程。 需要长时间在后台运行,且不需要交互的情况下使用Service。如播放音乐,开启天气预报统计、数据统计等

二、生命周期

image.png service生命周期图

三、开启Service的两种方式以及区别

Service的方法:
onBind
绑定服务时才会调用,必须要实现的方法。
onCreate
首次创建服务时,系统将调用此方法来执行一次性设置程序(在调用onStartCommand() 或 onBind() 之前),如果服务已在运行,则不会调用此方法,该方法只被调用一次。
onStartCommand
每次通过startService() 方法启动Service时都会被回调。
onDestroy
服务销毁时回调

3.1 方法一:startService

  1. 定义一个类继承Service
  2. 在Manifest.xml文件中配置改Service
  3. 使用Context的startService(Intent)方法启动该Service
  4. 不再使用时,调用stopService(Intent)方法停止该服务

3.2 方法二: bindService

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private ServiceConnection connection;
    private BindService mService;
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final Intent intent = new Intent(this, BindService.class);
        // 绑定服务
        findViewById(R.id.band_service).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d(TAG, "绑定调用:bindService");
                bindService(intent, connection, Service.BIND_AUTO_CREATE);
            }
        });

        // 获取数据
        findViewById(R.id.get_data).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mService != null) {
                    Log.d(TAG, "获取的数据:" + mService.getTestNum());

                } else {
                    Log.d(TAG, "未绑定,无法获取数据");
                }
            }
        });

        // 解绑服务
        findViewById(R.id.unband_service).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d(TAG, "解绑调用:unbindService");
                if (mService != null) {
                    mService = null;
                    unbindService(connection);
                }
            }
        });

        connection = new ServiceConnection() {
            /**
             * 与服务器端交互的接口方法,绑定服务的时候被回调,在这个方法获取绑定service传递过来的IBinder对象
             * 通过这个IBinder对象,实现宿主和Service的交互
             */
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.d(TAG, "绑定成功调用 onServiceConnected");
                BindService.LocalBinder binder = (BindService.LocalBinder) service;
                mService = binder.getService();
            }

            /**
             * 当取消绑定的时候被回调,但正常情况下是不被调用的,它的调用时机是当Service服务被意外销毁时,
             * 例如内存的资源不足时这个方法才被自动调用
             */
            @Override
            public void onServiceDisconnected(ComponentName name) {
                mService = null;
            }
        };
    }
}

BindService.java

import androidx.annotation.Nullable;

public class BindService extends Service {
    private LocalBinder binder = new LocalBinder();

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

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

    public int getTestNum() {
        return 5;
    }
}

总结步骤如下:

  1. 创建BindService服务端,继承自Service并在类中,创建一个实现IBinder接口的实例对象并提供公共方法给客户端使用。
  2. 从onBind()回调方法返回此Binder实例
  3. 在客户端中,从onServiceConnected()回调方法接收Binder,并使用提供的方法调用绑定服务。