耗尽内存的android项目

时间:2014-08-20 20:03:21

标签: java android eclipse android-layout android-intent

当我在真实设备上启动并运行我的应用程序时,它说不幸停止并且在logcat中说java.lang.runoutofmemory并且我不知道如何修复它

这是我的主要活动类:

public class MainActivity extends Activity implements OnItemClickListener,
TextWatcher {


String[] category_name;
int[] category_id;
Bitmap[] pics;
GridView v1;

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

ActionBar bar = getActionBar();
// for color
bar.setBackgroundDrawable(new ColorDrawable(Color.parseColor("#5c7afe")));
// for image

setContentView(R.layout.activity_main);

v1 = (GridView) findViewById(R.id.gridvieww);
SetDB();
v1.setOnItemClickListener(this);
}

public void SetDB() {
SQLiteDatabase DB = openOrCreateDatabase("test", MODE_PRIVATE, null);// to
                                                                        // create
                                                                        // db
                                                                        // folder
InputStream is = getResources().openRawResource(R.raw.hotline_data);
try {
    byte[] b = new byte[is.available()];
    is.read(b);
    FileOutputStream fos = new FileOutputStream("/data/data/"
            + getPackageName() + "/databases/Hotline.sqlite");
    fos.write(b);
    fos.close();

    SQLiteDatabase hotline_db = openOrCreateDatabase("Hotline.sqlite",
            MODE_PRIVATE, null);
    Cursor c = hotline_db.rawQuery("select * from category", null);
    if (c.moveToFirst()) {
        category_name = new String[c.getCount()];
        category_id = new int[c.getCount()];
        pics = new Bitmap[c.getCount()];
        int i = 0;
        do {
            int id = c.getInt(c.getColumnIndex("id"));
            String name = c.getString(c.getColumnIndex("name"));
            byte[] b1 = c.getBlob(c.getColumnIndex("pic"));
            Bitmap bm = BitmapFactory.decodeByteArray(b1, 0, b1.length);
            category_name[i] = name;
            category_id[i] = id;
            pics[i] = bm;
            i++;
        } while (c.moveToNext());
        CustomGridAdapter cga = new CustomGridAdapter(this,
                category_name, pics);
        v1.setAdapter(cga);
     }

  } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }

 }

@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// TODO Auto-generated method stub
Intent i = new Intent(this, Company.class);
i.putExtra("cat_id", category_id[arg2]);
startActivity(i);
}

@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub

}

@Override
public void beforeTextChanged(CharSequence s, int start, int count,
    int after) {
// TODO Auto-generated method stub

}

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub

}

现在这里是网格视图类

public class CustomGridAdapter extends BaseAdapter {
private Context context;
private final String [] gridValues;
private Bitmap[] pic;
public CustomGridAdapter (Context context,String[] gridValues,Bitmap[] pic){
this.context= context;
this.gridValues=gridValues;
this.pic=pic;


}
@Override
public int getCount() {
    // TODO Auto-generated method stub
    return gridValues.length;
}

@Override
public Object getItem(int arg0) {
    // TODO Auto-generated method stub
    return null;
}

@Override
public long getItemId(int arg0) {
    // TODO Auto-generated method stub
    return 0;
}

@Override
public View getView(int arg0, View arg1, ViewGroup arg2) {
    // TODO Auto-generated method stub

    LayoutInflater li=(LayoutInflater)                                  
    View v=li.inflate(R.layout.grid, arg2, false);
    context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    ImageView iv=(ImageView) v.findViewById(R.id.gridimage);

    iv.setImageBitmap(pic[arg0]);

    return v;
    }

    }

这是日志猫

