0

メモリの問題を絞り込もうとしていて、2 つのタブを持つ ViewPager を作成しました。各タブには、プログラムで作成された 5000 個のボタンが含まれています。静的参照がないため、ボタンがクリアされない理由がわかりません。

ボタンを 2 回押した後、OutOfMemory エラーが発生し、MAT から「android.widget.Button」への参照が 19,416 個あることがわかり、そのうちの class_references タブでは、そのうちの 19,416 個が java.lang.ref.WeakReference であることがわかります。ViewPager を含むアクティビティを起動する前に GC.Collect() を呼び出すと、約 10,000 しかないと予想されます。

変換された hprof ファイルをアップロードしました。

これが私のコードです:

主な活動:

        button.Click += delegate {
            GC.Collect();

            StartActivity(typeof(MyPagerActivity));
        };

マイページャー アクティビティ:

public class MyPagerActivity : Activity
{
    private MyPagerAdapter m_pageradapter;
    private ViewPager m_viewpager;

    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (null); // Always recreate everything (parameter is null)

        RequestWindowFeature(WindowFeatures.ActionBar);
        SetContentView(Resource.Layout.tabactivity);

        InitialiseTabs();
    }

    void InitTab (Fragment frag, string sTitle)
    {
        ActionBar.Tab tab = ActionBar.NewTab();
        m_pageradapter.AddFragment(frag);
        tab.SetText (sTitle);
        tab.TabSelected += HandleTabSelected;
        ActionBar.AddTab(tab);
    }

    void InitialiseTabs()
    {
        m_pageradapter = new MyPagerAdapter(FragmentManager);
        View v = FindViewById(Resource.Id.viewpager);
        m_viewpager = v.JavaCast<ViewPager>();

        InitTab(new FragLotsOfButtons (), "Buttons 1");
        InitTab(new FragLotsOfButtons (), "Buttons 2");

        ActionBar.NavigationMode = ActionBarNavigationMode.Tabs;

        m_viewpager.PageSelected += HandlePageSwipe;
        m_viewpager.Adapter = m_pageradapter;
    }

    void HandlePageSwipe (object sender, ViewPager.PageSelectedEventArgs e)
    {
        ActionBar.SetSelectedNavigationItem(e.Position);
    }

    void HandleTabSelected (object sender, ActionBar.TabEventArgs e)
    {
        m_viewpager.CurrentItem = ActionBar.SelectedNavigationIndex;
    }
}

tabactivity.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <android.support.v4.view.ViewPager
        android:id="@+android:id/viewpager"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
</LinearLayout>

MyPagerAdapter:

class MyPagerAdapter : FragmentStatePagerAdapter
{
    private List<Fragment> m_frags;

    public MyPagerAdapter(FragmentManager fragman) : base(fragman)
    {
        m_frags = new List<Fragment>();
    }

    public void AddFragment(Fragment frag)
    {
        m_frags.Add(frag);
    }

    public override int GetItemPosition (Java.Lang.Object @object)
    {
        return FragmentStatePagerAdapter.PositionNone;
    }

    #region implemented abstract members of FragmentStatePagerAdapter
    public override Fragment GetItem (int p0)
    {
        return m_frags[p0];
    }
    #endregion
    #region implemented abstract members of PagerAdapter
    public override int Count {
        get {
            return m_frags.Count;
        }
    }
    #endregion
}

FragLotsOfButtons:

public class FragLotsOfButtons : Fragment
{
    private LinearLayout m_linearlayout = null;

    public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        m_linearlayout = new LinearLayout (Activity);
        m_linearlayout.LayoutParameters = new ViewGroup.LayoutParams (WindowManagerLayoutParams.FillParent, WindowManagerLayoutParams.FillParent);
        m_linearlayout.Orientation = Orientation.Vertical;

        AddButtons ();

        return m_linearlayout;
    }

    private void AddButtons ()
    {
        for (int i = 0; i < 2500; i++) {
            LinearLayout ll = new LinearLayout (Activity);
            ll.LayoutParameters = new ViewGroup.LayoutParams(WindowManagerLayoutParams.WrapContent, WindowManagerLayoutParams.WrapContent);
            ll.Orientation = Orientation.Horizontal;
            Button testview = new Button (Activity);
            testview.LayoutParameters = new ViewGroup.LayoutParams (WindowManagerLayoutParams.WrapContent, WindowManagerLayoutParams.WrapContent);
            testview.Text = "A" + i.ToString ();
            ll.AddView (testview);
            testview = new Button (Activity);
            testview.LayoutParameters = new ViewGroup.LayoutParams (WindowManagerLayoutParams.WrapContent, WindowManagerLayoutParams.WrapContent);
            testview.Text = "B" + i.ToString ();
            ll.AddView (testview);
            m_linearlayout.AddView (ll);
        }
    }
}

StackOverflow で既にいくつかのソリューションを試しましたが、これまでのところ喜びはありません。

編集:

例外情報が追加されました:

