您的位置:首页 > 移动开发 > Android开发

Android四大组件之Service服务学习笔记(一)

2016-08-31 20:03 746 查看

Android四大组件之Service服务学习笔记(一)

  Service是安卓四大组件之一,服务是用在后台处理事情的,并且是不可见的,该服务不是我们所说的服务器的服务,他经常用来处理一些循环操作,但是它不同于子线程,服务是运行在主线程中的。

  服务一般分为本地服务和远程服务,这里先介绍本地服务。

  本地服务通常用两种启动方式

  1. 直接启动模式

    我们可以通过startService(Intent intent)方式去直接启动一个服务,对于intent意图,我们也可以用两种形式

  创建,一种是显示启动,一种是隐示启动,但是需要注意的是,在android5.0以后,所有的服务尽量通过显示

  意图来启动。否则就直接程序崩溃。所以建议都使用显示方式启动服务。如果一定要使用隐示启动方式, 则在对应的intent中添加一句
intent.setPackage(对应服务所在的包名)
,通过这个方法,可以防止5.0后隐示启动发生崩溃的作用。下面通过代码来详细讲解下。 

MainActivity.java

public class MainActivity extends AppCompatActivity {

private Intent intent;

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

}
public void onClick(View view){
intent = new Intent(this,MyService.class);
//intent.setPackage("cn.itrealman.servicedemo");5.0以后需要加上这句代码
switch (view.getId()) {
case R.id.start:
//启动服务
startService(intent);
break;
case R.id.stop:
//停止服务
stopService(intent);
break;        }
}
}


在AndroidManifest.xml中配置Service

<service
android:name=".MyService"
android:enabled="true"
android:exported="true">
<!--<intent-filter>-->
<!--建议不用写,因为5.0后的系统不支持隐示启动-->
<!--<action android:name="test.service" />-->
<!--</intent-filter>-->
</service>


MyService.java

public class MyService extends Service {
public MyService() {
Log.d("IT_Real", "MyService: 构造方法");
}

/**
* 这个方法是通过绑定的方式才会调用该方法
* @param intent
* @return
*/
@Override
public IBinder onBind(Intent intent) {
Log.d("IT_Real", "onBind: ");
return null;
}

/**
* 服务启动后初始化内部数据的方法,只会在第一次启动该服务的时候调用一次
*/
@Override
public void onCreate() {
Log.d("IT_Real", "onCreate: ");
super.onCreate();
}

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

@Override
public boolean onUnbind(Intent intent) {
Log.d("IT_Real", "onUnbind: ");
return super.onUnbind(intent);
}

/**
* 这个方法是直接启动服务时调用的方法,不过该方法已经过时了
* 被下面的onStartCommand方法代替了
* @param intent
* @param startId
*/
@Override
public void onStart(Intent intent, int startId) {
Log.d("IT_Real", "onStart: ");
super.onStart(intent, startId);
}

/**
* 这个方法也是直接启动服务时调用的方法
* @param intent
* @param flags
* @param startId
* @return
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("IT_Real", "onStartCommand: ");
return super.onStartCommand(intent, flags, startId);
}

}


在上面的代码中,当我们点击启动按钮时,相应的服务被启动,在此之前,我们先看一下直接启动方式服务的生命周期图:

                   


在上面的图中,我可以了解到,当我们第一次启动服务时,会先调用onCreate()——>onStartCommand()——onStart(),然后服务会开始运行,直到调用stopService()方法才会停止服务,然后会调用相应的onDestory()方法,如果服务已经启动,我们多次点击启动服务按钮,则会多次掉用onStartCommand()——>onStart()方法

对于上面的这种方式,我们不会获取任何服务对象,也不能操作任何服务里面的数据,都是系统自己去操作的,加入说,我们的服务里面有一个doSth()方法,我想去调用这个方法做该事情,那么该怎么调用呢?这个时候,我们就只能去通过在onStartCommand()方法里面去调用了(在onStart()方法中也可以调用,但是不推荐这样使用,过时的方法我能不用就不用),代码如下:

/**
* 这个方法也是直接启动服务时调用的方法
* @param intent
* @param flags
* @param startId
* @return
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("IT_Real", "onStartCommand: ");
//通过调用该方法
doSth();
return super.onStartCommand(intent, flags, startId);
}
private void doSth(){
Log.d("IT_Real", "doSth: 我正在做某事...");
}


这样我们就能完成需要操作的事情了,但是这样的操作往往会很不方便,不能很好的让用户去通过某种方式去操作,比如在播放音乐的时候,我们就会很难去控制服务去处理某些事情,所以一般我们会通过绑定的方式来启动服务。

  2. 绑定启动模式

  对于绑定启动服务,我们可以很好的获取到服务给我们返回的Ibinder对象,由于Ibinder是一个接口,通常我们会返回一个Ibinder的子类Binder对象。一般情况下,我们会去继承Binder对象,添加自己所需要的实现功能。绑定启动的方式是通过bindService(Intent intent, ServiceConnection conn, int flags)绑定服务,该方法的三个参数如下:

  intent:通过Intent指定要启动的服务

  conn:该参数是一个ServiceConnection对象,该对象用于监听访问者与service之间的连接情况。当访问者与Service直接连接成功时将回调ServiceConnection对象的onServiceConnected(ComponentName name, IBinder service)方法,当Service所在的宿主进程由于异常中断或者其他原因终止,导致该Service与访问者之间断开连接时,会调用ServiceConnection对象的onServiceDisconnected(ComponentName name)方法。

  flags:指定绑定时,是否通过自动创建Service(未创建的情况下),如果该参数指定0(不创建),或者写BIND_AUTO_CREATE(自动创建)

  创建代码如下:

MainActivity.java

public class MainActivity extends AppCompatActivity {

private Intent intent;
private MyServiceConnection conn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
conn = new MyServiceConnection();

}
public void onClick(View view){
intent = new Intent(this,MyService.class);
switch (view.getId()) {
case R.id.bindStart:
bindService(intent,conn,BIND_AUTO_CREATE);
break;
case R.id.bindStop:
unbindService(conn);
break;        }
}

/**
* ServiceConnection类,通过该类中的onServiceConnected方法
* 中的IBinder service对象可以获取到绑定的服务对象中的MyBinder对象
* 然后可以通过MyBinder对象中的getBindService方法获取我们的
* MyBindService对象
*/
class MyServiceConnection implements ServiceConnection {

@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//获取Binder对象
MyBindService.MyBinder service1 = (MyBindService.MyBinder) service;
MyBindService service2 = service1.getBindService();
}

@Override
public void onServiceDisconnected(ComponentName name) {

}
}
}


