当前位置:网站首页>Service学习笔记02-实战 startService 与bindService
Service学习笔记02-实战 startService 与bindService
2022-06-11 17:25:00 【双木青橙】
启动服务的两种方式
最常见启动Service的两种方式是startService 和bindService,他们之间最主要的区别可参考startService与bindService的区别
启动服务
通过绑定服务的方式可以在客户端获取对应Service的引用,从而完成与Service的交互。主要过程如下图所示:
- 首先,在继承Service的自定义服务中新建一个继承自IBinder的内部类,在IBinder中获取myService的引用
- 在服务的onBinder()方法中将Service中的IBinder对象注入(这个方法会在绑定服务成功的时候被调用,客户端可以通过这个方法获得IBinder对象,进而获取Service的引用)
- 在客户端声明一个ServiceConnection 对象,在ServiceConnection对象的onServiceContected() (这个方法就是在绑定服务成功的时候调用的)可以获得服务中的IBinder对象
- 通过获得的IBinder对象获取Service引用,可以获取Service中的数据和方法

代码实战
首先,我们先定义一个TestService,增加myBinder的内部类,在里面通过一个public类返回TestService 对象,然后重写onBind方法将Binder类返回给客户端,这是必要的一步,这样客户端就可以通过bind方式获取到我们的Service
public class TestService extends Service {
private static final String TAG = "TestService";
private static final Random generator = new Random();
//通过binder实现调用client与Service之间的通信
private MyBinder binder;
//要想自己的Service 支持bindService的启动方式,就必须在Service的OnBind方法中返回一个IBinder类型的实例
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "TestService -> onBind,Thread:" + Thread.currentThread().getName());
return binder;
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "TestService -> onUnbind,Thread:" + intent.getStringExtra("from"));
return false;
}
public class MyBinder extends Binder {
public TestService getService() {
return TestService.this;
}
}
@Override
public void onCreate() {
Log.i(TAG, "TestService -> onCreate,Thread:" + Thread.currentThread().getName());
super.onCreate();
binder=new MyBinder();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "TestService -> onStartCommand,StartId: " + startId + "Thread:" + Thread.currentThread().getName());
return START_NOT_STICKY;
}
@Override
public void onDestroy() {
Log.i(TAG, "TestService -> onDestroy,Thread:" + Thread.currentThread().getName());
super.onDestroy();
}
//Service 暴露出去供client调用的公共方法
public int getRandomNumber() {
return generator.nextInt();
}
}
然后在Activity当中通过bindService来启动Service
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG="MainActivity";
private TestService service=null;
private boolean isBound=false;
private ServiceConnection connection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
isBound=true;
TestService.MyBinder myBinder=(TestService.MyBinder)binder;
service= myBinder.getService();
Log.i(TAG,"MainActivity onServiceConnected");
int num=service.getRandomNumber();
Log.i(TAG,"MainActivity 中调用TestService的getRandomNumber方法,结果:"+num);
}
@Override
public void onServiceDisconnected(ComponentName name) {
isBound=false;
Log.i(TAG,"MainActivity onServiceDisconnected");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i(TAG,"MainActivity -> onCreate,Thread:"+Thread.currentThread().getName());
Button bindServiceButton=(Button)findViewById(R.id.btnBindService);
bindServiceButton.setOnClickListener(this);
}
@Override
public void onClick(View v) {
Log.i(TAG,"onClick has into");
if(v.getId()==R.id.btnBindService){
Intent intent=new Intent(this,TestService.class);
intent.putExtra("from","ActivityA");
Log.i(TAG,"MainActivity 执行 bindService");
bindService(intent,connection,BIND_AUTO_CREATE);
}else if(v.getId()==R.id.btnUnBindService){
if(isBound){
Log.i(TAG,"MainActivity 执行 unBindService");
unbindService(connection);
}
}
}
}
在MainActivity 当中先是创建一个实现了ServiceConnection 的成员变量connection,里面主要需要重写onServiceConnected方法,在里面去创建IBinder 对象,并且获取Serivice对象
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG="MainActivity";
private TestService service=null;
private boolean isBound=false;
private ServiceConnection connection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
isBound=true;
TestService.MyBinder myBinder=(TestService.MyBinder)binder;
service= myBinder.getService();
Log.i(TAG,"MainActivity onServiceConnected");
int num=service.getRandomNumber();
Log.i(TAG,"MainActivity 中调用TestService的getRandomNumber方法,结果:"+num);
}
@Override
public void onServiceDisconnected(ComponentName name) {
isBound=false;
Log.i(TAG,"MainActivity onServiceDisconnected");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i(TAG,"MainActivity -> onCreate,Thread:"+Thread.currentThread().getName());
Button bindServiceButton=(Button)findViewById(R.id.btnBindService);
bindServiceButton.setOnClickListener(this);
Button unBindServiceButton=(Button)findViewById(R.id.btnUnBindService);
unBindServiceButton.setOnClickListener(this);
Button startActivityButton=(Button)findViewById(R.id.btnStartActivity);
startActivityButton.setOnClickListener(this);
Button coastRandomNumButton=(Button)findViewById(R.id.btnCoastRandomNum);
coastRandomNumButton.setOnClickListener(this);
}
@Override
public void onClick(View v) {
Log.i(TAG,"onClick has into");
if(v.getId()==R.id.btnBindService){
Intent intent=new Intent(this,TestService.class);
intent.putExtra("from","ActivityA");
Log.i(TAG,"MainActivity 执行 bindService");
bindService(intent,connection,BIND_AUTO_CREATE);
}else if(v.getId()==R.id.btnUnBindService){
if(isBound){
Log.i(TAG,"MainActivity 执行 unBindService");
unbindService(connection);
}
}else if(v.getId()==R.id.btnStartActivity){
Intent intent=new Intent(this,ActivityB.class);
Log.i(TAG,"MainActivity 启动ActivityB");
startActivity(intent);
}else if(v.getId()==R.id.btnFinish){
Log.i(TAG,"MainActivity 执行 finish");
this.finish();
}else if(v.getId()==R.id.btnCoastRandomNum){
Log.i(TAG,"MainActivity 执行 coastRandom");
Log.i(TAG,"random num :"+service.getRandomNumber());
}
}
@Override
protected void onDestroy() {
Log.i(TAG,"MainActivity -> onDestroy");
super.onDestroy();
}
}
- 问题1:在同一个Activity 重新执行bindService方法会如何?
重新执行ServiceConnection的onServiceConnected方法 - 问题2: bindService 或者unBindService 不成对出现会如何?
经过验证:重复执行bindService 方法只会执行一次Service的onBind 和onCreate 方法,bindService内部做了单例机制,但是如果多次执行unBindService方法会直接抛异常java.lang.IllegalArgumentException: Service not registered - 问题3:为什么已经执行了unBindService方法还是可以引用绑定service 的方法?
问题3 从而引起来是否存在内存泄漏的问题,通过查看
参考资料
https://blog.csdn.net/qq_33718648/article/details/79880105
https://blog.csdn.net/oudetu/article/details/79279596
边栏推荐
- 《DAMA数据管理知识体系指南》:章节分值占比
- Vscode configures eslint to automatically format an error "auto fix is enabled by default. use the single string form“
- C language: use H and C. summary of problems encountered in documents
- How does Sister Feng change to ice?
- 10 times faster than 5g. Are you ready for 10 Gigabit communication?
- Authing Share|理解 SAML2 协议
- CLP information -5 keywords to see the development trend of the financial industry in 2022
- 搜狐全員遭詐騙,暴露哪些問題?
- Intranet penetration based on UDP port guessing
- Tornado environment construction and basic framework construction -- familiar Hello World
猜你喜欢

