1

this is my code. the objective when started is to grab images into a dynamic list view, basically like a RSS feed from my own database. what i did is grab to http link and covert it into a drawable then from there setting the drawable into the imageview from the dynamic list view.

Here is the problem. When i enter the app, first load is okay. But when i hit the refresh button i will get "Out of memory on a 633632-bytes allocation" error follow by a more detail version of the error with all the heap size allocated, limits.

how can i go around this?

package com.whatstherex.sam;

import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Vector;

import org.apache.http.NameValuePair;

import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.StrictMode;
import android.view.View;
import android.widget.Button;
import android.widget.ListView;

public class Snapshots extends Activity implements View.OnClickListener {
Button bBackSnapshots, bRefreshSnapshots, bSnapshotsSnapshots;
ListView snapshotsDynamicListView;
Vector<SnapshotsData> snapshotsInputs = new Vector<SnapshotsData>();
SnapshotsCustomFeedAdaptor adaptor;
String username, snapshotsList;
String[] feed;

@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
    setContentView(R.layout.snapshots);

    initialize();
}

public void initialize() {
    bBackSnapshots = (Button) findViewById(R.id.bBackSnapshots);
    bRefreshSnapshots = (Button) findViewById(R.id.bRefreshSnapshots);
    bSnapshotsSnapshots = (Button) findViewById(R.id.bSnapshotsSnapshots);

    bBackSnapshots.setOnClickListener(this);
    bRefreshSnapshots.setOnClickListener(this);
    bSnapshotsSnapshots.setOnClickListener(this);                           

    getInformations();
}

private AsyncTask<String, Void, String> task;
private AsyncTask<String, Void, String> task1;
private AsyncTask<String, Void, InputStream[]> task2;

