4、Service基础-Android强化课程笔记

1、简介

  • Service是Android的四大组件之一;
  • 可以当做没有界面的Activity来处理,其与Service有很多相似之处,很多在Activity中能做的事情,在Service中也可以:开辟线程、访问网络、操作数据库等等;
  • Service也有完整的生命周期,其生命周期不受Activity的影响;
  • Service主要用于在后台处理耗时操作,比如下载、音乐播放等都可以在后台进行
  • 不能在Service中做的事情有:布局设置,根据需求给控件添加事件等等;

补充:Android5.0之后Service的Intent一定要显式声明:

Intent intent=new Intent();
intent.setAction("com.demo.myservice");
intent.setPackage("com.example.servicedemo");
startService(intent);

2、Service的生命周期

如图所示为Service的两种生命周期(图片来源):
这里写图片描述

3、两种服务的简单使用

3.1、启动服务

1.新建一个名为Service的项目,按下图所示编写其xml布局文件(这里为线性布局,并展示一个按钮的写法,其余按钮自行完成):
这里写图片描述
按钮的代码为:

    <Button
        android:id="@+id/start"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="operate"
        android:text="启动服务" />

2.新建一个Service,名字默认即可(默认为MyService),代码如下:

public class MyService extends Service {
    private static final String TAG = "MyService-service";

    public MyService() {
    }

    //创建
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "服务被创建了");
    }

    //启动
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "服务被启动了");
        return super.onStartCommand(intent, flags, startId);
    }

    //绑定
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "服务绑定了");
        return null;
    }

    //解绑
    @Override
    public boolean onUnbind(Intent intent) {
        Log.d(TAG, "服务解绑了");
        return super.onUnbind(intent);
    }

    //销毁
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "服务销毁了");
    }
}

3.在MainActivity的添加operate方法,代码如下所示:

注:在开启和关闭服务的代码中,我们都创建了Intent对象,但是其操作的却是同一个Serice。

public void operate(View view) {
        switch (view.getId()) {
            case R.id.start:
                startService(new Intent(this, MyService.class));
                break;
            case R.id.stop:
                stopService(new Intent(this, MyService.class));
                break;
        }
    }

4.运行代码,打开设置界面,查看正在运行的服务,然后点击启动服务,查看正在运行的服务,最后电器停止服务,再次查看正在运行的服务,如下图所示:
这里写图片描述
日志打印结果:
这里写图片描述

以上演示的为一幅图的生命周期,Service依次经历了startService→onCreate→onStartCommand→Service Running→onDestroy
5.再次运行代码,这次点击启动服务,然后再次点击启动服务。日志打印结果如下所示,再次启动服务,仅仅是启动服务了而并没有再次创建服务,除非你先销毁这个服务。
这里写图片描述
6.此时,我们按返回键关闭窗口,并单击菜单键,将后台清理,再次打开设置里面正在运行的服务,发现服务仍在运行。这边说明服务不收Activity生命周期的影响。

3.2、绑定服务

1.在MainActivity的添加全局的ServiceConnection对象。

private ServiceConnection serviceConnection=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {

        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

2.并且在operate方法中添加剩余两个按钮的单击事件。

    case R.id.bind:
        Intent intent = new Intent(this, MyService.class);
        bindService(intent, serviceConnection, BIND_AUTO_CREATE);
        break;
    case R.id.unbind:
        unbindService(serviceConnection);
        break;

3.运行程序,分别单击绑定服务和解绑服务两个按钮,日志打印结果如下所示,这就印证了第二张图的生命周期(上面代码中绑定服务的第三个参数BIND_AUTO_CREATE表明,在绑定服务的时候若服务不存在,则自动创建一个服务,若已存在,则直接绑定即可)。
这里写图片描述
4.这里需要注意的是,绑定服务,只是创建并绑定了服务,并没有启动服务。
5.运行程序,然后单击绑定服务按钮,然后按返回键退出应用,此时日志打印结果如下,随着退出应用服务也随之解绑并销毁。
这里写图片描述
6.运行程序,依次点击启动服务→绑定服务→解绑服务,此时发现解绑服务并没有销毁服务,日志打印如下所示:
这里写图片描述
7.紧接着上面的操作,点击停止服务,发现服务此时才被销毁。这就是说如果你对服务进行了启动操作,只有停止服务才能完成服务的销毁。
8.若点击绑定服务后点击停止服务,此时发现,此时并不能解绑并销毁服务,只有通过解绑服务才能解绑并销毁服务。

综上所述,启动服务与停止服务,绑定服务和解绑服务是一一对应关系,俗话说解铃还须系铃人。唯一的例外就是绑定服务后若没有启动服务,则服务并不会运行,此时按返回键也可解绑并销毁服务。

4、绑定操作的意义

绑定服务主要作用是用来实现对Service执行的任务进行进度监控

4.1实现IBinder接口

绑定服务除了要用到ServiceConnection,还要用到IBinder这个接口,并且看代码,IBinder正好是ServiceConnectiononServiceConnected方法的参数,而且也时ServiceonBind方法的返回值。这个返回值正好传递给onServiceConnected方法的参数。
IBinder:在Android中用于远程操作对象的一个接口。
对于onBind方法而言,要求返回IBinder对象,但是IBinder接口实现的方法很多,此时把问题复杂化了。实际上,我们会自定义一个内部类,让其继承自Binder类(Binder类实现了IBinder接口),然后就可以定义自己需要的方法了(这里我们仅仅想实现进度监控)。

修改MyService中代码(仅写有变化的部分代码)。

    private int i;

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "服务被创建了");
        //开启一个线程,用于模拟耗时任务
        new Thread() {
            @Override
            public void run() {
                super.run();
                for (i = 0; i < 30; i++) {
                    try {
                        //休眠
                        sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "服务绑定了");
        return new MyBinder();
    }

    class MyBinder extends Binder {
        //定义自己需要的方法
        public int getProcess() {
            return i;
        }
    }

4.2完成ServiceConnection的操作

bindServiceunbindService方法的参数中都用到ServiceConnection对象。
ServiceConnection是用于绑定客户端和服务的。

MainActivity中修改创建ServiceConnection对象的代码为:

private ServiceConnection serviceConnection = new ServiceConnection() {
        //当客户端与服务正常连接时,执行服务的绑定此方法会被调用
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            MyService.MyBinder myBinder = (MyService.MyBinder) service;
            Log.d(TAG, "onServiceConnected,此时操作进度为: " + myBinder.getProcess() + "%");
        }

        //当客户端与服务的连接丢失了,此方法会被调用
        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

运行程序,首先点击启动服务,然后交替点击绑定服务和解绑服务按钮,查看日志打印结果,这样便实现了进度的监控。
这里写图片描述

猜你喜欢

转载自blog.csdn.net/chaixingsi/article/details/81209723