【问题标题】:Out of memory condition for a simple activity简单活动的内存不足情况
【发布时间】:2012-01-26 12:58:16
【问题描述】:

我有一个活动可以做到这一点:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.list);

    ListView lv = (ListView) findViewById(R.id.ListList);
    lv.setItemsCanFocus(true);
    lv.setOnItemClickListener(this);
    adapter = new ListAdapter(this, lv, model, R.layout.simple, this);
    lv.setAdapter(adapter);
}

我的列表适配器类如下所示。

public static class ListAdapter extends ArrayAdapter<ListItem>
public ListAdapter(Activity activity, ListView lv, List<ListItem> model, int resource, OnActionClickListener onActionClickListener) {
    super(activity, android.R.layout.simple_list_item_1, model);
    ....
}

如果我改变方向,大约 20 次,它将耗尽内存并给我这样的错误:

12-22 17:33:44.977: E/dalvikvm-heap(29145): 1536000-byte external allocation too large for this process.

如果我不在 onCreate 中设置其余代码(过去的 setContentView),我没有问题。

我猜我正在(不经意间)持有活动的一个实例,但我不确定如何。

有什么想法吗?

tia.


所以导致问题的原因是“lv.setAdapter(adapter);” - 如果我注释掉那行,我没有问题......我在 onDestroy() 中尝试了 lv.setAdapter(null) - 没有帮助。我还将这个(http://stackoverflow.com/questions/1147172/what-android-tools-and-methods-work-best-to-find-memory-resource-leaks)添加到 onDestroy() - 似乎没有来帮忙。


所以,我已将其范围缩小到尽可能小。

这里是主要的 TestAppActivity.java 文件。

package com.junk.test;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class TestAppActivity extends Activity {
    protected ArrayList<ListItem> model = new ArrayList<ListItem>();
    protected ListAdapter adapter = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        ListView lv = (ListView) findViewById(R.id.ListList);
        lv.setItemsCanFocus(true);
        adapter = new ListAdapter(this, lv, model);
        lv.setAdapter(adapter);

        if (savedInstanceState == null) {
            Log.i("test", "@@ start");
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        boolean change = true;
                        Thread.sleep(4 * 1000);
                        for (int ii = 0; ii < 200; ii++) {
                            setRequestedOrientation(change ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                            Thread.sleep(4 * 1000);
                            change = !change;
                            Log.i("test", "@@ change: " + (ii+1));
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        Log.i("test", "@@ complete!");
                    }
                }
            }).start();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

// doesn't make any difference.
//        ListView lv = (ListView) findViewById(R.id.ListList);
//        lv.setAdapter(null);
//        adapter.clear();
//        adapter = null;

        unbindDrawables(findViewById(R.id.ListList));
        System.gc();
    }

    private void unbindDrawables(View view) {
        if (view == null) { return; }

        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));
            }
            if (view instanceof AdapterView) {

            } else {
                ((ViewGroup) view).removeAllViews();
            }
        }
    }

    public static class ListItem {
        public int x;
    }

    public static class ListAdapter extends ArrayAdapter<ListItem> implements View.OnClickListener {
        public ListAdapter(Activity activity, ListView lv, List<ListItem> model) {
            super(activity.getApplicationContext(), android.R.layout.simple_list_item_1, model);
        }

        @Override
        public void onClick(View v) {
        }
    }
}

这里是 main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:background="@drawable/player_background">

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />

    <ListView
        android:id="@+id/ListList"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:choiceMode="singleChoice"
        android:cacheColorHint="#00000000"
        android:dividerHeight="3dp"
        android:overScrollFooter="@null" />

</LinearLayout>

而且它仍然在泄漏 - 大约需要 110 次方向更改,但最终它给出了分配错误!

【问题讨论】:

标签: android memory out-of-memory orientation


【解决方案1】:

Eclipse Memory Analizer Tool 可以帮助您找到根本原因。通常的情况是在应用程序启动后立即进行堆转储,然后进行几次方向更改,使用 DDMS 强制 GC,然后再进行一次堆转储。之后,您可以比较堆转储,看看是否有剩余的活动或其他东西。 “到 GC 根目录的路径”工具可以显示丢失的引用,从而阻止收集剩余的对象。

查看this question 了解更多关于 MAT 的参考资料。

【讨论】:

    【解决方案2】:

    您的活动使用哪种启动模式?

    也许这些链接会帮助您做出决定

    Launch modes 1

    Launch modes 2

    希望对你有帮助……

    【讨论】:

    • 你使用什么样的适配器,它有什么样的静态变量(如果有的话)?
    • 我正在使用一个数组适配器(基类) - public static class ListAdapter extends ArrayAdapter
    • 我尝试将 ListAdapter 设为私有本地类(不是静态的),但没有任何区别。
    • 当您将您的代码与网络上提供的简单示例进行比较时,您是否在做一些与众不同的事情
    猜你喜欢
    • 1970-01-01
    • 2012-06-10
    • 1970-01-01
    • 2010-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多