Service基础|青训营笔记

66 阅读3分钟

这是我参与「第四届青训营」笔记创作活动的的第3天

Service组件是什么

相当一个没有界面的Activity,在后台运行的程序,并且可以与其他组件进行交互。

  • 与Activity相比同样可以开辟线程、数据存储和访问网络等
  • 可以在后台处理耗时操作(文件下载、音乐播放等)
  • 不受Activity生命周期的影响(Activity销毁了Service仍可以运行)

Service的创建

  • 类似Activity,创建Service类
public class MyService extends Service {
    public static final String TAG = "TAG";

    public MyService() {
    }

    @Override
    public void onBind() {
        super.onCreate();
    }
 }
  • AndroidManifest.xml配置组件注册
<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <service
        android:name=".MyService"
        android:enabled="true"
        android:exported="true"></service>
 </application>

Service生命周期

两种状态

  • 启动服务 流程图

image.png

注意点: 当服务已经被创建并激活启动后,继续startService()该服务则不会调用onCreate(),而会调用onStartCommand(),除非stopService()停止后再startService()服务,才会重新onCreate()。 简单实现Activity中启动Service

public class ServiceCode_Activity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_service_code_);

    }
//          按钮事件处理
    public void handleService(View v){
        switch(v.getId()){
            case R.id.startSerivce:{ 
                Intent t1 = new Intent(this, MyService.class);   //连接当前Activity与指定服务

                startService(t1);   //启动服务

            };break;
            case R.id.stopSerivce:{
                Intent t2 = new Intent(this,MyService.class);   //与上面指向的时同一个服务

                stopService(t2);  //停止服务 虽然Intent对象不同但是指向的时同一个服务,所以停止同一个服务
            };break;
     }
  • 绑定服务 流程图

image.png

注意点: 只绑定服务,则服务的生命周期会随着activity销毁而结束,绑定并启动服务存在两种情况

  • 绑定服务前没有启动服务:bindService()时会调用onCreate()—>onBind(),但是后台不会启动运行服务,此时,如果要启动服务则需要startService()后调用onStartCommand(),服务运行,unbindService()解绑服务时只会unBind(),服务不会被销毁,只能stopService()或系统停止(并非退出app)服务才会被销毁,并且只能unbindService()解绑后才能stopService()停止服务;如果不启动服务,unbindService()解绑服务或退出Activity时会unBind()—>onDestory();
  • 绑定服务前服务已经启动:startServicce()调用onCrete()->onStartCommand(),bindService()只会调用onBind(),unbindService()解绑服务时只会unBind(),服务不会被销毁,stopService()或系统停止 服务才会被销毁;

简单实现Activity绑定Service

public class ServiceCode_Activity extends AppCompatActivity {
    ServiceConnection conn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_service_code_);

        conn = new ServiceConnection() {  //该类对象用于客户端与服务进行关联
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {

            }

            @Override
            public void onServiceDisconnected(ComponentName name) {

            }
        };
    }
//          按钮事件处理
    public void handleService(View v){
        switch(v.getId()){
            case R.id.bindSerivce:{
                Intent t3 = new Intent(this,MyService.class);
//                绑定服务
                bindService(t3,conn,BIND_AUTO_CREATE);
            };break;
            case R.id.unbindSerivce:{
//                解绑服务
                unbindService(conn);
            };
        }
    }
}

简单实现获取后台进度

IBinder 接口的实现

可以发现Service生命周期中onBind()方法返回值是一个IBinder对象,而这个IBinder作用是Android实现远程操作的基本接口,而这里我们返回IBinder对象用于将Service中数据暴露出去。

Binder类

Binder类是IBinder接口的实现类,因为IBinder接口中只有一些定义抽象的方法,而onBind()返回一个IBinder接口需要实现里面的方法,而正常情况下我们是不需要这些方法的,Binder类已经空实现了IBInder接口中的方法,我们只需要返回一个自定义Binder子类,写入暴露的数据即可。

image.png

image.png

ServiceConnection类

可以观察到bindService()绑定服务是,用到的其中一个参数就是ServiceConnection对象,该类用于客户端与服务之间的连接,因为绑定运行的服务时,onBind()和onUnbind()只会调用一次,解绑后再次bindService()和unbindService()则表示客户端与服务建立连接和连接丢失,则不会再调用onBind()和onUnbind(),而是继续回调ServiceConnection类中的onServiceConnected()和onServiceConnected()。

image.png

image.png