您的位置:首页 > 其它

关于Service中bindService注意的几个问题

2015-07-17 21:48 302 查看
最近有用到Activity需要不断的从Service中获取数据,第一个想法肯定就是通过bind回调机制了,有几点概念模糊特此记录下:

单独使用bindService(),unbindService()会经历:->onCreate()->onBind()->Service running->onUnbind()
-> onDestroy() 。

单独使用startService(),stopService()会经历:->onCreate()->onStartCommand()->Service running-> onDestroy() 。

先调用startService(),再调用bindService()方法:

如果结束只调用unbindService(),那么只会执行到onUnbind(),将不会执行onDestroy():->onCreate()->onStartCommand()->onBind()->Service
running-> onUnbind()。
如果在unbindService后,在调用stopService(),那么:->onCreate()->onStartCommand()->onBind()->Service running->
onUnbind()->onDestroy() 。

1、绑定的Service只有当应用组件绑定后才能运行,多个组件可以绑定一个Service,当调用unbind()方法时,这个service就会被销毁了。

2、Service与Activity一样都存在与当前进程的主线程中,所以,一些阻塞UI的操作,比如耗时操作不能放在service里进行,比如另外开启一个线程来处理诸如网络请求的耗时操作。如果在service里进行一些耗CPU和耗时操作,可能会引发ANR警告,这时应用会弹出是强制关闭还是等待的对话框。所以,对service的理解就是和activity平级的,只不过是看不见的,在后台运行的一个组件,这也是为什么和activity同被说为Android的基本组件。
3、图形理解Service:



通过这个图可以看到,两种启动Service的方式以及他们的生命周期,bindService的不同之处在于当绑定的组件销毁后,对应的Service也就被kill了。Service的声明周期相比与Activity的简单了许多,只要好好理解两种启动service方式的异同就行

4、关于停止Service,如果service是非绑定的,最终当任务完成时,为了节省系统资源,一定要停止service,可以通过stopSelf()来停止,也可以在其他组件中通过stopService()来停止,绑定的service可以通过onUnBind()来停止service。

关于Activity与Service数据的互相传递,写了个demo:

public class MainActivity extends Activity implements View.OnClickListener {
private  TextView mTextView;
private EditText mEditText;
private MyService.LocalBinder binder=null;
MyService myService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mEditText = (EditText) findViewById(R.id.edt_content);
Button mBtnStart = (Button) findViewById(R.id.btn_start);
Button mBtnClose = (Button) findViewById(R.id.btn_close);
Button mBtnSubmit = (Button) findViewById(R.id.btn_submit);
mTextView = (TextView) findViewById(R.id.tv_show);
mBtnStart.setOnClickListener(this);
mBtnClose.setOnClickListener(this);
mBtnSubmit.setOnClickListener(this);
}
public ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
binder = (MyService.LocalBinder) service;//得到LocalBinder实例
myService = binder.getService();//得到Service实例
//设置接口回调获取Service中的数据
myService.setOnDataCallback(new MyService.OnDataCallback() {
@Override
public void onDataChange( final String message) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mTextView.setText(message);
}
});
}
});
}

@Override
public void onServiceDisconnected(ComponentName name) {
myService = null;
}
};
@Override
public void onClick(View v) {
Intent intent = new Intent(this,MyService.class);
switch (v.getId()){
case R.id.btn_start:
//                startService(intent);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);//为Activity绑定服务
break;
case R.id.btn_close:
unbindService(mServiceConnection);//解除绑定
//                stopService(intent);
break;
case R.id.btn_submit:
if(binder!=null){
//把数据传给Service,相比用Bundle效率更高
binder.setData(mEditText.getText().toString());
}
break;
}
}

@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);//解除绑定
}
}
MyService:

public class MyService extends Service {
private String message ;
private boolean isRunning = true;
private IBinder binder = new LocalBinder();
public class LocalBinder extends Binder {
public void setData(String message) {
//从Activity传入message值
MyService.this.message = message;
}

public MyService getService() {
//返回当前MyService对象
return MyService.this;
}
}
private OnDataCallback mOnDataCallback=null;

public void setOnDataCallback(OnDataCallback mOnDataCallback) {
this.mOnDataCallback = mOnDataCallback;
}

public interface OnDataCallback{
void onDataChange(String message);
}
@Override
public IBinder onBind(Intent intent) {
//返回这个LocalBinder对象,其实这个对象可以在Activity中onServiceConnected()方法中接收到,这个bind就是Activity和Service通信的桥梁
//因为在Activity通过这个bind对象可以得到Service的实例引用。一旦Service对象找到,就能得到它的公共方法和属性。
return binder;
}

@Override
public void onCreate() {
super.onCreate();
new Thread() {
@Override
public void run() {
int i=1;
while (isRunning) {
if(mOnDataCallback!=null){
mOnDataCallback.onDataChange(message + i);
}
i++;
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();

}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}

@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}

@Override
public void onDestroy() {
super.onDestroy();
isRunning = false;
}
}
Activity能进行绑定得益于Service的接口onBind()。Service和Activity的连接可以用ServiceConnection来实现,需要实现一个新的ServiceConnection,重写onServiceConnected和onServiceDisconnected方法。执行绑定,调用bindService方法,传入一个选择了要绑定的Service的Intent(显式或隐式)和一个你实现了的ServiceConnection实例。一旦连接建立,你就能通Service的接口onBind()得到mBinder实例进而得到Service的实例引用。一旦Service对象找到,就能得到它的公共方法和属性。但这种方式,只能在同一个进程和同一个Application里。跨进程跨应用通信IPC需要建立aidl文件(注:Android5.0以后跨应用只能通过显示Intent来启动Service,即包名、类名)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: