1

スタック オーバーフロー Android ユーザーの皆様、こんにちは。

次の質問を手伝ってください。

問題

魚の種をリストするアプリの機能を書いています。アダプターにカスタム ListView Adapter クラス (これを FishSpeciesListAdapter と呼びましょう) を使用しています。現在のところ、プログラムのデフォルトとして 27 種類の魚種が記録されています (最終的には、自分で追加することもできます)。問題は、アダプターを実際の listview xml オブジェクトにリンクし、リストを下にスクロールすると、しばらくすると次のエラーが発生することです。

UNHANDLED EXCEPTION: Java.Lang.OutOfMemoryError: Exception of type 'Java.Lang.OutOfMemoryError' was thrown.
at Android.Runtime.JNIEnv.CallStaticObjectMethod (intptr,intptr,Android.Runtime.JValue[]) <0x00080>
at Android.Graphics.BitmapFactory.DecodeByteArray (byte[],int,int) <0x001db>
at FishinTales.FishSpeciesListAdapter.GetView (int,Android.Views.View,Android.Views.ViewGroup) <0x002f7>
at Android.Widget.BaseAdapter.n_GetView_ILandroid_view_View_Landroid_view_ViewGroup_ (intptr,intptr,int,intptr,intptr) <0x00093>
at (wrapper dynamic-method) object.5dcc133f-a229-41c4-80e2-f5f5260ecdad (intptr,intptr,int,intptr,intptr) <0x0004b>

  --- End of managed exception stack trace ---
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
    at android.graphics.BitmapFactory.nativeDecodeByteArray(Native Method)
    at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:392)
    at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:405)
    at fishintales.FishSpeciesListAdapter.n_getView(Native Method)
    at fishintales.FishSpeciesListAdapter.getView(FishSpeciesListAdapter.java:55)
    at android.widget.AbsListView.obtainView(AbsListView.java:1294)
    at android.widget.ListView.addViewBelow(ListView.java:2896)
    at android.widget.ListView.scrollListItemsBy(ListView.java:2825)
    at android.widget.ListView.arrowScrollImpl(ListView.java:2322)
    at android.widget.ListView.arrowScroll(ListView.java:2269)
    at android.widget.ListView.commonKey(ListView.java:2071)
    at android.widget.ListView.onKeyDown(ListView.java:2018)
    at android.view.KeyEvent.dispatch(KeyEvent.java:1037)
    at android.view.View.dispatchKeyEvent(View.java:3740)
    at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:786)
    at android.widget.ListView.dispatchKeyEvent(ListView.java:2003)
    at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:788)
    at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:788)
    at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:788)
    at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:788)
    at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:1667)
    at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1102)
    at android.app.Activity.dispatchKeyEvent(Activity.java:2063)
    at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1643)
    at android.view.ViewRoot.deliverKeyEventToViewHierarchy(ViewRoot.java:2471)
    at android.view.ViewRoot.handleFinishedEvent(ViewRoot.java:2441)
    at android.view.ViewRoot.handleMessage(ViewRoot.java:1735)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:123)
    at android.app.ActivityThread.main(ActivityThread.java:4627)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:521)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
    at dalvik.system.NativeStart.main(Native Method)

