5

FragmentMediaOverviewsのリスト(それぞれにimageviewといくつかのテキストが含まれています)を含むFragmentActivityがありMediaItemView、詳細を開くアイテムの1つ(Fragment)をクリックします。ここで、リストから詳細フラグメントに何度か(戻るボタンを使用して)前後に(listitemをクリックして)戻ると、最終的にOOM-Errorsが発生します。SoftReferencelistitemsとdetailフラグメントのビットマップにsを使用します。MATによるとMediaItemView、インスタンスだけでなくsの数も増えていFragmentMediaOverviewますが、その理由がわかりません。

私はこのAndroidを読みました:AlertDialogはメモリリークを引き起こしますがnull、リスナーを解決することができませんでした。

これが私のコードです:

FragmentMediaOverview.java

MediaAdapter(タブレットレイアウトの場合、グリッドビューに接続する必要があるため、これはListFragmentではありません)

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

    }
}

MediaAdapter.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 AdapterしてくださいAPI 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 に答える