Last active
February 20, 2019 14:29
-
-
Save fesago90/ae7a56628c35e65ddaab to your computer and use it in GitHub Desktop.
shared element transition mem leak fix
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.dopplerlabs.hereactivelistening.hacks; | |
import android.content.Context; | |
import android.content.res.Resources; | |
import android.graphics.Bitmap; | |
import android.graphics.Matrix; | |
import android.graphics.RectF; | |
import android.graphics.drawable.BitmapDrawable; | |
import android.graphics.drawable.Drawable; | |
import android.os.Bundle; | |
import android.os.Parcelable; | |
import android.support.v4.app.SharedElementCallback; | |
import android.view.View; | |
import android.widget.ImageView; | |
/** | |
* Created by Felipe on 12/4/15. | |
* | |
* In your activities add the following code on creation: | |
* ActivityCompat.setEnterSharedElementCallback(this, new LeakFreeSupportSharedElementCallback()); | |
* ActivityCompat.setExitSharedElementCallback(this, new LeakFreeSupportSharedElementCallback()); | |
* | |
*/ | |
public class LeakFreeSupportSharedElementCallback extends SharedElementCallback { | |
static final String BUNDLE_SNAPSHOT_BITMAP = "BUNDLE_SNAPSHOT_BITMAP"; | |
static final String BUNDLE_SNAPSHOT_IMAGE_SCALETYPE = "BUNDLE_SNAPSHOT_IMAGE_SCALETYPE"; | |
static final String BUNDLE_SNAPSHOT_IMAGE_MATRIX = "BUNDLE_SNAPSHOT_IMAGE_MATRIX"; | |
static final String BUNDLE_SNAPSHOT_TYPE = "BUNDLE_SNAPSHOT_TYPE"; | |
static final String BUNDLE_SNAPSHOT_TYPE_IMAGE_VIEW = "BUNDLE_SNAPSHOT_TYPE"; | |
Matrix mTempMatrix; | |
@Override | |
public Parcelable onCaptureSharedElementSnapshot(View sharedElement, Matrix viewToGlobalMatrix, | |
RectF screenBounds) { | |
if (sharedElement instanceof ImageView) { | |
ImageView imageView = ((ImageView) sharedElement); | |
Drawable d = imageView.getDrawable(); | |
Drawable bg = imageView.getBackground(); | |
if (d != null && (bg == null || bg.getAlpha() == 0)) { | |
Bitmap bitmap = TransitionUtils.createDrawableBitmap(d); | |
if (bitmap != null) { | |
Bundle bundle = new Bundle(); | |
bundle.putParcelable(BUNDLE_SNAPSHOT_BITMAP, bitmap); | |
bundle.putString(BUNDLE_SNAPSHOT_IMAGE_SCALETYPE, | |
imageView.getScaleType().toString()); | |
if (imageView.getScaleType() == ImageView.ScaleType.MATRIX) { | |
Matrix matrix = imageView.getImageMatrix(); | |
float[] values = new float[9]; | |
matrix.getValues(values); | |
bundle.putFloatArray(BUNDLE_SNAPSHOT_IMAGE_MATRIX, values); | |
} | |
bundle.putString(BUNDLE_SNAPSHOT_TYPE, BUNDLE_SNAPSHOT_TYPE_IMAGE_VIEW); | |
return bundle; | |
} | |
} | |
} | |
if (mTempMatrix == null) { | |
mTempMatrix = new Matrix(viewToGlobalMatrix); | |
} else { | |
mTempMatrix.set(viewToGlobalMatrix); | |
} | |
Bundle bundle = new Bundle(); | |
Bitmap bitmap = TransitionUtils.createViewBitmap(sharedElement, mTempMatrix, screenBounds); | |
bundle.putParcelable(BUNDLE_SNAPSHOT_BITMAP, bitmap); | |
return bundle; | |
} | |
@Override | |
public View onCreateSnapshotView(Context context, Parcelable snapshot) { | |
View view = null; | |
if (snapshot instanceof Bundle) { | |
Bundle bundle = (Bundle) snapshot; | |
Bitmap bitmap = bundle.getParcelable(BUNDLE_SNAPSHOT_BITMAP); | |
if (bitmap == null) { | |
bundle.clear(); | |
return null; | |
} | |
// Curiously, this is required to have the bitmap be GCed almost immediately after transition ends | |
// otherwise, garbage-collectable mem will still build up quickly | |
bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, false); | |
if (bitmap == null) { | |
return null; | |
} | |
if (BUNDLE_SNAPSHOT_TYPE_IMAGE_VIEW.equals(((Bundle)snapshot).getString(BUNDLE_SNAPSHOT_TYPE))) { | |
ImageView imageView = new ImageView(context); | |
view = imageView; | |
imageView.setImageBitmap(bitmap); | |
imageView.setScaleType( | |
ImageView.ScaleType.valueOf(bundle.getString(BUNDLE_SNAPSHOT_IMAGE_SCALETYPE))); | |
if (imageView.getScaleType() == ImageView.ScaleType.MATRIX) { | |
float[] values = bundle.getFloatArray(BUNDLE_SNAPSHOT_IMAGE_MATRIX); | |
Matrix matrix = new Matrix(); | |
matrix.setValues(values); | |
imageView.setImageMatrix(matrix); | |
} | |
} else { | |
view = new View(context); | |
Resources resources = context.getResources(); | |
view.setBackground(new BitmapDrawable(resources, bitmap)); | |
} | |
bundle.clear(); | |
} | |
return view; | |
} | |
} |
@fesago90
Your code saved my time. Thanks!
Would you please declare the license of your code?
I'd like to use your code to avoid memory leak.
How to use the code?
I put my imageView to Pair
FragmentActivity activity = getActivity();
ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity,
Pair.create(imageView, "image"),
Pair.create(addressTextView, "address")
);
Bundle bundle = options.toBundle();
Intent intent = new Intent(activity,SecondActivity.class);
ActivityCompat.startActivity(activity, intent , bundle);
but in this line bitmap
is always null
. And the method onCaptureSharedElementSnapshot is never called
Seems in this line
https://gist.github.com/fesago90/ae7a56628c35e65ddaab#file-gistfile1-txt-L99
need to reverse
imageView.setImageBitmap(bitmap);
imageView.setScaleType(
ImageView.ScaleType.valueOf(bundle.getString(BUNDLE_SNAPSHOT_IMAGE_SCALETYPE)));
it should be like this:
imageView.setScaleType(
ImageView.ScaleType.valueOf(bundle.getString(BUNDLE_SNAPSHOT_IMAGE_SCALETYPE)));
imageView.setImageBitmap(bitmap);
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I've just come across this, did you make any further progress?