5

我有一个 FragmentActivity,其中FragmentMediaOverview包含一个MediaItemViews 列表(每个都有一个 imageview 和一些文本),然后单击其中一个打开详细信息片段的项目。现在,当我从列表到详细片段多次返回(通过后退按钮)和来回(单击列表项)时,我最终遇到了 OOM 错误。我将SoftReferences 用于列表项和详细信息片段中的位图。根据 MA​​T,MediaItemViews 和FragmentMediaOverview实例的数量越来越多,但我就是不知道为什么。

我读了这个Android: AlertDialog 会导致内存泄漏,但无法null通过侦听器解决它。

这是我的代码:

FragmentMediaOverview.java

(这不是 ListFragment,因为对于平板电脑布局MediaAdapter需要连接到 gridview)

public class FragmentMediaOverview extends Fragment {
    private static String TAG = FragmentMediaOverview.class.getSimpleName();

    private MediaAdapter adapter;
    private OnMediaSelectedListener selListener;
    private ArrayList<BOObject> mediaItems;

    private ViewGroup layoutContainer;    
    private AdapterView itemContainer; // list or gridview

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.d(TAG, "onCreateView");
        layoutContainer = (ViewGroup) inflater.inflate(R.layout.fragment_media_overview, null);

        return layoutContainer;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        selListener = (OnMediaSelectedListener) activity;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        itemContainer.setOnItemClickListener(null);
        selListener = null;
        adapter = null;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        initUi(layoutContainer);
        displayMedia();
    }

    private void initUi(ViewGroup layoutContainer) {
        itemContainer = (AdapterView) layoutContainer.findViewById(android.R.id.list);
        itemContainer.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                BOMedia mediaItem = ((BOMedia) mediaItems.get(position));
//the FragmentActivity is coordinating the FragmentTransactions
                selListener.onMediaSelected(mediaItem);
            }
        });
    }

    private void displayMedia() {
        Log.d(TAG, "Displaying List");
        if (mediaItems == null) {
            loadMedia();
            return;
        }

        Log.d(TAG, "List: " + mediaItems.size() + ", adapter: " + itemContainer.getAdapter());

        if (adapter == null) {
            Log.d(TAG, "Create Adapter with " + mediaItems.size());

            adapter = new MediaAdapter(getActivity(), mediaItems);
        }

        if (itemContainer.getAdapter() == null) {
            itemContainer.setAdapter(adapter);
        } else {
            adapter.setItems(mediaItems);
            adapter.notifyDataSetChanged();
        }

    }

    private void loadMedia() {
        FragmentHelper.showProgressSpinner(layoutContainer, android.R.id.list);
        DbHelper.getInstance().getMedia(mediaType, new DbQueryFinishListener() {

            @Override
            public void onDbCallFinish(ArrayList<BOObject> objects) {
                if (!getActivity().isFinishing()) {
                    mediaItems = objects;
                    Collections.sort(mediaItems, new Comparator<BOObject>() {
                        final Collator c = Collator.getInstance(Locale.GERMAN);
                        @Override
                        public int compare(BOObject s1, BOObject s2) {
                            if (s2 != null && ((BOMedia) s2).getTitle() != null && s1 != null
                                    && ((BOMedia) s1).getTitle() != null) {
                                return c.compare(((BOMedia) s1).getTitle(),((BOMedia) s2).getTitle());
                            } else {
                                return 0;
                            }
                        }
                    });
                    displayMedia();
                    FragmentHelper.hideProgressSpinner(layoutContainer, android.R.id.list);
                }
            }

            @Override
            public void onDbCallException(Exception exception) {
                if (!getActivity().isFinishing()) {
                    FragmentHelper.hideProgressSpinner(layoutContainer, android.R.id.list);
                }
            }
        });

    }
}

媒体适配器.java

public class MediaAdapter extends BaseAdapter {
    private static final String TAG = MediaAdapter.class.getSimpleName();
    private Context context;
    private ArrayList<BOObject> mediaItems;

    public MediaAdapter(Context c, ArrayList<BOObject> mediaItems) {
        super();
        context = c;
        this.mediaItems = mediaItems;
    }

    @Override
    public int getCount() {
        return mediaItems.size();
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = new MediaItemView(context);
        }
        ((MediaItemView)convertView).initialize((BOMedia) mediaItems.get(position));        
        return convertView;
    }

    public void setItems(ArrayList<BOObject> mediaItems) {
        this.mediaItems = mediaItems;
    }
}

MediaItemView.java

public class MediaItemView extends LinearLayout {
    private static final String TAG = MediaItemView.class.getSimpleName();
    private BOMedia item;
    private SoftReference<Bitmap> bm;
    private ImageView iv;
    private Context ctx;

    public MediaItemView(Context context) {
        super(context);
        LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        layoutInflater.inflate(R.layout.view_media_item, this);
        this.ctx = context;
    }

    /** Init the view with a new BOMedia object
     * @param mediaItem
     */
    public void initialize(BOMedia mediaItem) {
        this.item = mediaItem;
        initUI();
    }

    private void initUI() {
        TextView title = (TextView) findViewById(R.id.itemText);
        iv = (ImageView) findViewById(R.id.itemImage);

        title.setText(Html.fromHtml(item.getTitle()));
        iv.setImageBitmap(null);
        bm = null;
        System.gc();
        iv.invalidate();
        if (item.getFilepathThumb() != null && !item.getFilepathThumb().equals("")) {

            ExpansionPackManager.getInstance().getBitmapResource(item.getFilepathThumb(), false,
                    new BitmapReadListener() {

                        @Override
                        public void onFileRead(BitmapResponseMessage message) {
                            Log.d(TAG, "Bitmap read: " + message.getFilepath());
                            Bitmap image = message.getBitmap();
                            if (image != null && message.getFilepath().equals(item.getFilepathThumb())) {
                                bm = new SoftReference<Bitmap>(image);
                                iv.setImageBitmap(bm.get());
                                Log.d(TAG, "image set");
                            } else {
                                Log.d(TAG, "image too late: " + image);
                            }
                        }

                        @Override
                        public void onFileException(Throwable exception) {
                            Log.d(TAG, "image exception");
                        }
                    });

        }
    }

}
4

3 回答 3

2

在 MediaItemView 中,位图的大小必须太大。如果位图是 600x600 并且您想要显示大小为 50x50 的图像,您可以使用Bitmap.createScaledBitmap. 您还应该在加载位图时使用位图缓存。

于 2012-07-05T12:00:52.260 回答
1

这是因为在滚动时会重新创建Viewfor rach 子项。ListView这对资源来说非常沉重。为避免这种情况,请在适配器中使用持有者类getView()来保存和重用视图。这称为Efficient Adapter. 例如见Efficient List AdapterAPI demoshttp://developer.android.com/tools/samples/index.html

于 2012-06-27T14:29:56.977 回答
0

您还可以使用:

android:hardwareAccelerated = true

从 开始Android 3.0 (API level 11)Android 2D渲染管道旨在更好地支持硬件加速。硬件加速使用GPU.

欲了解更多信息http://developer.android.com/guide/topics/graphics/hardware-accel.html

于 2012-07-04T04:54:42.770 回答