public void getInformations(){
    task = new AsyncTask<String, Void, String>() {
        ProgressDialog dialog;
        Bundle bundle;
        String res;
        @Override 
        protected void onPreExecute(){
            dialog = new ProgressDialog(Snapshots.this, ProgressDialog.STYLE_SPINNER);
            dialog.setMessage("Loading Data...");           
            dialog.setCancelable(false);
            dialog.setCanceledOnTouchOutside(false);    

            dialog.show();
        }

        @Override
        protected String doInBackground(String... arg0) {
            bundle = getIntent().getExtras();
            res = bundle.getString("Username");
            return res;
        }

        @Override
        protected void onPostExecute(String result) {
            dialog.dismiss();
            username = result;      

            task1 = new AsyncTask<String, Void, String>() {
                ProgressDialog dialog1;
                ArrayList<NameValuePair> postParameters;
                String response1;
                String res1;
                @Override 
                protected void onPreExecute(){
                    snapshotsDynamicListView = (ListView) findViewById(R.id.lvSnapshots);                       

                    postParameters = new ArrayList<NameValuePair>();

                    dialog1 = new ProgressDialog(Snapshots.this, ProgressDialog.STYLE_SPINNER);
                    dialog1.setMessage("Loading Data...");          
                    dialog1.setCancelable(false);
                    dialog1.setCanceledOnTouchOutside(false);   

                    dialog1.show();
                }

                @Override
                protected String doInBackground(String... arg0) {
                    try {
                        response1 = CustomHttpClient.executeHttpPost("http://whatstherex.info/getS.php", postParameters);

                        res1 = response1.toString();

                        res1 = res1.replaceAll("null", "");

                        snapshotsList = res1.toString();

                        return snapshotsList;
                    }catch(Exception e){
                        res1 = e.toString();
                        return res1;
                    }
                }

                @Override
                protected void onPostExecute(String result1) {
                    feed = result1.split("[_]");

                    task2 = new AsyncTask<String, Void, InputStream[]>() {          
                        ProgressDialog dialog2;
                        InputStream[] is = new InputStream[50];
                        Drawable[] d = new Drawable[50];
                        String[] res2 = new String[50];
                        Drawable p4, p5, p9, p10, p14, p15, p19, p20, p24, p25, p29, p30, p34, p35, p39, p40, p44, p45, p49, p50, p54, p55, p59, p60, p64, p65, p69, p70, p74, p75, p79, p80, p84, p85, p89, p90, p94, p95, p99, p100, p104, p105, p109, p110, p114, p115, p119, p120, p124, p125;
                        @Override 
                        protected void onPreExecute(){
                            dialog2 = new ProgressDialog(Snapshots.this, ProgressDialog.STYLE_SPINNER);
                            dialog2.setMessage("Loading Data...");          
                            dialog2.setCancelable(false);
                            dialog2.setCanceledOnTouchOutside(false);   

                            dialog2.show();
                        }

                        @Override
                        protected InputStream[] doInBackground(String... src) {
                            for(int i = 0; i<50; i++){
                                res2[i] = src[i];
                            }
                            for(int i = 0; i<50; i++){
                                try {
                                    is[i] = (InputStream) new URL(res2[i]).getContent();                                        
                                } catch (Exception e) {
                                    e.toString();
                                }
                            }
                                return is;
                        }

                        @Override
                        protected void onPostExecute(InputStream[] result2) {
                            for(int i = 0; i<50; i++){
                                try {
                                    d[i] = Drawable.createFromStream(result2[i], "src name");
                                } catch (Exception e) {
                                    e.toString();
                                }
                            }

                            p4 = d[0];
                            p5 = d[1];
                            p9 = d[2];
                            p10 = d[3];
                            p14 = d[4];
                            p15 = d[5];
                            p19 = d[6];
                            p20 = d[7];
                            p24 = d[8];
                            p25 = d[9];
                            p29 = d[10];
                            p30 = d[11];
                            p34 = d[12];
                            p35 = d[13];
                            p39 = d[14];
                            p40 = d[15];
                            p44 = d[16];
                            p45 = d[17];
                            p49 = d[18];
                            p50 = d[19];
                            p54 = d[20];
                            p55 = d[21];
                            p59 = d[22];
                            p60 = d[23];
                            p64 = d[24];
                            p65 = d[25];
                            p69 = d[26];
                            p70 = d[27];
                            p74 = d[28];
                            p75 = d[29];
                            p79 = d[30];
                            p80 = d[31];
                            p84 = d[32];
                            p85 = d[33];
                            p89 = d[34];
                            p90 = d[35];
                            p94 = d[36];
                            p95 = d[37];
                            p99 = d[38];
                            p100 = d[39];
                            p104 = d[40];
                            p105 = d[41];
                            p109 = d[42];
                            p110 = d[43];
                            p114 = d[44];
                            p115 = d[45];
                            p119 = d[46];
                            p120 = d[47];
                            p124 = d[48];
                            p125 = d[49];

                            snapshotsInputs.add(new SnapshotsData(feed[1].toString(), feed[2].toString(), feed[3].toString(), p4, p5));
                            snapshotsInputs.add(new SnapshotsData(feed[6].toString(), feed[7].toString(), feed[8].toString(), p9, p10));
                            snapshotsInputs.add(new SnapshotsData(feed[11].toString(), feed[12].toString(), feed[13].toString(), p14, p15));
                            snapshotsInputs.add(new SnapshotsData(feed[16].toString(), feed[17].toString(), feed[18].toString(), p19, p20));
                            snapshotsInputs.add(new SnapshotsData(feed[21].toString(), feed[22].toString(), feed[23].toString(), p24, p25));
                            snapshotsInputs.add(new SnapshotsData(feed[26].toString(), feed[27].toString(), feed[28].toString(), p29, p30));
                            snapshotsInputs.add(new SnapshotsData(feed[31].toString(), feed[32].toString(), feed[33].toString(), p34, p35));
                            snapshotsInputs.add(new SnapshotsData(feed[36].toString(), feed[37].toString(), feed[38].toString(), p39, p40));
                            snapshotsInputs.add(new SnapshotsData(feed[41].toString(), feed[42].toString(), feed[43].toString(), p44, p45));
                            snapshotsInputs.add(new SnapshotsData(feed[46].toString(), feed[47].toString(), feed[48].toString(), p49, p50));
                            snapshotsInputs.add(new SnapshotsData(feed[51].toString(), feed[52].toString(), feed[53].toString(), p54, p55));
                            snapshotsInputs.add(new SnapshotsData(feed[56].toString(), feed[57].toString(), feed[58].toString(), p59, p60));
                            snapshotsInputs.add(new SnapshotsData(feed[61].toString(), feed[62].toString(), feed[63].toString(), p64, p65));
                            snapshotsInputs.add(new SnapshotsData(feed[66].toString(), feed[67].toString(), feed[68].toString(), p69, p70));
                            snapshotsInputs.add(new SnapshotsData(feed[71].toString(), feed[72].toString(), feed[73].toString(), p74, p75));
                            snapshotsInputs.add(new SnapshotsData(feed[76].toString(), feed[77].toString(), feed[78].toString(), p79, p80));
                            snapshotsInputs.add(new SnapshotsData(feed[81].toString(), feed[82].toString(), feed[83].toString(), p84, p85));
                            snapshotsInputs.add(new SnapshotsData(feed[86].toString(), feed[87].toString(), feed[88].toString(), p89, p90));
                            snapshotsInputs.add(new SnapshotsData(feed[91].toString(), feed[92].toString(), feed[93].toString(), p94, p95));
                            snapshotsInputs.add(new SnapshotsData(feed[96].toString(), feed[97].toString(), feed[98].toString(), p99, p100));
                            snapshotsInputs.add(new SnapshotsData(feed[101].toString(), feed[102].toString(), feed[103].toString(), p104, p105));
                            snapshotsInputs.add(new SnapshotsData(feed[106].toString(), feed[107].toString(), feed[108].toString(), p109, p110));
                            snapshotsInputs.add(new SnapshotsData(feed[111].toString(), feed[112].toString(), feed[113].toString(), p114, p115));
                            snapshotsInputs.add(new SnapshotsData(feed[116].toString(), feed[117].toString(), feed[118].toString(), p119, p120));
                            snapshotsInputs.add(new SnapshotsData(feed[121].toString(), feed[122].toString(), feed[123].toString(), p124, p125));

                            adaptor = new SnapshotsCustomFeedAdaptor(Snapshots.this, R.layout.snapshotsdata, snapshotsInputs);
                            snapshotsDynamicListView.setAdapter(adaptor);

                            dialog2.dismiss();  
                        }
                    };                      
                    task2.execute(feed[4], feed[5], feed[9], feed[10], feed[14], feed[15], feed[19], feed[20], feed[24], feed[25], feed[29], feed[30], 
                            feed[34], feed[35], feed[39], feed[40], feed[44], feed[45], feed[49], feed[50], feed[54], feed[55], feed[59], feed[60], 
                            feed[64], feed[65], feed[69], feed[70], feed[74], feed[75], feed[79], feed[80], feed[84], feed[85], feed[89], feed[90], 
                            feed[94], feed[95], feed[99], feed[100], feed[104], feed[105], feed[109], feed[110], feed[114], feed[115], feed[119], 
                            feed[120], feed[124], feed[125]);

                    dialog1.dismiss();
                }
            };
            task1.execute();
        }
    };
    task.execute();
}

