6

我正在使用图像设置为我所有活动的背景,但这会导致内存溢出问题并使应用程序崩溃。现在我在我的活动中的 pause() 和 Destroy() 上取消绑定我的可绘制对象,现在它在按下后退按钮时显示空白屏幕。那么如何在不使用额外内存的情况下避免这种情况。

    protected void onPause(){
    super.onPause();
    unbindDrawables(findViewById(R.id.login_root));
}

protected void onDestroy() {
        unbindDrawables(findViewById(R.id.login_root));
        super.onDestroy();
      }

private void unbindDrawables(View view) {
    System.gc();
    Runtime.getRuntime().gc();
    if (view.getBackground() != null) {
    view.getBackground().setCallback(null);
    }
    if (view instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
        unbindDrawables(((ViewGroup) view).getChildAt(i));
        }
    ((ViewGroup) view).removeAllViews();
    }

最初我使用 android:background="@drawable/" 膨胀我的布局,这总是导致内存溢出错误,说 VM 不会让我们分配 10MB(应用程序。)现在我从该可绘制对象中获取位图而无需缩小和绑定它在运行时。现在它说VM不会让我们在不使用unbindDrawables(..)的情况下分配5MB(应用程序)显然显示的背景图像的质量已经降低但我无法理解如果我使用的是13KB 的 png 文件,JVM 如何需要 5 或 10MB 的空间来处理请求?

我已将布局语句从 onCreate() 转移到 onResume() 方法,但应用程序在按下后退按钮时再次耗尽内存。

public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

  protected void onResume(){
        setContentView(R.layout.home);
        Bitmap bmp;
        ImageView background = (ImageView)findViewById(R.id.iv_home_background);
        InputStream is = getResources().openRawResource(R.drawable.background);
        bmp = BitmapFactory.decodeStream(is);
        background.setImageBitmap(bmp);

         super.onResume();
    }

 protected void onPause(){
        super.onPause();
        unbindDrawables(findViewById(R.id.home_root));
    }


 private void unbindDrawables(View view) {
        System.gc();
        Runtime.getRuntime().gc();
        if (view.getBackground() != null) {
        view.getBackground().setCallback(null);
        }
        if (view instanceof ViewGroup) {
            for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            unbindDrawables(((ViewGroup) view).getChildAt(i));
            }
        ((ViewGroup) view).removeAllViews();
        }
    }
4

2 回答 2

1

我找到了解决这个问题的方法。现在我在运行时将我的位图缩放到非常小的尺寸,然后将它们存储在内部存储中。程序在运行时从存储中调用缩放的位图,如果它不存在,它会从可绘制文件夹中调用它,缩放它,将其写入存储,然后将其绑定到视图。这样,在任何时候都不需要调用 unbindDrawables 方法,并且应用程序始终保持响应。我现在唯一关心的是位图的质量,我想我需要调整缩放大小以找出质量最高的最小尺寸。

于 2012-09-17T09:17:09.703 回答
0

您正在为每个子视图调用 GC。尝试在所有解除绑定完成后仅调用一次。

unbindDrawables(findViewById(R.id.login_root));
System.gc();

GC 是一个很重的负载,太频繁地调用它是没有用的。事实上,如果没有泄漏,它应该是必要的。

还要记住,png 文件的大小与内存上的位图无关。这是有关该 http://developer.android.com/training/displaying-bitmaps/index.html的更多信息

于 2013-09-16T13:54:44.797 回答