为什么用 unbindService() 方法解绑定服务后 仍然可以调用服务中的方法

rtcw2001 2016-07-03 09:35:09
为什么我用 unbindService 方法解除了绑定后,仍然可以在 活动中调用 服务中的方法,解除绑定后,服务确实已经调用了 onDestory方法销毁了服务,为什么还能调用服务中的方法呢?


活动的代码:

package com.example.myservicetest;

import com.example.myservicetest.MyService.*;

import android.app.*;
import android.content.*;
import android.view.*;
import android.view.View.*;
import android.os.*;
import android.util.Log;
import android.widget.*;

public class MainActivity extends Activity implements OnClickListener {

//--------------------------------------------------------------------
private Button b1, b2, b3, b4, b5;
private ServiceConnection connection;
private MyService myService;
private Intent in;

//--------------------------------------------------------------------
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//获取按钮
b1 = (Button)findViewById(R.id.bind);
b2 = (Button)findViewById(R.id.unbind);
b3 = (Button)findViewById(R.id.play);
b4 = (Button)findViewById(R.id.start);
b5 = (Button)findViewById(R.id.stop);

//注册点击事件
b1.setOnClickListener(this);
b2.setOnClickListener(this);
b3.setOnClickListener(this);
b4.setOnClickListener(this);
b5.setOnClickListener(this);

//用于连接服务
connection = new ServiceConnection()
{
@Override
public void onServiceDisconnected(ComponentName name)
{
Log.e("connection", "连接意外丢失");
}

@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
myService = ((MyBinder)service).getMyService();
Log.e("connection", "连接完成");
}
};

//启动服务意图
in = new Intent(this, MyService.class);

}

//--------------------------------------------------------------------
@Override
public void onClick(View v)
{
switch(v.getId())
{
//启动服务
case R.id.start:
startService(in);
break;

//停止服务
case R.id.stop:
stopService(in);
break;

//绑定服务
case R.id.bind:
bindService(new Intent(this, MyService.class), connection, BIND_AUTO_CREATE);
break;

//解绑服务
case R.id.unbind:
unbindService(connection);
break;

//调用服务中的方法
case R.id.play:
myService.play();
break;
}
}

}


服务的代码:

package com.example.myservicetest;

import android.app.*;
import android.content.*;
import android.os.*;
import android.util.Log;

public class MyService extends Service {

private MyBinder mBinder;

public class MyBinder extends Binder {
public MyService getMyService()
{
return MyService.this;
}
}

//--------------------------------------------------------------------
@Override
public void onCreate()
{
super.onCreate();
mBinder = new MyBinder();
Log.e("Service", "创建服务");
}

//--------------------------------------------------------------------
@Override
public IBinder onBind(Intent intent)
{
Log.e("Service", "执行onBind");
return mBinder;
}

//--------------------------------------------------------------------
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.e("Service", "执行onStartCommand");
return START_NOT_STICKY;
}

//--------------------------------------------------------------------
@Override
public boolean onUnbind(Intent intent)
{
Log.e("Service", "执行onUnbind");
return false;
}

//--------------------------------------------------------------------
@Override
public void onDestroy()
{
Log.e("Service", "服务销毁");
super.onDestroy();
}




//--------------------------------------------------------------------
public void play()
{
Log.e("binder", "播放音乐");
}

}




执行结果:
启动服务-绑定服务-播放-播放-解绑服务-停止服务-播放-播放
...全文
1593 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
徐乙 2018-03-20
  • 打赏
  • 举报
回复 1
这是内存泄漏了,你仍然维持着service的强引用,gc roots通过你的活动依然可以抵达服务。虽然service的销毁周期都跑了,onDestory试图去销毁服务,但是无法做到这一点。这个时候,这已经不是一个服务了,就是一个普通的类,你就是简单的在调用这个类的方法。 //////////// 你要把类和组件区分开。你这个问题就好比与new了一个碎片,就认为他已经初始化了,当然不是。。。只有通过事务与消息机制,进行处理,你的碎片才得到真正意义上的实例化。
bs243458584 2017-06-11
  • 打赏
  • 举报
回复
引用 8 楼 kokoromiro 的回复:
[quote=引用 6 楼 heaimnmn 的回复:] play方法在,不代表service在运行,只是说明这个类没有被回收
. 那bindService这个方法的作用是什么呢, 到底应该怎么用? 我一直都觉得是这么用,但现在看来应该不是这么用了.[/quote] service里的play方法就不该是public,用onStartCommand方法调用play才对。不要直接去持有service对象调用内部方法,要用onBind方法返回给onServiceConnection方法的IBind对象来实现与service的通信。
潇潇独行侠 2016-11-09
  • 打赏
  • 举报
回复
楼主解决没,可否告知,鄙人也是这点疑惑~
开发者_android 2016-07-04
  • 打赏
  • 举报
回复
引用 3 楼 kokoromiro 的回复:
[quote=引用 2 楼 dalor 的回复:] 如上所说。你直接创建了myService对象,调用它的play方法,你的对象在,能调用它的方法,这是最正常不过的。
也就是说,即便解除绑定,服务调用过了destroy方法,服务对象依然存在呗,那正常的用法是怎么用的?[/quote] 你还是要看看service的详细说明和使用。 销毁service,并不是把service对象设置为null.
哎,真难 2016-07-04
  • 打赏
  • 举报
回复
play方法在,不代表service在运行,只是说明这个类没有被回收
xing880307 2016-07-04
  • 打赏
  • 举报
回复
在service的onstart中调用自己的play方法。播放调用startservice(),停止播放调用stopservice
rtcw2001 2016-07-04
  • 打赏
  • 举报
回复
引用 1 楼 liudashao0 的回复:
你这是通过bindservice调用服务里面的方法? 你继承 Binder然后getMyService()里面返回的是这个类,你就根本没有通过bindservice调用服务里面的方法,你就直接调用了play方法,
不经过绑定就无法获得服务对象啊,也就没法调用服务的方法,怎么叫直接调用呢? 难道不是通过绑定来获得服务对象从而执行服务的方法吗? 那正常应该怎么用?
rtcw2001 2016-07-04
  • 打赏
  • 举报
回复
引用 2 楼 dalor 的回复:
如上所说。你直接创建了myService对象,调用它的play方法,你的对象在,能调用它的方法,这是最正常不过的。
也就是说,即便解除绑定,服务调用过了destroy方法,服务对象依然存在呗,那正常的用法是怎么用的?
开发者_android 2016-07-04
  • 打赏
  • 举报
回复
如上所说。你直接创建了myService对象,调用它的play方法,你的对象在,能调用它的方法,这是最正常不过的。
rtcw2001 2016-07-04
  • 打赏
  • 举报
回复
引用 6 楼 heaimnmn 的回复:
play方法在,不代表service在运行,只是说明这个类没有被回收
. 那bindService这个方法的作用是什么呢, 到底应该怎么用? 我一直都觉得是这么用,但现在看来应该不是这么用了.
liudashao0 2016-07-03
  • 打赏
  • 举报
回复
你这是通过bindservice调用服务里面的方法? 你继承 Binder然后getMyService()里面返回的是这个类,你就根本没有通过bindservice调用服务里面的方法,你就直接调用了play方法,

80,472

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