From 6e7fb60b93d3449d256282a9cc34ba3356add90e Mon Sep 17 00:00:00 2001 From: George Mount Date: Thu, 4 Sep 2014 16:20:20 -0700 Subject: [PATCH] Fix NPE when Window disappears during a transition. Bug 17343866 Change-Id: I421a28e833ecb78cd542f3f6a728ac87b65ef832 --- .../app/ActivityTransitionCoordinator.java | 20 ++++++++++--------- .../app/EnterTransitionCoordinator.java | 17 +++++++++------- .../app/ExitTransitionCoordinator.java | 5 +++-- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java index a09a2e7d090c5..1d8ca60bae513 100644 --- a/core/java/android/app/ActivityTransitionCoordinator.java +++ b/core/java/android/app/ActivityTransitionCoordinator.java @@ -467,11 +467,12 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { } protected void scheduleSetSharedElementEnd(final ArrayList snapshots) { - getDecor().getViewTreeObserver().addOnPreDrawListener( + final View decorView = getDecor(); + decorView.getViewTreeObserver().addOnPreDrawListener( new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { - getDecor().getViewTreeObserver().removeOnPreDrawListener(this); + decorView.getViewTreeObserver().removeOnPreDrawListener(this); notifySharedElementEnd(snapshots); return true; } @@ -664,8 +665,7 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { GhostView.addGhost(view, decor); ViewGroup parent = (ViewGroup) view.getParent(); if (moveWithParent && !isInTransitionGroup(parent, decor)) { - GhostViewListeners listener = - new GhostViewListeners(view, decor); + GhostViewListeners listener = new GhostViewListeners(view, parent, decor); parent.getViewTreeObserver().addOnPreDrawListener(listener); mGhostViewListeners.add(listener); } @@ -723,11 +723,12 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { } protected void scheduleGhostVisibilityChange(final int visibility) { - getDecor().getViewTreeObserver() + final View decorView = getDecor(); + decorView.getViewTreeObserver() .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { - getDecor().getViewTreeObserver().removeOnPreDrawListener(this); + decorView.getViewTreeObserver().removeOnPreDrawListener(this); setGhostVisibility(visibility); return true; } @@ -769,10 +770,12 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { private static class GhostViewListeners implements ViewTreeObserver.OnPreDrawListener { private View mView; private ViewGroup mDecor; + private View mParent; private Matrix mMatrix = new Matrix(); - public GhostViewListeners(View view, ViewGroup decor) { + public GhostViewListeners(View view, View parent, ViewGroup decor) { mView = view; + mParent = parent; mDecor = decor; } @@ -782,10 +785,9 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { @Override public boolean onPreDraw() { - ViewGroup parent = ((ViewGroup) mView.getParent()); GhostView ghostView = GhostView.getGhost(mView); if (ghostView == null) { - parent.getViewTreeObserver().removeOnPreDrawListener(this); + mParent.getViewTreeObserver().removeOnPreDrawListener(this); } else { GhostView.calculateMatrix(mView, mDecor, mMatrix); ghostView.setMatrix(mMatrix); diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java index 47d3fd60c5869..819f344991e81 100644 --- a/core/java/android/app/EnterTransitionCoordinator.java +++ b/core/java/android/app/EnterTransitionCoordinator.java @@ -71,12 +71,13 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { Bundle resultReceiverBundle = new Bundle(); resultReceiverBundle.putParcelable(KEY_REMOTE_RECEIVER, this); mResultReceiver.send(MSG_SET_REMOTE_RECEIVER, resultReceiverBundle); - getDecor().getViewTreeObserver().addOnPreDrawListener( + final View decorView = getDecor(); + decorView.getViewTreeObserver().addOnPreDrawListener( new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { if (mIsReadyForTransition) { - getDecor().getViewTreeObserver().removeOnPreDrawListener(this); + decorView.getViewTreeObserver().removeOnPreDrawListener(this); } return mIsReadyForTransition; } @@ -189,11 +190,12 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { moveSharedElementsToOverlay(); mResultReceiver.send(MSG_SHARED_ELEMENT_DESTINATION, state); } else { - getDecor().getViewTreeObserver() + final View decorView = getDecor(); + decorView.getViewTreeObserver() .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { - getDecor().getViewTreeObserver().removeOnPreDrawListener(this); + decorView.getViewTreeObserver().removeOnPreDrawListener(this); if (mResultReceiver != null) { Bundle state = captureSharedElementState(); setSharedElementMatrices(); @@ -344,11 +346,12 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { } final Bundle sharedElementState = mSharedElementsBundle; mSharedElementsBundle = null; - getDecor().getViewTreeObserver() + final View decorView = getDecor(); + decorView.getViewTreeObserver() .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { - getDecor().getViewTreeObserver().removeOnPreDrawListener(this); + decorView.getViewTreeObserver().removeOnPreDrawListener(this); startTransition(new Runnable() { @Override public void run() { @@ -358,7 +361,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { return false; } }); - getDecor().invalidate(); + decorView.invalidate(); } private void requestLayoutForSharedElements() { diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java index 3760b96b59807..dd33f8830c5bd 100644 --- a/core/java/android/app/ExitTransitionCoordinator.java +++ b/core/java/android/app/ExitTransitionCoordinator.java @@ -164,11 +164,12 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { }); final ArrayList sharedElementSnapshots = createSnapshots(mExitSharedElementBundle, mSharedElementNames); - getDecor().getViewTreeObserver() + final View decorView = getDecor(); + decorView.getViewTreeObserver() .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { - getDecor().getViewTreeObserver().removeOnPreDrawListener(this); + decorView.getViewTreeObserver().removeOnPreDrawListener(this); setSharedElementState(mExitSharedElementBundle, sharedElementSnapshots); return true; }