我是Android开发的新手。我正在尝试通过HTTP下载图像并将它们存储在ImageViews或Drawables中。在这个例子中,我使用的是ImageViews。最初,我使用AsyncTask下载这些图像(大约每个约500KB),但是我决定使用Picasso,因为我读过它更可靠。
在下面的代码中,我有20个ImageView。每个图像URL是大约400KB的图像。但是,在加载所有这些之后,我注意到我的getUsedMem()
大于100MB。我不确定是什么导致了这个内存泄漏。
你能帮助我吗?
public class Example extends Activity {
public long getUsedMem()
{
long freeSize = 0L;
long totalSize = 0L;
long usedSize = -1L;
try {
Runtime info = Runtime.getRuntime();
freeSize = info.freeMemory();
totalSize = info.totalMemory();
usedSize = totalSize - freeSize;
} catch (Exception e) {
e.printStackTrace();
}
return usedSize;
}
public void concatLogMessages(String msg)
{
TextView tv = (TextView) findViewById(R.id.textView1);
CharSequence cs = tv.getText();
tv.setText(cs + "\n" +
"Image #: " + msg + "\n" +
"Used Mem: " + getUsedMem()
);
}
public void loadImage(final ImageView target, String url, final int num) {
Picasso.with(this).load(url).into(target, new EmptyCallback(){
@Override
public void onError() {
Example.this.concatLogMessages("Picasso onError");
super.onError();
}
@SuppressLint("NewApi") @Override
public void onSuccess() {
Example.this.concatLogMessages("Picasso onSuccess " + num);
super.onSuccess();
}
});
}
@SuppressLint("NewApi")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
drawables = new ArrayList<Drawable>();
// Check Memory Before Everything
concatLogMessages("0");
// Imageview to show
ImageView image1 = (ImageView) findViewById(R.id.imageView1);
ImageView image2 = (ImageView) findViewById(R.id.imageView2);
ImageView image3 = (ImageView) findViewById(R.id.imageView3);
ImageView image4 = (ImageView) findViewById(R.id.imageView4);
ImageView image5 = (ImageView) findViewById(R.id.imageView5);
ImageView image6 = (ImageView) findViewById(R.id.imageView6);
ImageView image7 = (ImageView) findViewById(R.id.imageView7);
ImageView image8 = (ImageView) findViewById(R.id.imageView8);
ImageView image9 = (ImageView) findViewById(R.id.imageView9);
ImageView image10 = (ImageView) findViewById(R.id.imageView10);
ImageView image11 = (ImageView) findViewById(R.id.imageView11);
ImageView image12 = (ImageView) findViewById(R.id.imageView12);
ImageView image13 = (ImageView) findViewById(R.id.imageView13);
ImageView image14 = (ImageView) findViewById(R.id.imageView14);
ImageView image15 = (ImageView) findViewById(R.id.imageView15);
ImageView image16 = (ImageView) findViewById(R.id.imageView16);
ImageView image17 = (ImageView) findViewById(R.id.imageView17);
ImageView image18 = (ImageView) findViewById(R.id.imageView18);
ImageView image19 = (ImageView) findViewById(R.id.imageView19);
ImageView image20 = (ImageView) findViewById(R.id.imageView20);
/* Picasso */
ImageView target = (ImageView) findViewById(R.id.picassoImageView);
loadImage(target, image_url1, 0);
// Test 1-20 image views...
loadImage(image1, R.String.image_url1, 1);
loadImage(image2, R.String.image_url2, 2);
loadImage(image3, R.String.image_url3, 3);
loadImage(image4, R.String.image_url4, 4);
loadImage(image5, R.String.image_url5, 5);
loadImage(image6, R.String.image_url6, 6);
loadImage(image7, R.String.image_url7, 7);
loadImage(image8, R.String.image_url8, 8);
loadImage(image9, R.String.image_url9, 9);
loadImage(image10, R.String.image_url10, 10);
loadImage(image11, R.String.image_url11, 11);
loadImage(image12, R.String.image_url12, 12);
loadImage(image13, R.String.image_url13, 13);
loadImage(image14, R.String.image_url14, 14);
loadImage(image15, R.String.image_url15, 15);
loadImage(image16, R.String.image_url16, 16);
loadImage(image17, R.String.image_url17, 17);
loadImage(image18, R.String.image_url18, 18);
loadImage(image19, R.String.image_url19, 19);
loadImage(image20, R.String.image_url20, 20);
}
}
答案 0 :(得分:5)
我不认为这是泄密。
当Android“展开”您的图像(即将其解码为位图)时,每个像素将使用4个字节。计算像素数,将其乘以4再乘以20(图像数量),您可能会接近100mb的数字。例如,如果您的图像具有1,000,000像素分辨率,那么它将是1,000,000 x 4 x 20 = 80mb。
您不应该一次加载所有这些图像。使用某种LRU缓存或类似的(或者使用Universal Image Loader库来处理缓存)并且只在需要时加载位图。
我强烈建议您阅读本文并密切关注其建议: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
答案 1 :(得分:1)
我将这个用于很多图像并且工作正常
private class LoadImage extends AsyncTask<String, String, Bitmap> {
@Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog((Main)context);
pDialog.setMessage("Loading Image ....");
pDialog.show();
}
protected Bitmap doInBackground(String... args) {
Log.i("doInBack 1","length = 1 ");
try {
Bitmap positivo = BitmapFactory.decodeStream((InputStream)new URL(args[0]).getContent());
} catch (Exception e) {
e.printStackTrace();
}
return positivo;
}
protected void onPostExecute(Bitmap image) {
if(image != null){
//*bitmap is the bitmap u change each time
bitmap = image;
invalidate();
pDialog.dismiss();
}
}
如何调用它?,当你想用url
改变图像时写下这个new LoadImage().execute("https://yourimage.jpg");