在AndroidManifest.xml中配置Service

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


MyBindService.java

public class MyBindService extends Service {
public MyBindService() {
}

/**
* 返回的IBinder对象
*/
class MyBinder extends Binder{
public MyBindService getBindService(){
returnMyBindService.this;
}
}

@Override
public void onCreate() {
Log.d("IT_Real", "onCreate: ");
super.onCreate();
}

/**
* 绑定服务时调用该方法
* @param intent
* @return
*/
@Override
public IBinder onBind(Intent intent) {
Log.d("IT_Real", "onBind: ");
return new MyBinder();
}

@Override
public boolean onUnbind(Intent intent) {
Log.d("IT_Real", "onUnbind: ");
return super.onUnbind(intent);
}

@Override
public void onDestroy() {
Log.d("IT_Real", "onDestroy: ");
super.onDestroy();
}
}


这样我们就可以获取绑定服务对象了。然后我们看一下下面的生命周期图

                 


通过绑定服务我们可以看出该生命周期。当调用了bindService方法时,生命周期为onCreate()——>onBind()——>服务运行,当调用unbindService()方法时,服务被关闭,执行onUnbind()——>onDestroy()

通过绑定服务,我们可以获取到对应的服务对象,如果说要实现某些操作,在服务里面定义对应的该操作,然后通过服务对象可以去调用该方法。我们去调用一个播放、暂停、上一首、下一首等。代码如下

MainActivity.java

public class MainActivity extends AppCompatActivity {

private Intent intent;
private MyServiceConnection conn;
private MyBindService service2;

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

}
public void onClick(View view){
intent = new Intent(this,MyBindService.class);
switch (view.getId()) {
case R.id.bindStart:
bindService(intent,conn,BIND_AUTO_CREATE);
break;
case R.id.bindStop:
unbindService(conn);
break;
case R.id.startMusic:
//播放
service2.start();
break;
case R.id.pause:
//暂停
service2.pause();
break;
case R.id.previous:
//上一首
service2.previous();
break;
case R.id.next:
//下一首
service2.next();
break;

}
}

/**
* ServiceConnection类,通过该类中的onServiceConnected方法
* 中的IBinder service对象可以获取到绑定的服务对象中的MyBinder对象
* 然后可以通过MyBinder对象中的getBindService方法获取我们的
* MyBindService对象
*/
class MyServiceConnection implements ServiceConnection {

@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//获取Binder对象
MyBindService.MyBinder service1 = (MyBindService.MyBinder) service;
service2 = service1.getBindService();
}

@Override
public void onServiceDisconnected(ComponentName name) {

}
}
}


MyBindService.java

public class MyBindService extends Service {
public MyBindService() {
}

/**
* 返回的IBinder对象
*/
class MyBinder extends Binder{
public MyBindService getBindService(){
return MyBindService.this;
}
}

/**
* 服务被创建时调用该方法
*/
@Override
public void onCreate() {
Log.d("IT_Real", "onCreate: ");
super.onCreate();
}

/**
* 绑定服务时调用该方法
* @param intent
* @return
*/
@Override
public IBinder onBind(Intent intent) {
Log.d("IT_Real", "onBind: ");
return new MyBinder();
}

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

/**
* 当调用了unbindService方法是,调用该方法
* @param intent
* @return
*/
@Override
public boolean onUnbind(Intent intent) {
Log.d("IT_Real", "onUnbind: ");
return super.onUnbind(intent);
}

/**
* 被关闭之前调用该方法
*/
@Override
public void onDestroy() {
Log.d("IT_Real", "onDestroy: ");
super.onDestroy();
}

public void start(){
Log.d("IT_Real", "start: 播放");
}
public void pause(){
Log.d("IT_Real", "pause: 暂停");
}
public void next(){
Log.d("IT_Real", "next: 下一首");
}
public void previous(){
Log.d("IT_Real", "previous: 上一首");
}
}


这样就可以很好的操作服务里面的方法了。对于绑定服务,有一个地方需要注意,那就是,我们在启动服务后,如果退出了当前activity,或者结束该进程的时候,没有调用unbindService()方法,程序会报一个

Activity cn.itrealman.servicedemo.MainActivity has leaked ServiceConnectioncn.itrealman.service

demo.MainActivity$MyServiceConnection@6c1837b that was originally bound here
异常

这个异常表示连接已经绑定,我们没有解绑,会导致泄露问题。所以,一般我们建议在销毁Activity时,我们需要在Activity的onDestroy()方法中添加如下代码:

@Override
protected void onDestroy() {
unbindService(conn);
super.onDestroy();
}


或者说,我们在关闭Activity之前,自己手动调用解绑方法。这样就能保证我们的程序不出错。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: