2013-10-28 94 views
0

我試圖縮小內存問題,並創建了一個帶有兩個選項卡的ViewPager,每個選項卡包含以編程方式創建的5000個按鈕。沒有靜態引用,所以我很困惑爲什麼按鈕不能被清除。Monodroid viewpager內存不足

第二次按下按鈕後,我得到一個OutOfMemory錯誤,MAT告訴我我有19416個對「android.widget.Button」的引用,其中class_references選項卡告訴我這些是19416個是java.lang.ref.WeakReference。在啓動包含ViewPager的活動之前,我只希望有大約10,000個,因爲我調用GC.Collect()。

我上傳了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); 
     } 
    } 
} 

我到目前爲止已經試過了幾個解決方案已經在計算器上沒有快樂。

編輯:

異常信息說:

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。所有那些使得GREF引用的Java.Lang.Objects

我沒有看到任何地方,你實際上擺脫了Fragment實例,它們可能被你的Adapter保留,直到它認爲你不再需要它爲止。所以只需撥打GC.Collect()將不起作用。

+0

感謝您的回覆。我不明白爲什麼在MyPagerActivity關閉時它不會全部超出範圍?然後,當我點擊MainActivity中的按鈕並調用GC.Collect()時,它不應該清除MyPagerActivity的所有前一個實例? – Dave