ffmpeg CBR精准码流控制三个步骤

端口规划与APJ

TypeScript学习笔记(二)

定制 or 订阅?未来中国 SaaS 行业发展趋势是什么?

Guide to Dama data management knowledge system: percentage of chapter scores

What subclasses inherit, polymorphism, and upward transformation

满k叉树编号为 i 的节点的孩子编号公式推导

04_特征工程—特征选择

Authing CEO 谢扬入选福布斯 2021 年 30 Under 30 亚洲榜单

Authing Share|理解 SAML2 协议
随机推荐
Classification and method of feature fusion
vscode配置eslint自动格式化报错“Auto Fix is enabled by default. Use the single string form“
Port planning and APJ
error:指针作为函数参数错误总结
From a "trendsetter" to a "wind chaser", can master Kang still lead the market?
How to become an optimist organization?
【Mysql】redo log,undo log 和binlog详解(四)
子类继承了什么、多态、 向上转型
7-1 均是素数
6-5 统计单词数量(文件)(*)
LeetCode-859. 亲密字符串
6-1 需要多少单词可以组成一句话?
Custom or subscription? What is the future development trend of China's SaaS industry?
LeetCode-384. 打乱数组
Config: user attribute configuration framework
Leetcode力扣刷题
Talk about the interview questions of the collection
Science popularization genius on the left, madman on the right
[online problem] timeout waiting for connection from pool
6-3 读文章(*)