我试图缩小内存问题的范围,并创建了一个带有两个选项卡的 ViewPager,每个选项卡包含以编程方式创建的 5000 个按钮。没有静态引用,所以我很困惑为什么按钮没有被清除。
按下第二个按钮后,我收到 OutOfMemory 错误,MAT 告诉我有 19,416 个对“android.widget.Button”的引用,其中 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;
}
}
选项卡活动.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>
我的页面适配器:
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