前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android四大组件之一Service

Android四大组件之一Service

作者头像
提莫队长
发布2019-03-01 09:47:27
6740
发布2019-03-01 09:47:27
举报
文章被收录于专栏:刘晓杰刘晓杰

Service是能够在后台长期运行并且不提供用户界面的应用程序组件。

Service可以分为以下两种类型:

  1. Started(启动):当Activity通过startService()方法启动服务时,服务处于started状态。一旦启动,就算组件被销毁也不会停止。只有自身调用stopSelf()或者其他组件调用stopService()才停止
  2. Bound(绑定):当Activity通过bindService()方法启动服务时,服务处于bound状态。一个Service可以被多个服务绑定,当它们都解绑时,服务被销毁

Service类中的重要方法

  • onStartCommand():当组件调用startService()时,系统调用该方法。如果开发人员实现该方法,需要调用stopSelf()或stopService()来停止服务
  • onBind():当组件调用bindService()时,系统调用该方法。在该方法的实现中,开发人员必须返回IBinder提供客户端与服务通信的接口,该方法必须实现
  • onCreate():服务第一次创建时调用。在onStartCommand()或onBind()之前
  • onDestory():当服务不再使用时销毁

一、Started Service

1.继承IntentService类

IntentService可以实现如下任务:

  1. 创建区别于主线程的线程来执行发送到onStartCommand()方法的全部Intent
  2. 创建工作队列,每次传递一个Intent到onHandleIntent()
  3. 所有请求处理完毕后停止服务,不必调用stopSelf()
  4. 提供onBind()方法默认实现,返回null
  5. 提供onStartCommand()默认实现,它先发送Intent到工作队列,然后到onHandleIntent()方法实现
代码语言:javascript
复制
public class HelloIntentService extends IntentService {

	public HelloIntentService() {
		super("HelloIntentService");
		// TODO Auto-generated constructor stub
	}

	@Override
	protected void onHandleIntent(Intent arg0) {
		// TODO Auto-generated method stub
		// do something
	}
}

以上就是实现IntentService类所需要的全部操作:无参构造方法和onHandleIntent()方法

如果一定要重写其他回调方法,必须返回默认实现。也就是自动生成的return语句不能改

2.继承Service类

使用IntentService将简化启动服务的实现,但如果要处理多线程,则可以继承Service来处理各个Intent

对于每次启动的请求,它使用工作线程来执行任务,并且每次处理一个请求

代码语言:javascript
复制
public class HelloService extends Service {

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// TODO Auto-generated method stub
		return START_STICKY;
	}
}

onStartCommand()必须返回一个整数。该值用来描述系统停止服务以后如何继续服务。返回值必须是下列值之一:

  1. START_NO_STICKY:停止服务,不再创建服务
  2. START_STICKY:停止服务,重新创建服务并调用onStartCommand(),但是不重新发送最后的Intent。使用空Intent调用onStartCommand()
  3. START_REDELIVER_INTENT:停止服务,重新创建服务并使用最后的Intent调用onStartCommand()

二、Bound Service

绑定服务是允许其他应用进程绑定并且与之交互的Service类实现类。为了提供绑定,开发人员必须实现onBind()回调方法。该方法返回IBinder对象,它定义了客户端与服务的交互接口

在实现绑定服务时,最重要的是定义onBind()回调方法返回的接口

(1)继承Binder类:继承Binder类创建接口,从onBind()返回一个实例。仅用于私有应用程序

(2)使用Messenger:它是执行IPC最简单的方式

(3)使用AIDL:不推荐。会导致更加复杂的实现

1.继承Binder类

如果服务仅用于本地应用程序并且不必跨进程工作,那么可以实现自己的Binder类来为客户端提供访问的方式

实现步骤如下

  • (1)在服务中创建Binder类实例来完成下列操作之一
    1. 包含客户端能调用的公共方法
    2. 返回当前Service实例,其中包含客户端能调用的方法
    3. 返回服务管理的其他类的实例
  • (2)从onBind()回调方法中返回Binder实例
  • (3)在客户端,从onServiceConnected()接受Binder实例,并且使用提供的方法调用绑定服务

下面举个例子来说明:

CurrentTimeService.java

代码语言:javascript
复制
package com.example.bindertime;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.text.format.Time;

public class CurrentTimeService extends Service {
	public class LocalBinder extends Binder {
		CurrentTimeService getService(){		//返回当前Service实例
			return CurrentTimeService.this;
		}
	}

	private final IBinder binder = new LocalBinder();

	@Override
	public IBinder onBind(Intent intent) {			//返回binder实例,自动生成的
		// TODO Auto-generated method stub
		return binder;
	}

	public String getCurrentTime(){
		Time time = new Time();
		time.setToNow();
		String currentTime = time.format("%Y-%m-%d %H:%M:%S");
		return currentTime;
	}
}

CurrentTimeActivity.java

代码语言:javascript
复制
调用bindService()方法,传递ServiceConnection实现
代码语言:javascript
复制
package com.example.bindertime;

