问题
In my application i am downloading images from the web. i got the out memory exception. somebody suggests that clear heap using the following code. But still i am facing the out of memory exception.can anybody help me. The following method is called when the activity is started. Here I refer to this link
public void onStart()
{
super.onStart();
//Handling the out of memory exception
logHeap(this.getClass());
}
public static void logHeap(Class clazz) {
Double allocated = new Double(Debug.getNativeHeapAllocatedSize())/new Double((1048576));
Double available = new Double(Debug.getNativeHeapSize()/1048576.0);
Double free = new Double(Debug.getNativeHeapFreeSize()/1048576.0);
DecimalFormat df = new DecimalFormat();
df.setMaximumFractionDigits(2);
df.setMinimumFractionDigits(2);
System.out.println("debug. =================================");
System.out.println("debug.heap native: allocated " + df.format(allocated) + "MB of " + df.format(available) + "MB (" + df.format(free) + "MB free) in [" + clazz.getName().replaceAll("com.myapp.android.","") + "]");
System.out.println("debug.memory: allocated: " + df.format(new Double(Runtime.getRuntime().totalMemory()/1048576)) + "MB of " + df.format(new Double(Runtime.getRuntime().maxMemory()/1048576))+ "MB (" + df.format(new Double(Runtime.getRuntime().freeMemory()/1048576)) +"MB free)");
System.gc();
System.gc();
}
My Code:
@Override
public View getView(final int position, View convertView, ViewGroup parent)
{
ViewHolder holder;
convertView = null;
if (convertView == null)
{
convertView = mInflater.inflate(R.layout.giftcategorieslist, null);
holder = new ViewHolder();
holder.imgitem = (ImageView)convertView.findViewById(R.id.imgitem);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
final CategoryData Item = arItems.get(position);
strItemrow = Item.toString();
try
{
if(Item.dwgImage == null)
{
if(Item.bImageDownLoaded == 0)
{
holder.progress.setVisibility(View.VISIBLE);
DownLoadImageInAThreadHandler(Item, holder);
}
else
{
int idNoImage = R.drawable.giftsuggestionsnoimage;
Drawable dwgImgLoading = GiftCategories.this.getResources().getDrawable(idNoImage);
holder.imgitem.setImageDrawable(dwgImgLoading);
holder.imgitem.setVisibility(View.VISIBLE);
holder.progress.setVisibility(View.GONE);
}
}
else
{
holder.imgitem.setImageDrawable(Item.dwgImage);
holder.imgitem.setVisibility(View.VISIBLE);
holder.progress.setVisibility(View.GONE);
}
}
catch(Exception e)
{
System.out.println("Exception in Downloading image : " + e.getMessage());
}
return convertView;
}
public void DownLoadImageInAThreadHandler(final CategoryData Item, final ViewHolder holder)
{
nImageDownLoads++;
System.out.println("The images being downloaded :" + nImageDownLoads);
final Handler handler = new Handler()
{
@Override public void handleMessage(Message message)
{
holder.imgitem.setImageDrawable((Drawable) message.obj);
holder.imgitem.setVisibility(View.VISIBLE);
holder.progress.setVisibility(View.GONE);
}
};
//Thread for getting the attributes values
Thread t = new Thread()
{
public void run()
{
try
{
Item.bImageDownLoaded = 2;
System.out.println("Downloading image : " + Item.ImageUrl);
InputStream is = fetch(Item.ImageUrl);
Drawable drawable = Drawable.createFromStream(is, "src");
nImageDownLoads--;
System.out.println("Downloaded image :" + Item.ImageUrl);
System.out.println("Remaining images for downloading: " + nImageDownLoads);
if(drawable != null)
{
Item.dwgImage = drawable;
Item.bImageDownLoaded = 1;
//Send the message to the handler
Message message = handler.obtainMessage(1, drawable);
handler.sendMessage(message);
}
else
{
int idNoImage = R.drawable.giftsuggestionsnoimage;
Drawable dwgNoImg = GiftCategories.this.getResources().getDrawable(idNoImage);
//Send the message to the handler
Message message = handler.obtainMessage(1, dwgNoImg);
handler.sendMessage(message);
}
}
catch(Exception exp)
{
System.out.println("Exception in DownLoadImageInAThread : " + exp.getMessage());
}
}
};
t.start();
}
private InputStream fetch(String urlString) throws MalformedURLException, IOException
{
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet request = new HttpGet(urlString);
HttpResponse response = httpClient.execute(request);
return response.getEntity().getContent();
}
class ViewHolder
{
ImageView imgitem;
}
}
}
thanks
回答1:
You are saving all the images in the heap!
Probably if you do not scroll down you will not get the out of memory error
Try to
- save the images to file when downloaded
- let your Item objects hold the path of the image and not the whole
Drawable
CODE
This is a function I created that will take a url from you and it will return a drawable! It will save it to a file and get it if it exists
If not, it will download it and return the drawable.
In this case, all you have to do is save the url in Item
and give it to this function when drawable is needed.
/**
* Pass in an image url to get a drawable object
*
* @return a drawable object
*/
private static Drawable getDrawableFromUrl(final String url) {
String filename = url;
filename = filename.replace("/", "+");
filename = filename.replace(":", "+");
filename = filename.replace("~", "s");
final File file = new File(Environment.getExternalStorageDirectory()
+ File.separator + filename);
boolean exists = file.exists();
if (!exists) {
try {
URL myFileUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) myFileUrl
.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
final Bitmap result = BitmapFactory.decodeStream(is);
is.close();
new Thread() {
public void run() {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
result.compress(Bitmap.CompressFormat.JPEG, 40, bytes);
try {
if (file.createNewFile()){
//
}
else{
//
}
FileOutputStream fo;
fo = new FileOutputStream(file);
fo.write(bytes.toByteArray());
fo.flush();
fo.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
BitmapDrawable returnResult = new BitmapDrawable(result);
return returnResult;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
else {
return new BitmapDrawable(BitmapFactory.decodeFile(file.toString()));
}
}
回答2:
You could try to run a garbage collection(system.gc()) before you start this process. While it may work, this is not the best solution as gc will not always run just because you call it. Normally if you have to call gc in your program it means your doing something wrong. I would try to move the images to the file system as suggested above.
来源:https://stackoverflow.com/questions/7282334/android-out-of-memory