是这样在的,我在app运行的时候开启服务,然后退出app并在后台清除该app时,在Service的OnDestroy方法中打log发现并没有走该方法,并且在判断服务的方法中发现该服务仍旧存活。所以这种现象是正常现象吗,原因是什么,我怎样才能在清理后台的时候把这个app的service也关闭?
还有一件事就是,我在Service里面开了一个线程,线程在后台清理后被关闭了,可是线程的标志位改变是在OnDestroy方法中被执行的,难道线程是被系统强制关闭的?
猜测跟service的onstartcommand方法的返回值有关,当返回值为某些值时,在service被非正常杀死时,service有机会自动复活
onDestroy()是在当服务不再使用且将被销毁时,系统将调用此方法。服务应该实现此方法来清理所有资源,如线程、注册的侦听器、接收器等,这是服务接收的最后一个调用。
所以如果使用startService()或者stopSelf()方法请求停止服务,系统会就会尽快销毁这个服务。
如果使用bindService绑定的服务,需要使用unbindService方法来进行解绑销毁。
这个应该是不正常的那么把代码发来看一下吧
这个应该是不正常的那么把代码发来看一下吧
我就是写一个很简单的服务DEMO
public class TestService extends Service{
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
Log.d("TestService", "onCreate");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("TestService", "onStartCommand");
//startThread();
testService();
return super.onStartCommand(intent, flags, startId);
}
public void testService()
{
Log.d("TestService", "testService");
}
private void startThread() {
new Thread(new Runnable() {
@Override
public void run() {
while(true)
{
Log.d("test", "testtttt");
}
}
}).start();
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
Log.d("TestService", "onDestroy");
super.onDestroy();
}
}
MainActivity:
public class MainActivity extends Activity implements OnClickListener {
private Button isService;
private Button stopService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
isService = (Button) findViewById(R.id.isService);
stopService = (Button) findViewById(R.id.stopService);
isService.setOnClickListener(this);
stopService.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.isService:
Intent intent = new Intent(this, TestService.class);
if (CommonUtil.isServiceRunning(getApplicationContext(), TestService.class)) {
Toast.makeText(getApplicationContext(), "1111", 0).show();
} else {
startService(intent);
}
break;
case R.id.stopService:
Intent intent2 = new Intent(this, TestService.class);
stopService(intent2);
break;
default:
break;
}
}
}
CommonUtil.isServiceRunning方法实现:
public static boolean isServiceRunning(Context context,
Class<? extends Service> clazz) {
ActivityManager manager = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningServiceInfo> services = manager.getRunningServices(100);
for (int i = 0; i < services.size(); i++) {
String className = services.get(i).service.getClassName();
if (className.equals(clazz.getName())) {
return true;
}
}
return false;
}
就是长按Android 小圆点跳出程序列表的时候把它划掉。可以看到DDMS里面的程序被关闭了,但是一会儿又被开启了,这时候对服务判断发现仍旧存活,说明从列表中划去的操作并没有完全关闭服务。
被强制关闭就不会走onDestroy方法了
如果想在界面退出时同时销毁后台服务 需要通过 绑定服务 的方式 即: 界面打开时 开启服务 , 界面退出时 停止服务;
下面是我下的案列 你参考下:
Activity中的代码:
private ServiceConnection serviceConnection;
private Context context;
private Intent service;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bind_service_layout);
context = this;
//开启服务
service = new Intent(context, MyService.class);
startService(service);
//创建绑定服务的连接桥
serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
/**
*IBinder iBinder 如果服务里 onBind()返回了 该对象 那么这里可以间接地使用服务中的方法
*/
ToastUtils.showToast(context, "serviceConnection 服务已绑定");
LogUtils.showLog("bindService", "serviceConnection 服务已绑定");
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
ToastUtils.showToast(context, "serviceConnection 服务已解绑");
LogUtils.showLog("bindService", "serviceConnection 服务已解绑");
}
};
//开始绑定服务
bindService(service, serviceConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
/**
* 界面退出时解除绑定 绑定服务 必须 先解绑 ,再销毁
*/
if (serviceConnection != null) {
//解除绑定
unbindService(serviceConnection);
//销毁服务
stopService(service);
LogUtils.showLog("bindService", "Activity 中的服务已解绑 ");
}
super.onDestroy();
}
Service 中的代码:
public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;//这里可以自定义IBinder类 activity就可以使用service中的方法了
}
@Override
public void onCreate() {
super.onCreate();
ToastUtils.showToast(this, "Service 服务开启");
LogUtils.showLog("bindService", "Service 服务已开启");
}
@Override
public void onDestroy() {
ToastUtils.showToast(this, "服务销毁");
LogUtils.showLog("bindService", "Service 服务已销毁");
super.onDestroy();
}
}
你确定线程被关闭了??线程除非自己结束,否则是不归Service管的。如果能这么关掉,就没有内存泄漏的说法了。而且根据你那个任务管理器是不会关闭Service,取决不同的手机,一般手机在分页键里面不会关闭服务,需要去点击应用的强制停止才能
stone_you 这个朋友说的对,
sercice启动分为 startService和 bindService ,这2个service的启动方式,startSerice 是相当于注册service,除非调用stopSelf结束service才走destroy,与App是否退出无关。
bindService是绑定service,App退出时 会 onUnbind --onDestroy 来解除service
http://www.cnblogs.com/mengdd/archive/2013/03/24/2979944.html