Instance    {Java.Lang.OutOfMemoryError: Exception of type 'Java.Lang.OutOfMemoryError' was thrown.
    at Android.Runtime.JNIEnv.CallVoidMethod (intptr,intptr,Android.Runtime.JValue[]) [0x00023] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.8.2-branch/a25a31d0/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.g.cs:368
        at Android.Views.ViewGroup.AddView (Android.Views.View) [0x00043] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.8.2-branch/a25a31d0/source/monodroid/src/Mono.Android/platforms/android-15/src/generated/Android.Views.ViewGroup.cs:1357
            at PagerAdapterTest.FragLotsOfButtons.AddButtons () [0x000a5] in c:\Users\David.Wright\Documents\Projects\PagerAdapterTest\PagerAdapterTest\FragLotsOfButtons.cs:44
            at PagerAdapterTest.FragLotsOfButtons.OnCreateView (Android.Views.LayoutInflater,Android.Views.ViewGroup,Android.OS.Bundle) [0x00032] in c:\Users\David.Wright\Documents\Projects\PagerAdapterTest\PagerAdapterTest\FragLotsOfButtons.cs:25
            at Android.App.Fragment.n_OnCreateView_Landroid_view_LayoutInflater_Landroid_view_ViewGroup_Landroid_os_Bundle_ (intptr,intptr,intptr,intptr,intptr) [0x00022] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.8.2-branch/a25a31d0/source/monodroid/src/Mono.Android/platforms/android-15/src/generated/Android.App.Fragment.cs:990
            at (wrapper dynamic-method) object.f5d8ab18-1268-411a-908a-67c8e30f2dce (intptr,intptr,intptr,intptr,intptr) <IL 0x00023, 0x0005f>

            --- End of managed exception stack trace ---
            java.lang.OutOfMemoryError
            at android.view.ViewGroup.addInArray(ViewGroup.java:3735)
            at android.view.ViewGroup.addViewInner(ViewGroup.java:3694)
            at android.view.ViewGroup.addView(ViewGroup.java:3543)
            at android.view.ViewGroup.addView(ViewGroup.java:3488)
            at android.view.ViewGroup.addView(ViewGroup.java:3464)
            at pageradaptertest.FragLotsOfButtons.n_onCreateView(Native Method)
            at pageradaptertest.FragLotsOfButtons.onCreateView(FragLotsOfButtons.java:28)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:829)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1035)
            at android.app.BackStackRecord.run(BackStackRecord.java:635)
            at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1399)
            at android.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:437)
            at android.support.v13.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:167)
            at android.support.v4.view.ViewPager.populate(ViewPager.java:1064)
            at android.support.v4.view.ViewPager.populate(ViewPager.java:911)
            at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1432)
            at android.view.View.measure(View.java:15524)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5109)
            at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1396)
            at android.widget.LinearLayout.measureVertical(LinearLayout.java:681)
            at android.widget.LinearLayout.onMeasure(LinearLayout.java:574)
            at android.view.View.measure(View.java:15524)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5109)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
            at android.view.View.measure(View.java:15524)
            at android.widget.LinearLayout.measureVertical(LinearLayout.java:833)
            at android.widget.LinearLayout.onMeasure(LinearLayout.java:574)
            at android.view.View.measure(View.java:15524)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5109)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2397)
            at android.view.View.measure(View.java:15524)
            at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1986)
            at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1227)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1400)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1120)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4604)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
            at android.view.Choreographer.doCallbacks(Choreographer.java:555)
            at android.view.Choreographer.doFrame(Choreographer.java:525)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
            at android.os.Handler.handleCallback(Handler.java:615)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4921)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
            at dalvik.system.NativeStart.main(Native Method)
}   Java.Lang.OutOfMemoryError

LogCat は次のように述べています。

[dalvikvm-heap] Clamp target GC heap from 64.406MB to 64.000MB
[dalvikvm-heap] Clamp target GC heap from 65.822MB to 64.000MB
[dalvikvm-heap] Clamp target GC heap from 65.888MB to 64.000MB
[dalvikvm-heap] Clamp target GC heap from 65.888MB to 64.000MB
[dalvikvm-heap] Forcing collection of SoftReferences for 8800-byte allocation
[dalvikvm-heap] Clamp target GC heap from 65.888MB to 64.000MB
[dalvikvm-heap] Out of memory on a 8800-byte allocation.
[dalvikvm-heap] Clamp target GC heap from 65.889MB to 64.000MB
[dalvikvm-heap] Clamp target GC heap from 65.904MB to 64.000MB
[dalvikvm-heap] Clamp target GC heap from 65.904MB to 64.000MB
4

1 に答える 1

0

確かに 10kButtonsがありますが、 Text をインスタンス化LayoutParametersして に割り当ててButtonsいますが、それらすべてを にカプセル化していますLinearLayoutsJava.Lang.ObjectsGREF参照を作成するものはすべてです。

FragmentおそらくあなたAdapterの によって保持されているインスタンスを、もう必要ないと判断されるまで、実際に削除する場所はどこにもありません。したがって、単に呼び出すだけでは機能しGC.Collect()ません。

于 2013-10-28T16:45:56.260 に答える