安卓:内存错误的使用了位图时 [英] Android: out of memory error when using bitmaps
问题描述
我经常收到内存不足的错误在我的应用程序。我相信这与我从服务器上下载的位图的事情。任何想法,为什么?
**在我的活性的方法,设置了ListView的:**私有类NewsFeedArrayAdapter扩展ArrayAdapter< AnimalLocationLog> { ArrayList的< AnimalLocationLog>物体;
上下文语境;
ArrayList的<串GT;网址;
ImageDownloader下载; 公共NewsFeedArrayAdapter(上下文的背景下,INT textViewResourceId,ArrayList的< AnimalLocationLog>对象的ArrayList<串GT;的网址){
超(背景下,textViewResourceId,对象);
this.context =背景;
this.objects =物体;
this.urls =网址;
下载=新ImageDownloader();
} @覆盖
公共查看getView(INT位置,查看convertView,父母的ViewGroup){
LayoutInflater吹气=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
查看rowView = inflater.inflate(R.layout.list_single,父母,假); AnimalLocationLog电流= objects.get(位置); ImageView的图像=(ImageView的)rowView.findViewById(R.id.icon);
TextView的FIRSTLINE =(TextView中)rowView.findViewById(R.id.firstline);
TextView的secondline =(TextView中)rowView.findViewById(R.id.secondline); //下载外部图像
downloader.download(urls.get(仓位14%),图像); firstline.setText(current.getSpecies());
secondline.setText(花斑+ current.getDateTime()的toString(YYYY-MM-DD H:M)); 返回rowView;
}
** ImageDownloader.java:** 公共类ImageDownloader { 地图<弦乐,位图> imageCache; 公共ImageDownloader(){
imageCache =新的HashMap<弦乐,位图>(); } //下载功能
公共无效下载(字符串URL,ImageView的ImageView的){
如果(cancelPotentialDownload(URL,ImageView的)){ //缓存code就在这里
字符串文件名=将String.valueOf(url.hash code());
文件f =新的文件(getCacheDirectory(imageView.getContext()),文件名); //是在我们的记忆缓存中的位图?
位图位图= NULL; 位=(位图)imageCache.get(f.getPath()); 如果(位图== NULL){ 位= BitmapFactory.de codeFILE(f.getPath()); 如果(位图!= NULL){
imageCache.put(f.getPath(),位图);
} }
//没有?下载它
如果(位图== NULL){
BitmapDownloaderTask任务=新BitmapDownloaderTask(ImageView的);
DownloadedDrawable downloadedDrawable =新DownloadedDrawable(任务);
imageView.setImageDrawable(downloadedDrawable);
task.execute(URL);
}其他{
//是?设置图像
imageView.setImageBitmap(位图);
}
}
} //取消下载(仅供内部使用)
私有静态布尔cancelPotentialDownload(字符串URL,ImageView的ImageView的){
BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(ImageView的); 如果(bitmapDownloaderTask!= NULL){
字符串bitmapUrl = bitmapDownloaderTask.url;
如果((bitmapUrl == NULL)||(!bitmapUrl.equals(URL))){
bitmapDownloaderTask.cancel(真);
}其他{
//相同的URL已经被下载。
返回false;
}
}
返回true;
} //如果存在的ImageView的得到现有下载
私有静态BitmapDownloaderTask getBitmapDownloaderTask(ImageView的ImageView的){
如果(ImageView的!= NULL){
可绘制可绘制= imageView.getDrawable();
如果(绘制的instanceof DownloadedDrawable){
DownloadedDrawable downloadedDrawable =(DownloadedDrawable)绘制;
返回downloadedDrawable.getBitmapDownloaderTask();
}
}
返回null;
} //我们的缓存功能
//查找目录保存缓存图像
私有静态文件getCacheDirectory(上下文的背景下){
串sdState = android.os.Environment.getExternalStorageState();
文件cacheDir; 如果(sdState.equals(android.os.Environment.MEDIA_MOUNTED)){
文件sdDir = android.os.Environment.getExternalStorageDirectory(); // TODO:在此处更改diretcory
cacheDir =新的文件(sdDir,数据/ TAC / imagess);
}
其他
cacheDir = context.getCacheDir(); 如果(!cacheDir.exists())
cacheDir.mkdirs();
返回cacheDir;
} 私人无效WriteFile的(BMP位图,文件f){
FileOutputStream中走出= NULL; 尝试{
OUT =新的FileOutputStream(F);
bmp.com preSS(Bitmap.Com pressFormat.PNG,80出);
}赶上(例外五){
e.printStackTrace();
}
最后{
尝试{如果out.close()(满分!= NULL); }
赶上(例外前){}
}
}
/////////////////////// //下载的AsyncTask
公共类BitmapDownloaderTask扩展的AsyncTask<弦乐,太虚,位图> {
私人字符串URL;
私人最终的WeakReference< ImageView的> imageViewReference; 公共BitmapDownloaderTask(ImageView的ImageView的){
imageViewReference =新的WeakReference< ImageView的>(ImageView的);
} @覆盖
//实际的下载方法,在任务线程中运行
保护位图doInBackground(字符串... PARAMS){
// PARAMS来自execute()调用:PARAMS [0]是的URL。
URL =(字符串)PARAMS [0];
返回downloadBitmap(PARAMS [0]);
} @覆盖
//一旦图像被下载,它关联到的ImageView
保护无效onPostExecute(位图位图){
如果(isCancelled()){
位= NULL;
} 如果(imageViewReference!= NULL){
ImageView的ImageView的= imageViewReference.get();
BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(ImageView的);
//改变位图只有在这个过程中仍与它相关联
如果(这种== bitmapDownloaderTask){
imageView.setImageBitmap(位图); //缓存图片
字符串文件名=将String.valueOf(url.hash code());
文件f =新的文件(getCacheDirectory(imageView.getContext()),文件名); imageCache.put(f.getPath(),位图); 写文件(位图,F);
}
}
}
} 静态类DownloadedDrawable扩展ColorDrawable {
私人最终的WeakReference< BitmapDownloaderTask> bitmapDownloaderTaskReference; 公共DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask){
超(Color.BLACK);
bitmapDownloaderTaskReference =
新的WeakReference< BitmapDownloaderTask>(bitmapDownloaderTask);
} 公共BitmapDownloaderTask getBitmapDownloaderTask(){
返回bitmapDownloaderTaskReference.get();
}
} //实际的下载code
静态位图downloadBitmap(字符串URL){
的HttpParams PARAMS =新BasicHttpParams();
params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION,HttpVersion.HTTP_1_1);
HttpClient的客户端=新DefaultHttpClient(PARAMS);
最终HTTPGET调用getRequest =新HTTPGET(URL); 尝试{
HTT presponse响应= client.execute(调用getRequest);
。最终诠释状态code = response.getStatusLine()的getStatus code();
如果(状态code!= HttpStatus.SC_OK){
Log.w(ImageDownloader,错误+状态code +,同时检索从位图+网址);
返回null;
} 最终HttpEntity实体= response.getEntity();
如果(实体!= NULL){
为InputStream的InputStream = NULL;
尝试{
的InputStream = entity.getContent();
最后的位图位图= BitmapFactory.de codeStream(InputStream的);
返回位图;
} {最后
如果(的InputStream!= NULL){
inputStream.close();
}
entity.consumeContent();
}
}
}赶上(例外五){
//可以提供IOException异常或IllegalStateException异常更明确的错误信息
getRequest.abort();
; Log.w(ImageDownloader+ URL + e.toString()错误而来自检索的位图)
} {最后
如果(客户端!= NULL){
//client.close();
}
}
返回null;
}
}
如果您有高分辨率的图像,你应该扩展他们失望。参见下加载缩小版本到内存的话题。结果
http://developer.android.com/training/displaying-bitmaps/load -bitmap.html 结果
内存不足错误的Android 的
在如何避免它们:结果
<一href=\"http://stackoverflow.com/questions/19151719/how-to-avoid-out-of-memory-error-while-using-bitmap-in-android\">how以避免内存不足的错误,而在Android的使用位图
对于大略介绍:结果
的http://blogs.innovationm.com/android-out-of-memory-error-causes-solution-and-best-practices/
http://android-developers.blogspot.de/2009/01 /avoiding-memory-leaks.html
i often get out of memory errors in my app. I believe it has to do with the bitmaps i download from the server. Any ideas why?
**A method in my activity that sets up ListView:**
private class NewsFeedArrayAdapter extends ArrayAdapter<AnimalLocationLog> {
ArrayList<AnimalLocationLog> objects;
Context context;
ArrayList<String> urls;
ImageDownloader downloader;
public NewsFeedArrayAdapter(Context context, int textViewResourceId, ArrayList<AnimalLocationLog> objects, ArrayList<String> urls) {
super(context, textViewResourceId, objects);
this.context = context;
this.objects = objects;
this.urls = urls;
downloader = new ImageDownloader();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.list_single, parent, false);
AnimalLocationLog current = objects.get(position);
ImageView image = (ImageView) rowView.findViewById(R.id.icon);
TextView firstline = (TextView) rowView.findViewById(R.id.firstline);
TextView secondline = (TextView) rowView.findViewById(R.id.secondline);
// Download external images
downloader.download(urls.get(position % 14), image);
firstline.setText(current.getSpecies());
secondline.setText("Spotted " + current.getDateTime().toString("yyyy-MM-dd H:m"));
return rowView;
}
**ImageDownloader.java:**
public class ImageDownloader {
Map<String,Bitmap> imageCache;
public ImageDownloader(){
imageCache = new HashMap<String, Bitmap>();
}
//download function
public void download(String url, ImageView imageView) {
if (cancelPotentialDownload(url, imageView)) {
//Caching code right here
String filename = String.valueOf(url.hashCode());
File f = new File(getCacheDirectory(imageView.getContext()), filename);
// Is the bitmap in our memory cache?
Bitmap bitmap = null;
bitmap = (Bitmap)imageCache.get(f.getPath());
if(bitmap == null){
bitmap = BitmapFactory.decodeFile(f.getPath());
if(bitmap != null){
imageCache.put(f.getPath(), bitmap);
}
}
//No? download it
if(bitmap == null){
BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);
DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task);
imageView.setImageDrawable(downloadedDrawable);
task.execute(url);
}else{
//Yes? set the image
imageView.setImageBitmap(bitmap);
}
}
}
//cancel a download (internal only)
private static boolean cancelPotentialDownload(String url, ImageView imageView) {
BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
if (bitmapDownloaderTask != null) {
String bitmapUrl = bitmapDownloaderTask.url;
if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
bitmapDownloaderTask.cancel(true);
} else {
// The same URL is already being downloaded.
return false;
}
}
return true;
}
//gets an existing download if one exists for the imageview
private static BitmapDownloaderTask getBitmapDownloaderTask(ImageView imageView) {
if (imageView != null) {
Drawable drawable = imageView.getDrawable();
if (drawable instanceof DownloadedDrawable) {
DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable;
return downloadedDrawable.getBitmapDownloaderTask();
}
}
return null;
}
//our caching functions
// Find the dir to save cached images
private static File getCacheDirectory(Context context){
String sdState = android.os.Environment.getExternalStorageState();
File cacheDir;
if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) {
File sdDir = android.os.Environment.getExternalStorageDirectory();
//TODO : Change your diretcory here
cacheDir = new File(sdDir,"data/tac/imagess");
}
else
cacheDir = context.getCacheDir();
if(!cacheDir.exists())
cacheDir.mkdirs();
return cacheDir;
}
private void writeFile(Bitmap bmp, File f) {
FileOutputStream out = null;
try {
out = new FileOutputStream(f);
bmp.compress(Bitmap.CompressFormat.PNG, 80, out);
} catch (Exception e) {
e.printStackTrace();
}
finally {
try { if (out != null ) out.close(); }
catch(Exception ex) {}
}
}
///////////////////////
//download asynctask
public class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
private String url;
private final WeakReference<ImageView> imageViewReference;
public BitmapDownloaderTask(ImageView imageView) {
imageViewReference = new WeakReference<ImageView>(imageView);
}
@Override
// Actual download method, run in the task thread
protected Bitmap doInBackground(String... params) {
// params comes from the execute() call: params[0] is the url.
url = (String)params[0];
return downloadBitmap(params[0]);
}
@Override
// Once the image is downloaded, associates it to the imageView
protected void onPostExecute(Bitmap bitmap) {
if (isCancelled()) {
bitmap = null;
}
if (imageViewReference != null) {
ImageView imageView = imageViewReference.get();
BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
// Change bitmap only if this process is still associated with it
if (this == bitmapDownloaderTask) {
imageView.setImageBitmap(bitmap);
//cache the image
String filename = String.valueOf(url.hashCode());
File f = new File(getCacheDirectory(imageView.getContext()), filename);
imageCache.put(f.getPath(), bitmap);
writeFile(bitmap, f);
}
}
}
}
static class DownloadedDrawable extends ColorDrawable {
private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;
public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
super(Color.BLACK);
bitmapDownloaderTaskReference =
new WeakReference<BitmapDownloaderTask>(bitmapDownloaderTask);
}
public BitmapDownloaderTask getBitmapDownloaderTask() {
return bitmapDownloaderTaskReference.get();
}
}
//the actual download code
static Bitmap downloadBitmap(String url) {
HttpParams params = new BasicHttpParams();
params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
HttpClient client = new DefaultHttpClient(params);
final HttpGet getRequest = new HttpGet(url);
try {
HttpResponse response = client.execute(getRequest);
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url);
return null;
}
final HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = null;
try {
inputStream = entity.getContent();
final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;
} finally {
if (inputStream != null) {
inputStream.close();
}
entity.consumeContent();
}
}
} catch (Exception e) {
// Could provide a more explicit error message for IOException or IllegalStateException
getRequest.abort();
Log.w("ImageDownloader", "Error while retrieving bitmap from " + url + e.toString());
} finally {
if (client != null) {
//client.close();
}
}
return null;
}
}
If you have high resolution image , you should scale them down. See the topic under Load a Scaled Down Version into Memory.
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
Out of memory error android
On how to avoid them:
how to avoid out of memory error while using bitmap in android
For an oveview:
http://blogs.innovationm.com/android-out-of-memory-error-causes-solution-and-best-practices/
http://android-developers.blogspot.de/2009/01/avoiding-memory-leaks.html
这篇关于安卓:内存错误的使用了位图时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!