Android四大组件学习(二):Service

jkouu 70 0

什么是Service?

Service是一个后台运行(当然也可以设置成前台运行)的组件,执行长时间运行且不需要用户交互的任务。即使应用被销毁也依然可以工作。

这里需要说明的是,Service是后台运行,但是它仍然运行在主线程。如果你要在Service内进行网络操作的话,还是需要另外开一个线程。Service的意义在于,即使应用销毁了,异步任务也可以继续进行。

Service的三种形式

启动

调用startService方法启动一个Service。以这种方式启动的Service会一直执行任务,即使启动它的组件已经被销毁。需要人为通过StopService或stopSelf停止。

绑定

调用bindService方法将一个服务绑定在组件上。这种服务会提供一个接口,允许组件与服务交互。多个组件可以同时绑定服务,当所有绑定的组件销毁后,服务也会被销毁。

启动且绑定

需要同时重写onStartCommand和onBind两个方法。允许服务与组件交互,但组件被销毁后服务不会被销毁,需要人为停止

Service的创建

使用Service之前,需要在Manifest文件中声明服务的类名。

创建一个Service的子类时,一般需要重写下面的几个方法

onStartCommand

当组件通过startService启动一个Service时,系统将调用此方法。一旦调用此方法,需要调用stopService或stopSelf来人为停止这个Service

onBind

当组件通过bindService启动一个Service时,系统将调用此方法。此方法必须返回一个IBinder,为组件与Service交互提供接口

onCreate

创建服务时,系统会调用此函数初始化服务。如果服务已经运行则不会调用此方法。

onDestroy

当Service不再使用且即将被销毁时,系统将调用此方法。

Service简单例子

为了演示Service的三种启动方法,我写了一个简单的demo。没有注释,因为这demo太简单了。

首先是UI布局:

Android四大组件学习(二):Service

就四个按钮,很简单吧?

然后是Service的类:

public class MyService extends Service {
    static class MyBinder extends Binder{
        public void execute(){
            Log.i("tag","信息传递");
        }
    }

    private MyBinder myBinder;
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.i("tag", "绑定服务");
        return myBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.i("tag", "解绑服务");
        return super.onUnbind(intent);
    }

    @Override
    public void onRebind(Intent intent) {
        Log.i("tag", "重绑服务");
        super.onRebind(intent);
    }

    @Override
    public void onCreate() {
        Log.i("tag", "服务创建");
        myBinder = new MyBinder();
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("tag", "服务开始");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.i("tag", "服务销毁");
        super.onDestroy();
    }
}

代码逻辑也很简单,我就是把Service可能会出现的状态用日志输出而已。这里要说明的是我写的MyBinder的内部类。上面说了,在使用绑定服务的时候,服务需要提供一个接口,这个接口用来进行服务与控件的交互。在这里,继承了Binder的MyBinder类就是一个接口。它的execute方法大家可以理解为一个实现业务逻辑的方法,当然大家也可以写很多方法,并不是说只能写一个方法。

然后是Activity的代码:

public class MainActivity extends AppCompatActivity {
    private MyService.MyBinder myBinder;

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

        Button start = findViewById(R.id.start_btn);
        Button end = findViewById(R.id.end_btn);

        start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, MyService.class);
                startService(intent);
            }
        });

        end.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, MyService.class);
                stopService(intent);
            }
        });


        final ServiceConnection serviceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.i("tag", "链接到服务");
                myBinder = (MyService.MyBinder)service;
                myBinder.execute();
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                Log.i("tag", "断开连接");
            }
        };

        Button bind = findViewById(R.id.bind_btn);
        Button unbind = findViewById(R.id.unbind_btn);

        bind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, MyService.class);
                bindService(intent, serviceConnection, BIND_AUTO_CREATE);
            }
        });

        unbind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                unbindService(serviceConnection);
            }
        });
    }
}

代码也很好懂,这里就不再做解释了。大家要好好看这个代码,这就是最基本的管理服务的操作。

看完了代码,我们来看一看实际效果。

启动模式

首先我们看一下启动模式。依次点击开始服务和结束服务,看一看日志中会有什么输出:

Android四大组件学习(二):Service

可以看到这个过程用到了Service的onCreate、onStartCommand和onDestory方法。

然后我们再试一下点击两次开始服务,接着点击结束服务:

Android四大组件学习(二):Service

可以看到,onCreat方法只被调用了一次,这也是意料之中的。

这里再说另外两种不好展示的情况。首先是只点击结束服务,日志没有任何输出;然后是只点击开始服务,然后杀死进程,服务会在进程被杀死后自动调用onDestory方法。

绑定模式

然后我们看一下绑定模式。首先依次点击绑定和解绑:

Android四大组件学习(二):Service

我们看到,点击绑定按钮(即调用bindService方法)后,会依次执行onCreate、onBind、onServiceConnected和execute方法;点击解绑(即调用unbindService方法)后,会依次执行unbind和onDestory方法。

然后我们看一下点击两次绑定后再点解绑:

Android四大组件学习(二):Service

可以看到,第二次点击绑定并没有什么作用,这是因为MainActivity已经绑定在了MyService上。

这里再说两种不好展示的情况。首先是只点击解绑,程序会直接崩溃;然后是只点击绑定接着杀死进程,这种情况下不会调用onDestory和onDestory,可能存在服务没有杀死的情况,因此强烈不建议这种情况发生!

启动绑定模式

这个模式不太好展示,我就直接说一下结果,大家可以自己跑一下demo验证。

首先是先点击绑定。在这种情况下,再点击开始只会执行onStartCommand方法;再点击结束会没有任何效果;再点击解绑会接触绑定并销毁Service。

然后是先点击开始再点击绑定。在这种情况下,再点击结束没有任何效果;再点击解绑只会接触绑定。在点击结束后解绑会解除绑定并销毁Service;在解绑后点击结束会销毁Service。

根据上面的实验结果,我们可以得到Service销毁的条件:当Service既没有启动也没有绑定时,Service才会被销毁。

IntentService

最后再提一下IntentService。IntentService主要是用来解决多线程与Service交互的问题。IntentService包含一个队列,每一次处理时,IntentService只会处理队首的请求。

IntentService默认实现了Service的一系列函数,它不需要我们人为地来销毁。在使用它时,我们只需要重写onHandleIntent方法就可以了。

 

 

发表评论 取消回复
您必须 [登录] 才能发表评论!
分享