2013-10-28 5 views
0

Я пытаюсь сузить проблему памяти и создал ViewPager с двумя вкладками, каждая вкладка содержит 5000 кнопок, созданных программно. Нет статических ссылок, поэтому я смущен тем, почему кнопки не очищаются.Monodroid viewpager out of memory

После второй кнопки нажмите «Ошибка OutOfMemory», и MAT сообщает мне, что у меня есть 19,416 ссылок на «android.widget.Button», из которых на вкладке class_references указано, что 19 416 из них - это java.lang.ref.WeakReference. Я ожидал бы только около 10 000, хотя, как я называю GC.Collect(), перед запуском активности, содержащей ViewPager.

Я загрузил converted hprof file.

Вот мой код:

MainActivity:

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

      StartActivity(typeof(MyPagerActivity)); 
     }; 

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 не радость до сих пор.

EDIT:

информация Исключение добавлено:

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 
+0

В каком классе вы получаете OutOfMemory..post ваш logcat .. –

ответ

0

Конечно у вас есть 10k Buttons, но вы также инстанцировании LayoutParameters и назначение текста в Buttons, но вы также инкапсулируете все это в LinearLayouts. Все это Java.Lang.Objects, что делает ссылки на GREF.

Я не вижу нигде, где вы действительно избавитесь от своих Fragment экземпляров, которые, вероятно, хранятся у вашего Adapter, пока он не сочтет это вам больше не нужно. Поэтому просто вызов GC.Collect() не будет работать.

+0

Спасибо, что ответили. Я не понимаю, почему это не все выходит за рамки, когда MyPagerActivity закрывается? Затем, когда я нажимаю кнопку MainActivity и вызывается GC.Collect(), не следует ли очищать весь предыдущий экземпляр MyPagerActivity? – Dave