Android中 service组件详解
service组件跟activity组件及其类似,可以说service是没有界面的activity,
当然service的生命周期和activity还是有一定的差别的。
service组件一般用在什么地方的,上面讲了service组件没有界面,不用跟用户直接交互,
所以service组件一般运行在后台。比如做一些不需要界面的数据处理等等。
开发service需要两个步骤:
1,定义一个基础service的子类。
2,在AndroidManifest.xml文件中配置该service。
怎么启动service呢,想想启动activity是不是有两种方法:
startActivity(intent),
startActivityForResult(intent)
那么启动service也有两种方法:
startService(intent),
bindService(Intentservice,ServiceConnectionconn,intflags),
两者有什么区别可以先看下面的代码:
publicclassBindServiceextendsService
{
privateintcount;
privatebooleanquit;
//定义onBinder方法所返回的对象
privateMyBinderbinder=newMyBinder();
//通过继承Binder来实现IBinder类
publicclassMyBinderextendsBinder
{
publicintgetCount()
{
//获取Service的运行状态:count
returncount;
}
}
//必须实现的方法
@Override
publicIBinderonBind(Intentintent)
{
System.out.println("ServiceisBinded");
//返回IBinder对象
returnbinder;
}
//Service被创建时回调该方法。
@Override
publicvoidonCreate()
{
super.onCreate();
System.out.println("ServiceisCreated");
//启动一条线程、动态地修改count状态值
newThread()
{
@Override
publicvoidrun()
{
while(!quit)
{
try
{
Thread.sleep(1000);
}
catch(InterruptedExceptione)
{
}
count++;
}
}
}.start();
}
//Service被断开连接时回调该方法
@Override
publicbooleanonUnbind(Intentintent)
{
System.out.println("ServiceisUnbinded");
returntrue;
}
//Service被关闭之前回调。
@Override
publicvoidonDestroy()
{
super.onDestroy();
this.quit=true;
System.out.println("ServiceisDestroyed");
}
@Override
publicvoidonRebind(Intentintent)
{
super.onRebind(intent);
this.quit=true;
System.out.println("ServiceisReBinded");
}
}
上面的Service的作用是简单的开启一个线程,每1秒钟count++,这个count数据
通过binder对象传递给访问者。
待会再做详解,先看下面的代码怎么启动Service,并得到Service的count数据
publicclassMainActivityextendsActivity
{
ButtonstartService_bnt,bindService_bnt;
//保持所启动的Service的IBinder对象
BindService.MyBinderbinder;
@Override
publicvoidonCreate(BundlesavedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startService_bnt=(Button)findViewById(R.id.start_bnt);
bindService_bnt=(Button)findViewById(R.id.bind_bnt);
//创建启动Service的Intent
Intentintent=newIntent(this,BindService.class);
startService_bnt.setOnClickListener(newOnClickListener()
{
@Override
publicvoidonClick(Viewsource)
{
//绑定指定Serivce
startService(intent);
}
});
bindService_bnt.setOnClickListener(newOnClickListener()
{
@Override
publicvoidonClick(Viewsource)
{
//绑定指定Serivce
bindService(intent,conn,Service.BIND_AUTO_CREATE);
Toast.makeText(MainActivity.this
,"Serivce的count值为:"+binder.getCount()
,4000)
.show();
}
});
}
//定义一个ServiceConnection对象
privateServiceConnectionconn=newServiceConnection()
{
//当该Activity与Service连接成功时回调该方法
@Override
publicvoidonServiceConnected(ComponentNamename
,IBinderservice)
{
System.out.println("--ServiceConnected--");
//获取Service的onBind方法所返回的MyBinder对象
binder=(BindService.MyBinder)service;
}
//当该Activity与Service断开连接时回调该方法
@Override
publicvoidonServiceDisconnected(ComponentNamename)
{
System.out.println("--ServiceDisconnected--");
}
};
}
上面activity定义了两个按钮,点击两个按钮有两种不同的方法启动Service:
startService(intent), bindService(Intentservice,ServiceConnectionconn,intflags),
现在来讲解一下两种启动方式的区别,并解释上面的代码。
startService(intent)启动Service呢它不具有与访问者交互的能力,就像activity的startActivity(),它不能从新启动的activity拿到返回数据一样
而bindService(Intentservice,ServiceConnectionconn,intflags),就不一样了
访问者能从启动的Service拿到数据,怎么拿到的呢,bindService的第二个参数conn,该参数是一个ServiceConnection 对象,当访问者与Service连接成功就会回调ServiceConnection 的onServiceConnected()方法,上面的程序就是在这个回调方法里面拿到IBinder 对象的。
可以在看一下
//定义一个ServiceConnection对象
privateServiceConnectionconn=newServiceConnection()
{
//当该Activity与Service连接成功时回调该方法
@Override
publicvoidonServiceConnected(ComponentNamename
,IBinderservice)
{
System.out.println("--ServiceConnected--");
//获取Service的onBind方法所返回的MyBinder对象
binder=(BindService.MyBinder)service;
}
//当该Activity与Service断开连接时回调该方法
@Override
publicvoidonServiceDisconnected(ComponentNamename)
{
System.out.println("--ServiceDisconnected--");
}
};
简单点也就是说访问者通过bindService绑定到Service,绑定成功后会回调ServiceConnection中的onServiceConnected()方法,这个方法里面有IBinderservice参数,这个参数就是Service暴露给访问者的对象,访问者拿到这个对象就可以访问Service的数据了
这就是访问者与Service数据交互的原理,是通过IBinder对象来传递的。
可能到这这里你还对binder=(BindService.MyBinder)service;这句代码不理解。
你肯能觉得拿到的IBinder对象不应该是上面Service代码中onBind方法返回的binder才是嘛,怎么强转成BindService.MyBinder对象了。
而且返回的binder 也没count数据,访问者怎么就能binder.getCount()得到数据呢。
@Override
publicIBinderonBind(Intentintent)
{
System.out.println("ServiceisBinded");
//返回IBinder对象
returnbinder;
}
别忘了上面Service代码里面还对IBinder对象进行处理
//通过继承Binder来实现IBinder类
publicclassMyBinderextendsBinder
{
publicintgetCount()
{
//获取Service的运行状态:count
returncount;
}
}
Binder是IBinder的实现类,MyBinder继承Binder并在里面定义了个方法。
那么拿到 IBinder 对象就相当于拿到 MyBinder对象,就可以访问getCount方法了,这也是为什么binder=(BindService.MyBinder)service;进行强转,并且binder.getCount()可以拿到count数据,因为IBinder里面并没有业务实现,是MyBinder帮它实现了。