1

私は、150kb 未満の異なるサイズの画像を少なくとも 28 個ロードしている単純な静的画像ギャラリーを使用しています。

ここで2つの問題に気付きました:

1)スクロールが遅い 2)このアクティビティに2回3回行くと、メモリ不足の例外が発生します。

ここでの問題とその解決方法を教えてくれる人はいますか?

任意の助けをいただければ幸いです

丸太の猫:

03-15 15:32:55.899: E/AndroidRuntime(14662): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:563)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:439)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.content.res.Resources.loadDrawable(Resources.java:1709)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.content.res.Resources.getDrawable(Resources.java:581)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.widget.ImageView.resolveUri(ImageView.java:501)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.widget.ImageView.setImageResource(ImageView.java:280)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at com.tackfu.Art$ImageAdapter.getView(Art.java:84)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.widget.AbsListView.obtainView(AbsListView.java:1515)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.widget.GridView.makeAndAddView(GridView.java:1269)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.widget.GridView.makeRow(GridView.java:315)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.widget.GridView.fillDown(GridView.java:268)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.widget.GridView.fillGap(GridView.java:235)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.widget.AbsListView.trackMotionScroll(AbsListView.java:4063)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.widget.AbsListView.onTouchEvent(AbsListView.java:2471)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.view.View.dispatchTouchEvent(View.java:3885)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:903)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1750)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1135)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.app.Activity.dispatchTouchEvent(Activity.java:2096)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1734)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2216)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.view.ViewRoot.handleMessage(ViewRoot.java:1887)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.os.Handler.dispatchMessage(Handler.java:99)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.os.Looper.loop(Looper.java:130)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at android.app.ActivityThread.main(ActivityThread.java:3687)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at java.lang.reflect.Method.invokeNative(Native Method)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at java.lang.reflect.Method.invoke(Method.java:507)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
03-15 15:32:55.899: E/AndroidRuntime(14662):    at dalvik.system.NativeStart.main(Native Method)

活動コード:

 @Override
        public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);
            setContentView(R.layout.art);

 GridView gridview = (GridView) findViewById(R.id.gridv
 gridview.setAdapter(new ImageAdapter(this));

}

 public class ImageAdapter extends BaseAdapter {
            private Context mContext;

            public ImageAdapter(Context c) {
                mContext = c;
            }

            public int getCount() {
                return mThumbIds.length;
            }

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

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

            // create a new ImageView for each item referenced by the Adapter
            public View getView(int position, View convertView, ViewGroup parent) {
                ImageView imageView;
                if (convertView == null) {  // if it's not recycled, initialize some attributes
                    imageView = new ImageView(mContext);
                    imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
                    imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
                    imageView.setPadding(8, 8, 8, 8);
                } else {
                    imageView = (ImageView) convertView;
                }

                imageView.setImageResource(mThumbIds[position]);
                return imageView;
            }

            // references to our images
            private Integer[] mThumbIds = {
                    R.drawable.i1, R.drawable.i2,
                    R.drawable.i3, R.drawable.i4,
                    R.drawable.i5, R.drawable.i6,
                    R.drawable.i7, R.drawable.i8,
                    R.drawable.i9, R.drawable.i10,
                    R.drawable.i11, R.drawable.i12,
                    R.drawable.i13,R.drawable.i14,
                    R.drawable.i15,R.drawable.i16,
                    R.drawable.i17,R.drawable.i18,
                    R.drawable.i19,R.drawable.i20,
                    R.drawable.i21, R.drawable.i22,
                    R.drawable.i23, R.drawable.i24,
                    R.drawable.i26, R.drawable.i28,
                    R.drawable.i29, R.drawable.i30
            };
        }
4

3 に答える 3

1

使用していないビットマップをリサイクルします。パフォーマンスを向上させるには、ビュー ホルダーを使用します。 http://www.youtube.com/watch?v=wDBM6wVEO70。リンク先をご覧になることをお勧めします。listview に適用されるものは何でも gridview にも適用され、ビデオはそれについて話します。ビデオには、メモリ リークを回避するために使用する必要があるビュー ホルダーに関するトークもあります。

http://android-developers.blogspot.de/2009/01/avoiding-memory-leaks.htmlには、メモリ リークの回避に関する話もあります。

http://developer.android.com/training/displaying-bitmaps/load-bitmap.html . 縮小バージョンをメモリにロードするセクションを参照してください。

MAT アナライザーを使用してメモリ リークをチェックします。http://www.youtube.com/watch?v=_CruQY55HOk .

http://developer.android.com/training/articles/perf-tips.htmlでいくつかのヒントを検討してください。

于 2013-03-15T10:49:54.017 に答える
1

サイズが 150KB の 28 枚の画像は、約 4MB の RAM です。加えてアプリケーション データであり、小さなヒープには収まりません。マニフェストに大きなヒープを設定できます:

android:largeHeap="true"

ただし、メモリに制限がなく、画像の数が増えるとこのエラーが再び発生する可能性があるため、この方法は回避策のように見えます。また、遅延読み込みを使用するか、デバイスの画面サイズによって画像のサイズを変更する必要があります。

于 2013-03-15T10:46:03.863 に答える
0

スクロールが遅い理由は非常に単純です。ビューが作成されるたびに、UIスレッドに画像を読み込んでいます。優先度の低い別のスレッドにロードを委任する必要があります。必要に応じて、UIスレッドにサムネイルを読み込んですばやく何かを表示してから、バックグラウンドでフル解像度を読み込むことができます。

Androidには、アプリを優れたものにするための巧妙なトリックがたくさんありますが、それらを賢く使用する必要があることに注意してください。たとえば、Androidは静的ビューをいわゆるDrawing Cacheにキャッシュしますが、ImgaeViewsの場合は、追加のメモリを必要とし、何も提供しないため、意味がありません。ハードウェアアクセラレーションUIを使用すると、各ビューキャッシュが2の累乗のテクスチャで描画されるため、さらに多くのメモリが使用されます。これは、100x35pxボタンが128x64x4バイトの追加メモリを必要とすることを意味します。Androidは、線形テクスチャサンプラーなどのアンチエイリアスの使用も試みます。これは優れていますが、CPU時間がかかるため、オフにすることをお勧めします。

setImageResourceを介して画像をロードすると、ほとんど制御できません。ロードとアンロードをより正確に制御できるように、自分でイメージをロードすることをお勧めします。画像を少しキャッシュすることもできます。LRUキャッシュは、そのような用途のために作成されたクラスの良い例です:http: //developer.android.com/reference/android/util/LruCache.html。現在の画像をロードして、左側と右側に1つずつプリロードできます。ユーザーが前の画像に戻ると、その画像がメモリに保存されます。

また、ブルートフォースを使用する場合は、NativeBufferを使用して画像をキャッシュできます:http ://code.google.com/p/native-buffer/ 。ギャラリーの再設計を余儀なくされますが、画像の多いアプリを大幅に早める可能性があります。

于 2013-03-15T11:08:23.167 に答える