四大组件之Service初步

作为四大组件之一,所处重要地位可想而知。但是它并不像Activity那样可以所见,而是在后台默默的为应用程序服务着。那么到底什么是Service呢?


上面的官方文档说的很清楚了,Service不是一个线程,是主程序的一部分,需要调用Context.startService()来启动它,如果退出应用时,Service进程并没有结束,它仍然在后台行。比如我们在执行下载应用的时候,有可能去看新闻,正是有了Service,我们可以切换到新闻客户端来阅读新闻,而下载任务在后台被Service所执行。

Service生命周期,看下官网上的表述:


上面说Service有两种启动方式,分别是Context.startService(),Context.bindService()。下面简单的介绍这两种启动过程:

Context.startService():onCreate() => onStartCommand() => Context.stopService() || stopSelf() => onDestroy()

Context.bindService():onCreate() => onBind() => onUnbind() => onDestroy()

注意:

通过Context.startService()方式启动后,访问者与Service之间没有关联,即使访问者退出了,Service也仍然运行。

通过Context.bindService()方式启动后,访问者与Service绑定在一起,访问者一旦退出,Service就终止了。

这里分享一个小技巧,因为网络原因,我们查看android sdk下的文档时,非常慢(我用的是Chrome 49.0.26XXX),当然如果翻墙或者用VPN也可以,但是这都需要在有网下访问。由于我们在查看文档时,需要访问网络造成的,所以导致非常卡顿(断网情况下也是非常慢)。我们可以用Firefox浏览器打开文档,然后选择"开发者"工具中的"脱机工作",可以完美秒开文档。

下面通过demo简单的介绍Service用法。布局文件很简单:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.example.service.MainActivity"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button 
        android:id="@+id/createService"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="启动服务"
        />
    <Button
        android:id="@+id/stopService"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:text="停止服务" />
    <Button
        android:id="@+id/bindService"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:text="绑定服务" />
    <Button
        android:id="@+id/ubindService"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:text="解除绑定服务" />
    <Button 
        android:id="@+id/status"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="T的状态信息"
        />
</LinearLayout>
需要有一个我们自己的Service类:

public class MyService extends Service {
    
    private boolean bool = true;
    private int T;
    private MyBind mbind = new MyBind();
    
	public class MyBind extends Binder{   //实现具体业务逻辑
		public int getT(){
		 Log.d("MyBind","Mybind");
		 //实现具体的逻辑
		 return T;
		}
	}
	@Override
	public IBinder onBind(Intent intent) {   //返回IBinder对象
		// TODO 自动生成的方法存根
		return mbind;
	}
	
	public boolean onUnbind(Intent intent){  //解除绑定的时候回调
		Log.d("onUnbind","onUnbind");
		return true;
	}
	public void onCreate(){ //Service第一次被创建时回调。多次启动已有的Service组件时,将直接回调onStartCommand(),而不会再次回调onCreate()
		super.onCreate();
		Log.d("onCreate","onCreate()");
		new Thread(new Runnable() {			
			@Override
			public void run() {
				// TODO 自动生成的方法存根		
				while(bool){
					try {
						Thread.sleep(6000);
					} catch (InterruptedException e) {
						// TODO 自动生成的 catch 块
						e.printStackTrace();
					}
					T = new Random().nextInt(1000);
				}
			}
		}).start();
	}
	
     public int onStartCommand(Intent intent,int flags,int startId){  //客户端每次调用startService()启动该Service时回调此方法
		Log.d("onStartCommand","onStartCommand");
		return super.onStartCommand(intent, flags, startId);
		
	}
	
	public void onDestroy(){  //Service关闭时回调该方法
		super.onDestroy();
		Log.d("onDestory","onDestory()");
	}

}
MainActivity:

public class MainActivity extends Activity implements OnClickListener{
    
	private Button startButton;
	private Button stopButton;
	private Button bindService;
	private Button ubindService;
	private Button status;
	private MyService.MyBind mbind;
	ServiceConnection conn = new ServiceConnection() {
		
		@Override
		public void onServiceDisconnected(ComponentName name) {
			// TODO 自动生成的方法存根
			
		}
		
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			// TODO 自动生成的方法存根
			mbind = (MyService.MyBind)service;
		}
	};
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		startButton = (Button)findViewById(R.id.createService);
		stopButton = (Button)findViewById(R.id.stopService);
		bindService = (Button)findViewById(R.id.bindService);
		status = (Button)findViewById(R.id.status);
		ubindService = (Button)findViewById(R.id.ubindService);
		
		startButton.setOnClickListener(this);
		stopButton.setOnClickListener(this);
		bindService.setOnClickListener(this);
		ubindService.setOnClickListener(this);
		status.setOnClickListener(this);
	}

	@SuppressLint("ShowToast")
	@Override
	public void onClick(View v) {
		// TODO 自动生成的方法存根
		switch (v.getId()) {
		case R.id.createService:  //通过Context.startService()启动服务
			Intent intentstart = new Intent(MainActivity.this,MyService.class);
			startService(intentstart);
			break;

		case R.id.stopService:   //停止服务
			Intent intentstop = new Intent(MainActivity.this,MyService.class);
			stopService(intentstop);
			break;
		case R.id.bindService:   //绑定服务
			Intent bindintent = new Intent(MainActivity.this,MyService.class);
			bindService(bindintent, conn, 0); //如果指定flags为0时,若想启动服务,则必须通过<span style="font-family: Arial, Helvetica, sans-serif;">Context.startService()启动</span>
  			break;
		case R.id.ubindService:  //取消绑定
			unbindService(conn);
			break;
		case R.id.status:
			Toast.makeText(MainActivity.this,"T的值为:"+mbind.getT(),Toast.LENGTH_SHORT).show();
	    default:
	    	break;
		}
	}
}

四大组件都需要在AndroidManifest.xml中注册:

    <application
        ... >
        ...
        ...
        <service
            android:name="com.example.service.MyService">
        </service>
        ...
        ...
    </application>
运行程序:(就不通过日志分析,通过查看正在运行的Service比较直接)



那么如何把Activity与Service绑定呢?

需要用到public abstract booleanbindService(Intent service,ServiceConnection conn, int flags):

分析上面三个参数的含义(详细可以查看API)

service:通过Intent指定要启动的Service

conn:该参数是一个ServiceConnection对象,用于监听访问者与Service之间的连接情况。当访问者与Service成功连接时,回调该对象的onServiceConnected(ComponentName name, IBinder service)方法;当Service与访问者之间断开连接时回调该对象的onServiceDisconnected(ComponentName name)方法。

flags:指定绑定时是否自动创建Service(当Service还未创建),该参数可以是0(不自动创建)或BIND_AUTO_CREATE(自动创建),该参数可以自己模拟。由于上面绑定服务时,指定flags为0,所以若想点击"T的状态信息"按钮时,必须先点击"启动服务"按钮。

下面看下效果:


MyService中,设置T为随机数,MyBind类中的getT()用于返回T,onBind()返回IBinder对象,当访问者与Service成功连接时,onServiceConnected(ComponentName name, IBinder service)方法中会获得onBind()中返回的IBinder对象,然后调用MyBind类中的getT()方法,获得T,这就是上面的简单实现。由于本人水平有限,上面有误,请指正,不甚感激!

 总结:

1.Service需要在AndroidManifest.xml注册才可以生效

2.IBinder是访问者与Service之间信息交流的信使

3.Service两种启动方式以及不同点


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值