Activity onDestory延时10秒执行

前期做音乐播放器有个需求是桌面有一个浮标里面有音乐封面,如果音乐在播放的时候封面图片要旋转,后面有发现只要我的浮标在并且图片旋转会导致activity的onDestory方法延时10秒回调。

Activity onDestory延时10秒执行_第1张图片

百思不得其解,最后还是发现因为使用Animation动画在页面销毁的时候没有停止会出现这种情况。

最终解决方法:由于activity销毁动画还要继续,浮标是全局的,音乐播放是service在后台一直播放所以动画不能随activity生命周期结束,所以也不能停止Animation,最后换成属性动画ObjectAnimator

if(objectAnimator==null) {
            objectAnimator = ObjectAnimator.ofFloat(
                    imageView, "rotation", 0f, 360f);
            objectAnimator.setDuration(7000);
            objectAnimator.setInterpolator(new LinearInterpolator());
            objectAnimator.setRepeatCount(ValueAnimator.INFINITE);
        }
        objectAnimator.start();

这样结果是能正常的activity销毁回调onDestory方法。

分析一下原因:

在activity生命周期过程中新显示的Activity在resume后,App的主线程空闲下来才会通知AMS执行后续流程,将之前上一个关闭的Activity销毁。如果新显示Activity在resume后,主线程一直在循环处理MessageQueue中堆积的msg的话(Animation动画一直在post Runnable到主线程),通知AMS执行销毁上一个倍关闭的activity流程自然被延迟了ondestory方法回调也自然被延迟。但是android系统在resume之后还是有一个容错机制

//ActivityStack.java
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
  .....
   // From this point on, if something goes wrong there is no way
            // to recover the activity.
            try {
                next.completeResumeLocked();
            } catch (Exception e) {
                // If any exception gets thrown, toss away this
                // activity and try the next one.
                Slog.w(TAG, "Exception thrown during resume of " + next, e);
                requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
                        "resume-exception", true);
                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                return true;
            }
  .....
}
//ActivityRecord.java
 void completeResumeLocked() {
   .....
    // Schedule an idle timeout in case the app doesn't do it for us.
        mStackSupervisor.scheduleIdleTimeoutLocked(this);
   .....
//ActivityStackSupervisor.java
void scheduleIdleTimeoutLocked(ActivityRecord next) {
        if (DEBUG_IDLE) Slog.d(TAG_IDLE,
                "scheduleIdleTimeoutLocked: Callers=" + Debug.getCallers(4));
        Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
        mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);//延时10s处理以及销毁的activity
    }

Animation.start():最终执行到

//Animation.java
private void fireAnimationStart() {
        if (mListener != null) {
            if (mListenerHandler == null) mListener.onAnimationStart(this);
            else mListenerHandler.postAtFrontOfQueue(mOnStart);
        }
    }

往MessageQueue不断的发Runnable。

因此如果在Animation没有停止会导致activity的onDestory方法回调延时10秒执行。但是Animator则是最终会在 Choreographer中执行

// Thread local storage for the choreographer.
    private static final ThreadLocal sThreadInstance =
            new ThreadLocal() {
        @Override
        protected Choreographer initialValue() {
            Looper looper = Looper.myLooper();
            if (looper == null) {
                throw new IllegalStateException("The current thread must have a looper!");
            }
            Choreographer choreographer = new Choreographer(looper, VSYNC_SOURCE_APP);
            if (looper == Looper.getMainLooper()) {
                mMainInstance = choreographer;
            }
            return choreographer;
        }
    };

并不是主线程,因此不会影响activity的生命周期回调。

更多文章请关注公众号:

Activity onDestory延时10秒执行_第2张图片

 

你可能感兴趣的:(android)