Unhandled Exception:
Java.Lang.OutOfMemoryError: Exception of type 'Java.Lang.OutOfMemoryError' was thrown.
at Android.Runtime.JNIEnv.CallStaticObjectMethod (intptr,intptr,Android.Runtime.JValue[]) <0x00080>
at Android.Graphics.BitmapFactory.DecodeByteArray (byte[],int,int) <0x001db>
at FishinTales.FishSpeciesListAdapter.GetView (int,Android.Views.View,Android.Views.ViewGroup) <0x002f7>
at Android.Widget.BaseAdapter.n_GetView_ILandroid_view_View_Landroid_view_ViewGroup_ (intptr,intptr,int,intptr,intptr) <0x00093>
at (wrapper dynamic-method) object.5dcc133f-a229-41c4-80e2-f5f5260ecdad (intptr,intptr,int,intptr,intptr) <0x0004b>

  --- End of managed exception stack trace ---
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
    at android.graphics.BitmapFactory.nativeDecodeByteArray(Native Method)
    at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:392)
    at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:405)
    at fishintales.FishSpeciesListAdapter.n_getView(Native Met

これが私のカスタム ListAdapter です。

public class FishSpeciesListAdapter : BaseAdapter
{
    Context n_context;
    List<AppCode.Specie> n_specieData;

    public FishSpeciesListAdapter (Context context, List<AppCode.Specie> specieData)
    {
        this.n_context = context;
        this.n_specieData = specieData;
    }

    public override int Count {
        get { return this.n_specieData.Count; }
    }

    public override Java.Lang.Object GetItem (int position)
    {
        return null;
    }

    public override long GetItemId (int position)
    {
        return 0;
    }

    // create a new ImageView for each item referenced by the Adapter
    public override View GetView (int position, View convertView, ViewGroup parent)
    {
        View v;
        if(convertView==null){

            LayoutInflater li = LayoutInflater.FromContext(parent.Context);
            v = li.Inflate(Resource.Layout.Adapter_FishSpeciesIcon, null);
        }
        else
        {
            v = convertView;
        }
        ImageView iconImage = (ImageView)convertView.FindViewById(Resource.Id.xml_adapter_fishSpeciesIconImage);
        TextView nameText = (TextView)convertView.FindViewById(Resource.Id.xml_adapter_fishSpeciesNameText);
        TextView scientificNameText = (TextView)convertView.FindViewById(Resource.Id.xml_adapter_fishSpeciesScientificNameText);

        nameText.Text = this.n_specieData[position].Name;
        scientificNameText.Text = this.n_specieData[position].ScientificName;

        if (this.n_specieData[position].RelatedMedia.AttachedPhotos.Count < 1)
        {
            iconImage.SetImageResource(Resource.Drawable.Icon); 
        }
        else
        {
            iconImage.SetImageBitmap(BitmapFactory.DecodeByteArray(this.n_specieData[position].RelatedMedia.AttachedPhotos[0], 0, this.n_specieData[position].RelatedMedia.AttachedPhotos[0].Length));  
        }   

        return v;
    }
}

私の代理でのその他の研究

すべての画像は 100 ~ 300 KB の範囲です。これは本当にこの問題を引き起こしますか?

関連するものですが、新しい質問が必要なため、追加のコードについては私の最後の投稿を参照してください。お時間をいただきありがとうございます。

4

1 に答える 1

4

解決しました!

それが行っていたのは、GetView が呼び出されるたびに、バイト配列をビットマップにデコードするのが遅れていたことです。そこで、コンストラクターでそれらをすべて変換し、GetView メソッドが呼び出されたときに参照するビットマップのキャッシュを作成しました。

これが、機能する更新されたカスタム ListView アダプターです。

public class FishSpeciesListAdapter : BaseAdapter
{
    Context n_context;
    List<AppCode.Specie> n_specieData;
    List<Bitmap> n_bitmapCache;

    public FishSpeciesListAdapter (Context context, List<AppCode.Specie> specieData)
    {
        this.n_context = context;
        this.n_specieData = specieData;
        this.n_bitmapCache = new List<Bitmap>();
        this.LoadBitmapsIntoCache();
    }

    private void LoadBitmapsIntoCache()
    {
        foreach(AppCode.Specie specie in this.n_specieData)
        {
            if (specie.RelatedMedia.AttachedPhotos.Count < 1)
            {
                this.n_bitmapCache.Add(BitmapFactory.DecodeResource(this.n_context.Resources, Resource.Drawable.Icon)); 
            }
            else
            {
                this.n_bitmapCache.Add(BitmapFactory.DecodeByteArray(specie.RelatedMedia.AttachedPhotos[0], 0, specie.RelatedMedia.AttachedPhotos[0].Length));  
            }
        }
    }

    public override int Count {
        get { return this.n_specieData.Count; }
    }

    public override Java.Lang.Object GetItem (int position)
    {
        return null;
    }

    public override long GetItemId (int position)
    {
        return 0;
    }

    // create a new ImageView for each item referenced by the Adapter
    public override View GetView (int position, View convertView, ViewGroup parent)
    {
        if(convertView==null){

            LayoutInflater li = LayoutInflater.FromContext(parent.Context);
            convertView = li.Inflate(Resource.Layout.Adapter_FishSpeciesIcon, null);
        }

        ImageView iconImage = (ImageView)convertView.FindViewById(Resource.Id.xml_adapter_fishSpeciesIconImage);
        TextView nameText = (TextView)convertView.FindViewById(Resource.Id.xml_adapter_fishSpeciesNameText);
        TextView scientificNameText = (TextView)convertView.FindViewById(Resource.Id.xml_adapter_fishSpeciesScientificNameText);

        nameText.Text = this.n_specieData[position].Name;
        scientificNameText.Text = this.n_specieData[position].ScientificName;
        iconImage.SetImageBitmap(this.n_bitmapCache[position]); 

        return convertView;
    }
}

コンストラクターで LoadBitmapsIntoCache() を呼び出し、ビットマップをリストに保存した後。この問題は解決され、OutOfMemory エラーなしですべての魚種をスクロールできました。助けてくれたすべての人に感謝します。

于 2012-12-03T16:53:34.293 に答える