facebook/fresco
GitHub で見るbitmap's byte[] leak when use RoundedBitmapDrawable in android 6.0
Open
#2,429 opened on 2019年10月31日
bughelp wantedstarter-task
説明
Description
when wrap a drawable with RoundedBitmapDrawable in fresco ,after call bitmap.recycle(), it's byte[] data is still hold by native stack which cause a memory leak.
here is the memry when show and destroy a image:

here is the hprof,the byte[] 's GC root is Native Stack,and without anyother references :

Reproduction
app's gradle file
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
buildToolsVersion "29.0.0"
defaultConfig {
applicationId "com.example.imagetest"
minSdkVersion 23
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
implementation 'com.github.bumptech.glide:glide:4.10.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.10.0'
implementation 'com.facebook.fresco:fresco:1.8.0'
}
sample code
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import androidx.appcompat.app.AppCompatActivity;
import com.facebook.drawee.drawable.RoundedBitmapDrawable;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
public class MainActivity extends AppCompatActivity {
ViewGroup root;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
root = findViewById(R.id.root);
}
private Bitmap mBitmap;
private ImageView mView;
private Bitmap decode(String url) throws IOException {
InputStream is = null;
Bitmap bmp;
try {
URL url1 = new URL(url);
HttpURLConnection con = (HttpURLConnection) url1.openConnection();
is = con.getInputStream();
bmp = BitmapFactory.decodeStream(is);
} finally {
if (is != null) {
is.close();
}
}
return bmp;
}
private BitmapDrawable getDrawable(Bitmap map) {
return new BitmapDrawable(getResources(), map);
}
private RoundedBitmapDrawable getRoundDrawable(BitmapDrawable drawable) {
RoundedBitmapDrawable bitmapDrawable = new RoundedBitmapDrawable(getResources(), drawable.getBitmap(), drawable.getPaint());
bitmapDrawable.setCircle(false);
float[] roundd = {15.36f, 15.36f, 15.36f, 15.36f, 15.36f, 15.36f, 15.36f, 15.36f};
bitmapDrawable.setRadii(roundd);
bitmapDrawable.setBorder(0, 0);
bitmapDrawable.setPadding(0);
bitmapDrawable.setScaleDownInsideBorders(false);
return bitmapDrawable;
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.create:
if (mView != null) {
return;
}
new Thread(new Runnable() {
@Override
public void run() {
try {
mBitmap = decode("https://images.manmanapp.com/banner/5d8daf812ff15.jpg");
runOnUiThread(new Runnable() {
@Override
public void run() {
mView = new ImageView(MainActivity.this);
mView.setImageDrawable(
getDrawable(mBitmap));
mView.setLayoutParams(new LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
root.addView(mView);
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
break;
case R.id.delete:
View v1 = mView;
if (v1 != null) {
mView = null;
root.removeView(v1);
}
Bitmap bit = mBitmap;
if (bit != null) {
mBitmap = null;
bit.recycle();
}
break;
default:
break;
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/create"
android:layout_width="100dp"
android:layout_height="100dp"
android:text="create"
android:onClick="onClick"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@color/colorAccent"
android:layout_margin="10dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/delete"
android:layout_width="100dp"
android:layout_height="100dp"
android:text="delete"
android:onClick="onClick"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@color/colorAccent"
android:layout_margin="10dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!--
<ImageView
android:id="@+id/img"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
-->
</LinearLayout>
</ScrollView>
Additional Information
- Fresco version: [1.8.0]
- Platform version: [android 6.0]