Service是与Activity最相似的组件,他们都代表可执行的程序,只是Service一直都是在后台运行,它没有用户界面,所以绝对不会到前台来,一旦Service被启动起来之后,它就像Activity一样拥有自己的生命周期,同样是从Context中派生而来的,因此也可以调用Context里定义的如getResources(),getContentResolver()等方法,如果不需要用户交互界面,我们可以考虑通过Service来实现。
创建一个Service的过程:
1.定义一个继承自Service的之类
2.在AndroidManifest.xml文件中配置该Service
我们来看一下具体的code:
/**
* Service 启动Service的方式(Activity中):
* Intent service = new Intent(this,MyService.class);
startService(service);
第一次创建Service的时候会调用onCreate函数,然后调用onStartCommand函数
每点击一次启动Service的时候都会调用onStartCommand函数
停止Service的时候调用:stopService(service);这个函数会调用Service中的onDestory函数多次调用stopService只会触发一次onDestory
* */
public class MyService extends Service {
private boolean exit = false;
private static int count = 0;
@Override
public IBinder onBind(Intent intent){
System.out.println("onBind()");
count = 0 ;//为了演示一下unbind之后再次绑定,我们清楚以前统计的值
MyBinder myBinder= new MyBinder();
return myBinder;
}
@Override
public void onCreate() {
System.out.println("onCreate()");
super.onCreate();
new Thread(new Runnable() {
@Override
public void run() {
while(!exit){
try {
//1s增加一次count
Thread.sleep(1000);
count++;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
}
@Override
public void onDestroy() {
System.out.println("onDestroy()");
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("onStartCommand()");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onRebind(Intent intent) {
System.out.println("onRebind()");
super.onRebind(intent);
}
@Override
public boolean onUnbind(Intent intent) {
System.out.println("onUnbind()");
exit = true;
return true;
}
//我们可以通过传递binder对象来获取我们Service中的count值
public class MyBinder extends Binder{
public int getCount(){
return count;
}
}
}
我们必须实现public IBinder onBind(Intent intent){}这个是在我们bindService的时候用得到;
Service启动的两种方式:
一、startService(intent)启动解析:
这里我们可以通过打印得到其生命周期:
onCreate—–>onStartCommand—->Service停止—–>onDestory
这里我们需要注意的是:
1.onCreate函数只在启动Service的时候调用一次,
2.onStartCommand则是在调用startService的时候调用,且每次都会调用到这个函数
3.stopService(intent)点击多次只会调用一次onDestory
4.由于这里没有涉及到bind函数,因此这也叫非绑定性的Service
二、bindService()启动解析:
首先是其生命周期显示:
onCreate—->onBind—>解绑定Service—->onUnbind—>onDestory
这里我么需要注意的是:
1.我们没有调用onStartCommand函数,而是调用了onBind函数,并且多了一个onUnbind函数的调用
2.每次调用bindService的时候我们都会去调用onServiceConnected函数,这里类似上面的onStartCommand函数的调用
3.onDestory函数的调用是在onUnbind函数之后,但是我们需要注意的是并不是说onUnbind调用之后就一定要调用onDestory,当我们通过startService启动Service之后我们调用bindService之后调用onUnbind函数是不会触发调用onDestory的,因此这里不要理解错了!
4.Activity调用bindService绑定一个已启动的Service时,系统只是把Service内部的IBinder对象给了Activity(通过onServiceConnected中的IBinder service参数传递过来),并不会把该Service生命周期完全绑定到该Activity上,因此当调用unBindService的时候也只是切断了与Activity的联系,并不能停止该Service
通过第4点我们得到了还有一种Service的启动模式,也就是混合模式:
通过startService启动然后绑定Service之后解绑之后stopService
onCreate—->onStartCommand—>onBind—>onUnbind—->onDestory
如果我们解绑之后再次点击绑定,我们会发现我们触发了 onRebind(前提是onUnBind方法返回true)
因此此时过程变成了:
onCreate—->onStartCommand—>onBind—>onUnbind—->onRebind—>onUnbind—->onDestory
然后我们需要了解的是Binder 与Activity之间是怎么通信的,因此做了一个demo,在Activity中去获取Service中的一个static int count 变量,在onCreate中开一个线程不断增加这个变量的值,直到我们调用onUnbind函数
因此我们可以得到他们之间的关系是:
conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
System.out.println("onServiceDisconnected");
}
//service是我们调用Service中的onBind方法返回来的一个Binder对象。通过这个对象我们就可以操作对象关联的函数了
//我们多次点击BindService,只会调用一次Service中的onBind方法,但是会多次调用onServiceConnected方法
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
System.out.println("onServiceConnected");
myBinder = (MyBinder) service;
System.out.println("count = "+myBinder.getCount());
}
};
bindService(service, conn, Service.BIND_AUTO_CREATE);—–中的conn变量作为一个Service沟通的桥,里面我们获取了绑定Service之后由onBind函数返回的一个Binder对象,然后我们的Activity就可以通过这个对象获取Service中的count变量的值了,因此这样就实现了这两大组件之间的联系
下面看一下我们的布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="startService"
android:text="startService" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="stopService"
android:text="stopService" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="DoBindService"
android:text="bindService" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="DoUnbindService"
android:text="UnbindService" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="getCount"
android:text="getCount" />
</LinearLayout>
MainActivity中的对这些button的点击事件的反应:
public class MainActivity extends Activity {
private Intent service ;
private MyBinder myBinder;
private ServiceConnection conn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
service = new Intent(this,MyService.class);
}
public void startService(View v)
{
startService(service);
}
public void stopService(View v)
{
stopService(service);
}
//bindService会调用onCreate 和 onBind
public void DoBindService(View v)
{
conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
System.out.println("onServiceDisconnected");
}
//service是我们调用Service中的onBind方法返回来的一个Binder对象。通过这个对象我们就可以操作对象关联的函数了
//我们多次点击BindService,只会调用一次Service中的onBind方法,但是会多次调用onServiceConnected方法
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
System.out.println("onServiceConnected");
myBinder = (MyBinder) service;
System.out.println("count = "+myBinder.getCount());
}
};
bindService(service, conn, Service.BIND_AUTO_CREATE);
}
public void getCount(View v){
Toast.makeText(this, "count="+myBinder.getCount(), 0).show();
}
public void DoUnbindService(View v )
{
if(conn!=null){
unbindService(conn);
conn = null;
}
}
}