在后台长期服务的活动不会被杀死



在Android上,我有一个名为FirstActivityActivity,它启动一个名为MyServiceService,在后台进行网络工作。ActivityService通过调用方法一直相互通信。

现在,当用户从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_ACTIVITYContext.BIND_WAIVE_PRIORITY呢 - 我需要这些吗?

(非常感谢@corsair992的有用指示!


如果始终按该顺序调用活动(即 FirstActivitySecondActivity开始,而不是相反,那么基本上,你应该尝试将服务的生命周期与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

相关内容

  • 没有找到相关文章

最新更新