我试图创建使用从服务器上下载图像,并将其显示成列表视图的应用程序。 我提出的问题是内存泄漏,使我的应用程序崩溃。 我是在Android的博客搜索像这样的链接 ,它显示出一个伟大的想法,但仍不足以与多线程做。 机器人的一些设备可以使用它,但一些设备只能在单个线程处理,有时不能在所有的工作。
我的应用程序有许多活动,他们每个人都有需要显示的图像快速地一个ListView。 通过谷歌IO 2012,他们使用缓冲区来保存原始图像,以SD卡,它解决问题的泄漏的内存,但它使加载很慢,因为需要下载的图片太大。
我的问题是: 有没有办法与写入图像到SD卡扩展起来的形象? 我找出一些可能的解决方案是在InputStream对象使用跳过字节,我能找到宽度和高度也每次我需要下载图像的像素位。
下面的代码是用在谷歌IO 2012,并将其与多线程很好地工作,在我来说,我有4个线程在后台运行。
private void downloadAndWriteFile(final String url, final File file) throws OutOfMemoryError {
BufferedOutputStream out = null;
try {
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
conn.setDoInput(true);
conn.connect();
final InputStream in = new BufferedInputStream(conn.getInputStream(), IO_BUFFER_SIZE_BYTES); // buffer size 1KB
out = new BufferedOutputStream(new FileOutputStream(file), IO_BUFFER_SIZE_BYTES);
int b;
while ((b = in.read()) != -1) {
out.write(b);
}
out.close();
conn.disconnect();
}
catch (Exception e) {
Log.e(TAG, "!!downloadAndWriteFile " + e.getMessage());
file.delete();
}
}
1)设定图像进行释放与此位图相关联的原生对象之前使用下面的代码,并清除参考像素数据。 它只是允许它被垃圾收集,如果没有其他的引用。
BitmapDrawable drawable = (BitmapDrawable) myImage.getDrawable();
Bitmap bitmap = drawable.getBitmap();
if (bitmap != null)
{
bitmap.recycle();
}
2)使用此方法来减小存储器位图的大小:
/**
* decodes image and scales it to reduce memory consumption
*
* @param file
* @param requiredSize
* @return
*/
public static Bitmap decodeFile(File file, int requiredSize) {
try {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(file), null, o);
// The new size we want to scale to
// Find the correct scale value. It should be the power of 2.
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true) {
if (width_tmp / 2 < requiredSize
|| height_tmp / 2 < requiredSize)
break;
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(file),
null, o2);
return bmp;
} catch (FileNotFoundException e) {
} finally {
System.gc();
}
return null;
}
您可以使用此。
private void downloadImagesToSdCard(String downloadUrl,String imageName) {
try {
URL url = new URL(downloadUrl); //you can write here any link
File myDir = new File("/sdcard"+"/"+Constants.imageFolder);
//Something like ("/sdcard/file.mp3")
if (!myDir.exists()) {
myDir.mkdir();
Log.v("", "inside mkdir");
}
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = imageName;
File file = new File (myDir, fname);
if (file.exists ()) file.delete ();
/* Open a connection to that URL. */
URLConnection ucon = url.openConnection();
InputStream inputStream = null;
HttpURLConnection httpConn = (HttpURLConnection)ucon;
httpConn.setRequestMethod("GET");
httpConn.connect();
if (httpConn.getResponseCode() == HttpURLConnection.HTTP_OK) {
inputStream = httpConn.getInputStream();
}
/*
* Define InputStreams to read from the URLConnection.
*/
// InputStream is = ucon.getInputStream();
/*
* Read bytes to the Buffer until there is nothing more to read(-1).
*/
FileOutputStream fos = new FileOutputStream(file);
int size = 1024*1024;
byte[] buf = new byte[size];
int byteRead;
while (((byteRead = inputStream.read(buf)) != -1)) {
fos.write(buf, 0, byteRead);
bytesDownloaded += byteRead;
}
/* Convert the Bytes read to a String. */
fos.close();
} catch(IOException io) {
networkException = true;
continueRestore = false;
} catch(Exception e) {
continueRestore = false;
e.printStackTrace();
}
}
此代码下载图像,而不使用位图的工厂,它不是在模拟器工作,使用任何Android手机
package com.example.filedownload;
import org.apache.http.util.ByteArrayBuffer;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.content.*;
import android.app.*;
import android.net.*;
import android.app.DownloadManager.Request;
import android.os.Environment;
public class MainActivity extends Activity {
public long reference;
BroadcastReceiver receiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button=(Button)findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
String file = "http://tmacfitness.com/wp-content/uploads/2013/04/Beauty-of-nature-random-4884759-1280-800.jpg";
String serviceString = Context.DOWNLOAD_SERVICE;
DownloadManager downloadManager;
downloadManager = (DownloadManager)getSystemService(serviceString);
Uri uri = Uri.parse(file);
DownloadManager.Request request ;
request = new Request(uri);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "accel.jpg");
reference = downloadManager.enqueue(request);
}
});
IntentFilter filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
long ref = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
if (reference == ref) {
setContentView(R.layout.finalscreen);
unregister();
}
}
};
registerReceiver(receiver, filter);
}
public void unregister(){
unregisterReceiver(receiver);
}
}
activity_main.xml中
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<TableLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true" >
<TableRow
android:id="@+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</TableRow>
<TableRow
android:id="@+id/tableRow2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<CheckedTextView
android:id="@+id/checkedTextView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Accel" />
</TableRow>
<TableRow
android:id="@+id/tableRow3"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</TableRow>
<TableRow
android:id="@+id/tableRow4"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</TableRow>
</TableLayout>
</RelativeLayout>
finalscreen.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="270dp"
android:layout_height="wrap_content"
android:layout_weight="2.12"
android:text="DOWNLOAD COMPLETED" />
</LinearLayout>
文章来源: Android download image from server and save to sdcard without using BitmapFactory