import com.example.bindertime.CurrentTimeService.LocalBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class CurrentTimeActivity extends Activity {
	CurrentTimeService cts;
	boolean bound;

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

	@Override
	protected void onStart() {
		// TODO Auto-generated method stub
		super.onStart();
		Button button = (Button)findViewById(R.id.current);
		button.setOnClickListener(new OnClickListener(){
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Intent intent = new Intent(CurrentTimeActivity.this, CurrentTimeService.class);
				bindService(intent, sc, BIND_AUTO_CREATE);		//调用bindService()方法,传递ServiceConnection实现
				if(bound){
					Toast.makeText(CurrentTimeActivity.this, cts.getCurrentTime(), 
							Toast.LENGTH_SHORT).show();
				}
			}
		});
	}

	@Override
	protected void onStop() {
		// TODO Auto-generated method stub
		super.onStop();
		if(bound){
			bound = false;
			unbindService(sc);
		}
	}
	//实现ServiceConnection,这需要重写onServiceConnected()和onServiceDisconnected()两个回调函数
	private ServiceConnection sc = new ServiceConnection(){
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {		//接受Binder实例
			// TODO Auto-generated method stub
			LocalBinder binder = (LocalBinder)service;
			cts = binder.getService();
			bound = true;
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			// TODO Auto-generated method stub
			bound = false;
		}	
	};
}

2.使用Messenger类

如果需要和远程进程通信,可以使用Messenger来为服务提供接口。

使用Messenger要注意:

  1. 实现Handler的服务因为每次从客户端调用而收到回调
  2. Handler用于创建Messenger对象
  3. Messenger创建IBinder,服务从onBind()方法返回到客户端
  4. 客户端使用IBinder来实例化Messenger,然后使用它来发送Message对象到服务
  5. 服务在Handler的handleMessage()方法接受message

CurrentTimeService.java

代码语言:javascript
复制
package com.example.messengertime;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.text.format.Time;
import android.widget.Toast;

public class CurrentTimeService extends Service {
	public class IncomingHandler extends Handler {
		@Override
		public void handleMessage(Message msg) {	//服务在Handler的handleMessage()方法接受message
			// TODO Auto-generated method stub
			if(msg.what == CURRENT_TIME){
				Time time = new Time();
				time.setToNow();
				String currentTime = time.format("%Y-%m-%d %H:%M:%S");
				Toast.makeText(CurrentTimeService.this, currentTime, Toast.LENGTH_SHORT).show();
			}else{
				super.handleMessage(msg);
			}
		}
	}

	public static final int CURRENT_TIME = 0;

	@Override //Messenger创建IBinder,服务从onBind()方法返回到客户端
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		Messenger messenger = new Messenger(new IncomingHandler());//Handler用于创建Messenger对象
		return messenger.getBinder();
	}
}

CurrentTimeActivity.java

代码语言:javascript
复制
package com.example.messengertime;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.view.View;
import android.widget.Button;

public class CurrentTimeActivity extends Activity {
	Messenger messenger;
	boolean bound;

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

	@Override
	protected void onStart() {
		// TODO Auto-generated method stub
		super.onStart();
		
		Button button = (Button)findViewById(R.id.current);
		button.setOnClickListener(new View.OnClickListener(){
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Intent intent = new Intent(CurrentTimeActivity.this, CurrentTimeService.class);
				bindService(intent, connection, BIND_AUTO_CREATE);
				if(bound){
					Message message = Message.obtain(null, CurrentTimeService.CURRENT_TIME, 0, 0);
					try {
						messenger.send(message);
					} catch (RemoteException e) {
						e.printStackTrace();
					}
				}
			}
		});
	}

	@Override
	protected void onStop() {
		// TODO Auto-generated method stub
		super.onStop();
		if(bound){
			bound = false;
			unbindService(connection);
		}
	}
	
	private ServiceConnection connection = new ServiceConnection(){
		@Override //客户端使用IBinder来实例化Messenger,然后使用它来发送Message对象到服务
		public void onServiceConnected(ComponentName name, IBinder service) {
			// TODO Auto-generated method stub
			messenger = new Messenger(service);
			bound = true;
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			// TODO Auto-generated method stub
			messenger = null;
			bound = false;
		}
	};
}

3.绑定到服务

如果需要从客户端绑定服务,需要完成如下操作:

  1. 实现ServiceConnection,这需要重写onServiceConnected()和onServiceDisconnected()两个回调函数
  2. 调用bindService()方法,传递ServiceConnection实现
  3. 当系统调用ServiceConnection时,可以使用接口定义的方法回调服务
  4. 调用unbindService()方法解除绑定

三、Service生命周期

可参考这篇文章:service生命周期

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015年12月19日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Service类中的重要方法
  • 一、Started Service
    • 1.继承IntentService类
      • 2.继承Service类
      • 二、Bound Service
        • 1.继承Binder类
          • CurrentTimeService.java
          • CurrentTimeActivity.java
        • 2.使用Messenger类
          • CurrentTimeService.java
          • CurrentTimeActivity.java
        • 3.绑定到服务
        • 三、Service生命周期
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档