在Android上,我有一个名为FirstActivity
的Activity
,它启动一个名为MyService
的Service
,在后台进行网络工作。Activity
和Service
通过调用方法一直相互通信。
现在,当用户从FirstActivity
导航到SecondActivity
时,不应终止或重新创建后台服务,而应保持活动状态并传递给现在与服务通信的SecondActivity
。
换句话说,只要两个Activity
中的一个正在运行,Service
就应该运行,并且当用户在两个Activity
之间导航时,它不应该停止。
其中一个Activity
将始终位于前台,在此期间,服务应该(最好(永远不会被杀死。我认为这应该不是问题,因为这两个Activity
中的一个始终处于活动状态,因此Android知道该服务很重要,而不是必须杀死的东西。
(如果没有办法阻止Android不时终止和重新创建服务,我需要一种方法来优雅地恢复服务的完整状态。
综上所述,Service
应该与两个Activity
"组合"具有相同的寿命。它应该从其中第一个开始,并在它们都被摧毁之前停止。
那么以下代码对于该设置和目标是否正确?
public class MyService extends Service {
public class LocalBinder extends Binder {
public MyService getService() {
return MyService.this;
}
}
...
}
public class FirstActivity extends Activity {
private MyService mMyService;
private ServiceConnection mMainServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
MyService mainService = ((LocalBinder) service).getService();
mMyService = mainService;
mMyService.setCallback(FirstActivity.this);
}
@Override
public void onServiceDisconnected(ComponentName className) {
mMyService = null;
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
...
startService(new Intent(FirstActivity.this, MyService.class));
}
@Override
protected void onResume() {
super.onResume();
bindService(new Intent(FirstActivity.this, MyService.class), mMainServiceConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onPause() {
super.onPause();
if (mMainServiceConnection != null) {
unbindService(mMainServiceConnection);
}
if (mMyService != null) {
mMyService.setCallback(null);
}
if (!isUserMovingToSecondActivity) {
stopService(new Intent(FirstActivity.this, MyService.class));
}
}
@Override
public void onBackPressed() {
stopService(new Intent(FirstActivity.this, MyService.class));
super.onBackPressed();
}
...
}
public class SecondActivity extends Activity {
private MyService mMyService;
private ServiceConnection mMainServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
MyService mainService = ((LocalBinder) service).getService();
mMyService = mainService;
mMyService.setCallback(SecondActivity.this);
}
@Override
public void onServiceDisconnected(ComponentName className) {
mMyService = null;
}
};
@Override
protected void onResume() {
super.onResume();
bindService(new Intent(SecondActivity.this, MyService.class), mMainServiceConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onPause() {
super.onPause();
if (mMainServiceConnection != null) {
unbindService(mMainServiceConnection);
}
}
@Override
protected void onDestroy() {
...
stopService(new Intent(SecondActivity.this, MyService.class));
}
...
}
这是保证在Activity
后台持久服务的最佳方式,不会被杀死或重新创建吗?
Context.BIND_AUTO_CREATE
呢?在这里设置此标志是否正确?Context.BIND_ADJUST_WITH_ACTIVITY
和Context.BIND_WAIVE_PRIORITY
呢 - 我需要这些吗?
(非常感谢@corsair992的有用指示!
如果始终按该顺序调用活动(即 FirstActivity
从SecondActivity
开始,而不是相反,那么基本上,你应该尝试将服务的生命周期与FirstActivity
的生命周期"捆绑"起来。
一般来说(请参阅后面的警告(,这意味着:
FirstActivity.onCreate()
中呼叫startService()
。- 在
FirstActivity.onDestroy()
中呼叫stopService()
。 - 在两个活动的
onStart()
/onStop()
方法中调用bindService()
/unbindService()
(以访问Binder对象,并能够对其调用方法(。
以这种方式启动的服务将一直处于活动状态,直到调用stopService()
并且每个客户端都解除绑定,请参阅管理服务的生命周期:
这两条道路并非完全分开。也就是说,您可以绑定到 已使用 startService(( 启动的服务。(...)在这种情况下,stopService(( 或 stopSelf(( 实际上不会停止服务,直到所有客户端 㩠。
和:
当最后一个客户端从服务中解除绑定时,系统会销毁 服务(除非该服务也由 startService(( 启动(。
有了这个基本策略,只要FirstActivity
还在(即它没有被破坏(,该服务就会存在。但是,仍然存在重要的一点:如果未显式处理配置更改(例如屏幕旋转(,将导致活动自行重新启动,并且服务将被销毁(因为我们在onDestroy()
中调用stopService()
(。
为了防止这种情况,您可以在实际停止服务之前检查isChangingConfigurations()
(因为由于此原因而发生的onDestroy()
回调意味着尽管此特定 Activity 实例被销毁,但之后将重新创建它。
因此,完整的解决方案将是这样的:
public class FirstActivity extends Activity
{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startService(new Intent(this, MyService.class));
}
private ServiceConnection mServiceConnection = new ServiceConnection() { ... }
@Override
protected void onStart() {
super.onStart();
bindService(new Intent(this, MyService.class), mServiceConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
unbindService(mServiceConnection);
super.onStop();
}
@Override
protected void onDestroy() {
if (!isChangingConfigurations())
stopService(new Intent(this, MyService.class));
super.onDestroy();
}
虽然SecondActivity
只会实现onStart()
/onStop()
方法(以相同的方式(。
关于您的特定实现的一些说明:
- 没有必要覆盖
onBackPressed()
,因为如果活动被销毁,将调用必要的生命周期方法(另外,它可以在不按后退按钮的情况下完成,例如,如果调用finish()
(。 - 在
onDestroy()
中停止服务而不是onPause()
使您不必检查isUserMovingToSecondActivity
。