08-20 18:09:41.738: E/AndroidRuntime(11021):    at android.view.Choreographer.doFrame(Choreographer.java:573)
08-20 18:09:41.738: E/AndroidRuntime(11021):    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:789)
08-20 18:09:41.738: E/AndroidRuntime(11021):    at android.os.Handler.handleCallback(Handler.java:733)
08-20 18:09:41.738: E/AndroidRuntime(11021):    at android.os.Handler.dispatchMessage(Handler.java:95)
08-20 18:09:41.738: E/AndroidRuntime(11021):    at android.os.Looper.loop(Looper.java:157)
08-20 18:09:41.738: E/AndroidRuntime(11021):    at android.app.ActivityThread.main(ActivityThread.java:5356)
08-20 18:09:41.738: E/AndroidRuntime(11021):    at java.lang.reflect.Method.invokeNative(Native Method)
08-20 18:09:41.738: E/AndroidRuntime(11021):    at java.lang.reflect.Method.invoke(Method.java:515)
08-20 18:09:41.738: E/AndroidRuntime(11021):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
08-20 18:09:41.738: E/AndroidRuntime(11021):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
08-20 18:09:41.738: E/AndroidRuntime(11021):    at dalvik.system.NativeStart.main(Native Method)
08-20 18:09:41.738: E/AndroidRuntime(11021): Caused by: java.lang.reflect.InvocationTargetException
08-20 18:09:41.738: E/AndroidRuntime(11021):    at java.lang.reflect.Constructor.constructNative(Native Method)
08-20 18:09:41.738: E/AndroidRuntime(11021):    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
08-20 18:09:41.738: E/AndroidRuntime(11021):    at android.view.LayoutInflater.createView(LayoutInflater.java:600)
08-20 18:09:41.738: E/AndroidRuntime(11021):    ... 41 more
08-20 18:09:41.738: E/AndroidRuntime(11021): Caused by: java.lang.OutOfMemoryError
08-20 18:09:41.738: E/AndroidRuntime(11021):    at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
08-20 18:09:41.738: E/AndroidRuntime(11021):    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:677)
08-20 18:09:41.738: E/AndroidRuntime(11021):    at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:507)
08-20 18:09:41.738: E/AndroidRuntime(11021):    at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:872)
08-20 18:09:41.738: E/AndroidRuntime(11021):    at android.content.res.Resources.loadDrawable(Resources.java:3056)
08-20 18:09:41.738: E/AndroidRuntime(11021):    at android.content.res.TypedArray.getDrawable(TypedArray.java:602)
08-20 18:09:41.738: E/AndroidRuntime(11021):    at android.widget.ImageView.<init>(ImageView.java:133)
08-20 18:09:41.738: E/AndroidRuntime(11021):    at android.widget.ImageView.<init>(ImageView.java:123)

快速需要你的帮助

2 个答案:

答案 0 :(得分:2)

您尝试在运行时加载太多位图。虽然Android设备可能拥有相当数量的内存,但操作系统仅为运行应用程序分配了少量内存,因此如果您持有足够的内容,您可能会遇到OutOfMemmoryError。

在我的应用程序中,我需要保存1024x1024图像的缓冲区,并在加载约3-4个后开始出现OutOfMemory错误。

解决此问题的一个选项是在清单文件中设置largeHeap设置,但添加的内存量有限,并且在不同设备之间有所不同。最后,您可以加载更多图像,但是您仍然可以达到相同的死角。

解决这个问题的真正方法是提出一种在运行时不需要多个位图的方法。找出您需要在任何给定时刻在屏幕上显示哪些图像并仅加载这些图像。应该删除任何实际上未显示或即将显示的位图。删除位图时,请务必调用它们上的recycle()函数,因为这会立即释放位图的内存。

这应该让你开始。

答案 1 :(得分:1)

除了Gil的回复之外,Google还提供了一些关于如何处理以下两个链接的位图的建议:

Displaying Bitmaps EfficientlyLoading Bitmaps Efficiently

这可以通过根据屏幕存储大小的本地版本,操作inSampleSize并在加载期间检查OOM以便能够在RunTime中适当响应(如果您发现自己用完了)来完成。