【问题标题】:Out of memory on a 633632-bytes allocation633632 字节分配内存不足
【发布时间】:2013-01-13 08:50:36
【问题描述】:

这是我的代码。开始时的目标是将图像抓取到动态列表视图中,基本上就像我自己数据库中的 RSS 提要一样。我所做的是抓取http链接并将其转换为drawable,然后从那里将drawable从动态列表视图设置为imageview。

这就是问题所在。当我进入应用程序时,第一次加载是好的。但是当我点击刷新按钮时,我会收到“633632 字节分配内存不足”错误,然后是更详细的错误版本,其中包含所有已分配的堆大小限制。

我该如何解决这个问题?

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;
    }
}       
}

【问题讨论】:

    标签: android http drawable inputstream out-of-memory


    【解决方案1】:

    为什么要将大量的 Drawables 添加到内存中。这就是问题所在。应用程序内存限制仅为 ~16MB(每个设备的变化)。然而,看起来您正在加载 100 个可绘制对象,很可能超过了这个。

    您应该仅在列表请求新视图时加载可绘制对象。它会在不需要时将其丢弃。

    编辑:

    你可以做的是覆盖适配器类。并指定一个图片的网址。然后在 getView 方法中,从给定的 Url 加载图像。这会按需处理异步加载。

    例如:

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

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

    【讨论】:

    • 实际上只有 50 个可绘制的理由,因为每组都会有一张个人资料照片和一张“上传的照片”。请求时如何加载?
    • @Sam 查看编辑。这里有很多关于如何在列表视图中使用图像的示例。搜索谷歌了解更多:)
    • 但这就是我的应用程序的工作方式,首先当用户进入应用程序时,它会调用我的数据库来加载一个 url 链接列表,然后它被一个数组捕获,然后放进入drawable,最后进入适配器。那么我仍然可以使用您建议的答案吗?
    • @Sam,是的,您可以加载网址。但只有当它在屏幕上可见时才从 url 加载 drawable。否则你就是在浪费内存。
    • 这不是我的代码在做什么吗?你介意花几分钟帮我检查一下吗?抱歉,我对 android 开发很陌生。我还注意到 twitter 使用链接而不是显示图像,但 facebook 能够显示照片,是 facebook 使用不同的功能吗?
    【解决方案2】:

    引发错误的通常不是分配问题,除非它的大小为兆字节。您正在使用的所有其余内存都是一个问题。你几乎可以肯定泄漏了一些东西。使用该应用程序并获取堆栈的 hprof 转储,查找应该删除而不是删除的内容或创建的对象过多。

    【讨论】:

    • 如果你使用eclipse,进入ddms页面,有一个下载hprof的按钮,按钮旁边就是截图。也可以下载插件来阅读eclipse中的hprof。
    猜你喜欢
    • 2014-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多