@Override
public void onClick(View v) {
    switch (v.getId()){
    case R.id.bBackSnapshots:
        finish();
        break;
    case R.id.bRefreshSnapshots:
        finish();
        startActivity(getIntent());
        break;
    case R.id.bSnapshotsSnapshots:

        break;
    }
}       
}
Sam
  • 33
  • 1
  • 7

2 Answers2

2

Why are you adding loads of Drawables into memory. Thats the problem right there. The app memory limit is only ~16MB (changes per device). Yet it looks like you are loading 100 drawables, most likely exceeding this.

You should only load the drawables when the list requests a new view. It will dispose of it when its not needed.

EDIT:

What you could do is override adapter class. And specify a url to image. Then in the getView method, load your image from the given Url. This handles the async loading, on demand.

see for example:

https://stackoverflow.com/a/3068012/940834

http://www.androidhive.info/2012/02/android-custom-listview-with-image-and-text/

Community
  • 1
  • 1
IAmGroot
  • 13,760
  • 18
  • 84
  • 154
  • Actually there is only 50 drawable reason being every set there will be a profile pic and a "uploaded photo". how do i load when requested? – Sam Jan 13 '13 at 11:02
  • @Sam see edit. THere are many examples on how to use images in listview. Search google for more :) – IAmGroot Jan 13 '13 at 11:27
  • But this is how my app work, first when the user enter the app, it will call to my database to load up a list of url links then from then it is capture by a array which then put into the drawable, lastly then into the adapter. so will i still be able to use your suggested answer? – Sam Jan 14 '13 at 03:38
  • @Sam, yea you can load the Urls. But only load the drawable from the url when it is visible on screen. Else you are wasting memory. – IAmGroot Jan 14 '13 at 09:32
  • isn't that what my code is doing? do you mind spending a few minutes to help me check it out. sorry i'm pretty new to android development. Also i notice that twitter make use of link instead of showing the image, but facebook is able to show the photo instead, is facebook using a different function? – Sam Jan 14 '13 at 10:04
  • @Sam, your for loop 50. is doing `createFromStream` 50 times. So is loading 50 drawables into memory.. Unless you have 50 drawables on screen at once, this is a bad idea. I highly recommend research on using images in a listview. You could also read up on how to resize images to thumbnail size, to reduce memory. http://developer.android.com/training/displaying-bitmaps/index.html Im not sure how much this applies to drawables. – IAmGroot Jan 14 '13 at 10:12
  • thanks i will read up. actually i do. i have 25 post for the listview each having one profile pic and one upload pic, which add up to a total to 50 drawable. will there be any other alternative? – Sam Jan 14 '13 at 10:16
0

Its not the allocation that throws the error that's usually the problem, unless its megabytes in size. Its all the rest of the memory you're using that's a problem. You're almost certainly leaking something. Use the app and take hprof dumps of the stack, look for things which should be deleted not being deleted or too many of some object being created.

Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
  • If you're using eclipse, go to the ddms page and there's a button to download an hprof, right by the button to take a screenshot. You can also download plugins to read the hprof in eclipse. – Gabe Sechan Jan 13 '13 at 15:51