———-、
当使用startService()开启服务的时候,这样服务就会在后台运行,
如果要停止服务的话,必须调用stopService()方法停止服务!
当使用onBind()方法绑定服务的时候,那么就会和该服务建立了
通信,如果要解除绑定,要调用unbindService()方法。
这两条路径并不是完全分开的。
即是说,你可以和一个已经调用了 startService()而被开启的service进行绑定。
比如,一个后台音乐service可能因调用 startService()方法而被开启了,稍后,可能用户想要控制播放器或者得到一些当前歌曲的信息,可以通过bindService()将一个activity和service绑定。这种情况下,stopService()或 stopSelf()实际上并不能停止这个service,除非所有的客户都解除绑定。
无论是绑定还是开启服务,都要经过onCreate()这一方法。
还有 如果同时绑定和开启服务,必须要停止服务和解除绑定才可以完全停止运行!
还是实践出真知,写个demo加深自己的理解:
首先是布局:
activity_main.xml
<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"
>
<TextView
android:id="@+id/tvOut"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world"
/>
<EditText
android:id="@+id/editData"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="默认数据"
/>
<Button
android:id="@+id/btnStartService"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="启动服务"
/>
<Button
android:id="@+id/btnStopService"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="停止服务"
/>
<Button
android:id="@+id/btnBindService"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="绑定服务"
/>
<Button
android:id="@+id/btnUnbindService"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="解除绑定服务"
/>
</LinearLayout>
四个按钮,分别用于启动服务、停止服务、绑定服务、解除绑定服务。
然后创建一个Service,命名为AgainMyService
1.onCreate()启动服务的时候,首先调用该方法,一旦成功启动服务,那么它只会执行一次
2.onStartCommand()启动服务的时候,调用该方法,然后该方法,调用onStart()方法
3.onDestory()停止服务的时候,调用该方法
如果一个Service又被启动又被绑定,则该Service将会一直在后台运行。并且不管如何调用,onCreate始终只会调用一次,对应startService调用多少次,Service的onStart便会调用多少次。调用unbindService将不会停止Service,而必须调用 stopService 或 Service的 stopSelf 来停止服务。
AgainMyService.java
package com.xieth.as.againconnectservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class AgainMyService extends Service {
private String data;
private boolean isrunning = true;
public AgainMyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
Log.d("AgainMyService", "onBind");
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("AgainMyService", "onStartCommand");
data = intent.getStringExtra("data");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onCreate() {
super.onCreate();
Log.d("AgainMyService", "onCreate");
new Thread() {
@Override
public void run() {
super.run();
while (isrunning) {
try {
Log.d("AgainMyService", "data -> " + data);
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
@Override
public void onDestroy() {
super.onDestroy();
isrunning = false;
Log.d("AgainMyService", "onDestory");
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.d("AgainMyService", "onStart");
}
}
AgainMainActivity.java
package com.xieth.as.againconnectservice;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
public class AgainMainActivity extends AppCompatActivity implements View.OnClickListener, ServiceConnection {
private Intent it = null;
private String data = "这是默认信息";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
it = new Intent(AgainMainActivity.this, AgainMyService.class);
findViewById(R.id.btnStartService).setOnClickListener(this);
findViewById(R.id.btnStopService).setOnClickListener(this);
findViewById(R.id.btnBindService).setOnClickListener(this);
findViewById(R.id.btnUnbindService).setOnClickListener(this);
}
@Override
public void onClick(View v) {
int id = v.getId();
switch (id) {
case R.id.btnStartService:
it.putExtra("data", data);
startService(it);
break;
case R.id.btnStopService:
stopService(it);
break;
case R.id.btnBindService:
bindService(it, this, Context.BIND_AUTO_CREATE);
break;
case R.id.btnUnbindService:
unbindService(this);
break;
default:
break;
}
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
运行效果:
依次点击启动服务,再次点击启动服务,最后停止服务
输出结果:
首先执行onCreate->onStartCommand->onStart
再次点击执行onStartCommand->onStart,不再执行onCreate,可见此方法执行一次
最后停止服务,执行onDestory方法
接下来就是绑定服务和解除绑定服务:
界面布局一样:
onBind()绑定服务的时候,调用该方法
bindService()其他组件调用Service的onBind()方法。
unbindService()解除绑定时调用该方法
bindService启动模式下的生命周期:在这种模式下,当调用者首次使用bindService绑定一个服务时,系统会实例化一个Service实例,并一次调用其onCreate方法和onBind方法,然后调用者就可以和服务进行交互了,此后,如果再次使用bindService绑定服务,系统不会创建新的Service实例,也不会再调用onBind方法;如果我们需要解除与这个服务的绑定,可使用unbindService方法,此时onUnbind方法和onDestroy方法会被调用。
demo:
修改一下AgainMyService.java
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
data = intent.getStringExtra("data");
Log.d("AgainMyService", "onBind");
return new Binder();
}
AgainMainActivity.java
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("AgainMyService", "onServiceConnected");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d("AgainMyService", "onServiceDisconnected");
}
依次点击绑定服务和解除绑定服务:
输出结果:
执行顺序onCreate->onBind->onServiceConnected->onDestory
在使用bindService绑定服务时,我们需要一个ServiceConnection代表与服务的连接,它只有两个方法,onServiceConnected和onServiceDisconnected,前者是在操作者在连接一个服务成功时被调用,而后者是在服务崩溃或被杀死导致的连接中断时被调用,而如果我们自己解除绑定时则不会被调用。
2016年1月12日10:18:22 记录