Java “如何获得安卓系统”;“绑定”;服务在重新启动配置后仍然有效

Java “如何获得安卓系统”;“绑定”;服务在重新启动配置后仍然有效,java,android,Java,Android,我有一个android应用程序,有一些全局状态(包括一些大的声音池s),需要清理,所以在回答我之前的问题后,我尝试使用服务来处理这个问题 我目前正在使用一个绑定服务,每个活动都会在onStart/onStop中绑定/解除绑定到该服务,当所有活动停止时,该服务将被解除绑定并调用onDestroy,让我释放声音池 由于活动生命周期故意重叠(新活动onStart在旧活动激发onStop之前激发),因此在活动之间导航时,始终至少有一个活动绑定,并且服务保持活动状态 但是,如果我旋转屏幕以导致配置重新启动

我有一个android应用程序,有一些全局状态(包括一些大的
声音池
s),需要清理,所以在回答我之前的问题后,我尝试使用
服务来处理这个问题

我目前正在使用一个绑定服务,每个活动都会在
onStart
/
onStop
中绑定/解除绑定到该服务,当所有活动停止时,该服务将被解除绑定并调用
onDestroy
,让我释放
声音池

由于活动生命周期故意重叠(新活动
onStart
在旧活动激发
onStop
之前激发),因此在活动之间导航时,始终至少有一个活动绑定,并且服务保持活动状态

但是,如果我旋转屏幕以导致配置重新启动,则当活动活动经历配置重新启动生命周期时,服务将解除绑定并终止


我怎样才能绕过这个问题,在重新启动时保持服务的活动性,同时在应用程序停止时仍然允许服务死亡

好吧,既然这已经被证明是一个特别困难的问题,我想我会在这里发布我的解决方案,以防有人碰到类似的问题

显然有几种方法可以实现这一点,但我使用的最简单的方法是使用一个“已启动”的服务来决定何时关闭自己。我的活动每次绑定/解除绑定到服务,在设置的时间延迟(我使用了1分钟)后,如果没有其他活动绑定,服务将自动关闭-这包括用户是否停止使用app plus以及是否存在任何致命的活动错误

关机计时器在
onUnbind()
中计划,并在
onStartCommand()
onBind()
onRebind()中取消。如果触发,它会完全关闭服务,这反过来会触发清理服务的
ondestory()
中的托管状态

我的
服务
代码如下:

public class LocalStateService extends Service {

    /** The binder to give to clients. */
    private final IBinder binder = new LocalStateBinder();

    /** Used for time-delayed shutdown. */
    private final Handler handler = new Handler();

    /**
     * Called before starting or the first binding.
     */
    @Override
    public void onCreate() {
        // initialise state...
    }

    /**
     * Called when this service is explicitly started.
     * @param intent    The intent passed on starting, unused
     * @param flags     Startup flags, unused
     * @param startId   Identifies each start request 
     * @return Desired restart behaviour
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        cancelShutdown();

        // if killed, we would like Android to restart this service, but don't bother re-delivering
        // the original intent used to start the service
        return START_STICKY;
    }

    /**
     * Called when the first client binds.
     * @param intent        The intent passed on binding
     * @return The binding to use
     */
    @Override
    public IBinder onBind(Intent intent) {
        cancelShutdown();
        return binder;
    }

    /**
     * Called when the first of previous clients re-binds.
     * @param intent        The intent passed on binding
     */
    @Override
    public void onRebind(Intent intent) {
        cancelShutdown();
    }

    /**
     * Called when all clients have unbound.
     * @param intent        The first intent originally passed on binding
     * @return Whether this service should be notified of rebinding
     */
    @Override
    public boolean onUnbind(Intent intent) {

        // post a callback to be run in 1 minute
        handler.postDelayed(delayedShutdown, 1000L * 60);

        // we do want onRebind called when clients return
        return true;
    }


    @Override
    public void onDestroy() {
        // state cleanup...
    }

    private Runnable delayedShutdown = new Runnable() {

        @Override
        public void run() {
            LocalStateService.this.stopSelf();
        }

    };

    /**
     * Cancel any shutdown timer that may have been set.
     */
    private void cancelShutdown() {
        // remove any shutdown callbacks registered
        handler.removeCallbacks(delayedShutdown);
    }
}
我的主要活动不是从我的
应用程序中执行此操作,而是在
onCreate()
中调用
startService(..)
,因为这对于初始启动和用户返回到使用暂停的应用程序时都有效(服务可能已决定关闭,也可能尚未决定关闭)

然后,每个活动都会按照正常情况绑定和解除绑定

我发现:

  • 在活动之间导航时,不会触发任何服务回调。由于活动生命周期重叠,这些是次要绑定/取消绑定

  • 当活动重新启动时(例如屏幕旋转),服务将获得一个
    onUnbind()
    调用,然后是一个
    onRebind()
    调用

  • 暂停应用程序(例如,从主活动按home键)或完成应用程序(例如,从主活动按back键)时,服务将获得
    onUnbind()
    ,然后计时器启动


我需要在这方面做更多的工作。我避免像瘟疫一样绑定,因此我没有一个现成的模式来解决您的问题,显然我之前给您的建议是有缺陷的。如何向我的
应用程序
实例添加一些绑定/取消绑定功能-增加/减少一个内部计数器,并且只实际绑定/取消绑定一次?这可能会起作用,尽管这有点危险(例如,未处理的异常导致无法递减)。另一种方法是使用“已启动”
服务
,它可以决定何时需要自行关闭。然后,我可以复制活动的绑定/解除绑定,在最后一次解除绑定时关闭,但有一个方法,活动可以调用该方法来标记正在发生的配置重新启动?在不重新启动活动的情况下处理循环如何?这是一个令人耳目一新的研发。谢谢。您是否考虑从OnBand()中调用StestService(您自己)?为什么在OnBand中调用CalpSeleStutt?如何在第一个活动绑定到服务之前安排关闭?@JoeBowbeer-因为多个活动可以绑定到服务。第二个活动将使用onBind函数进入。@ScottNaef-我在实践中没有看到这一点。为了澄清,我指的是上面服务片段中对onBind/unUnbind/unreland的调用,这些调用在一个进程中运行,使用一个意图绑定多个上下文。onBind是第一次调用,除非最后一个客户端解除绑定(onUnbind),否则不会再次调用。