我们有一个master-detail流程,主要和详细信息片段都是通过片段管理器和后台堆栈“添加”的,如下所示,
我们将homefragment中的主片段添加为
getActivity().getSupportFragmentManager().beginTransaction()
.add(R.id.container, <masterfragment>, "master")
.addToBackStack()
.commit();
从master中我们以同样的方式添加子片段,当用户点击一行时,
getActivity().getSupportFragmentManager().beginTransaction()
.add(R.id.container, <detailfragment>, "detail")
.addToBackStack()
.commit();
现在我们得到一个随机stackoverflower错误,用户在主要和细节片段之间来回导航超过100次,
android.support.v4.app.Fragment.c
android.support.v4.app.FragmentManagerImpl.a
android.support.v4.app.Fragment.c
android.support.v4.app.FragmentManagerImpl.a
android.support.v4.app.FragmentActivity.onPreparePanel
android.support.v7.internal.view.WindowCallbackWrapper.onPreparePanel
android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.onPreparePanel
android.support.v7.internal.view.WindowCallbackWrapper.onPreparePanel
android.support.v7.internal.app.ToolbarActionBar$ToolbarCallbackWrapper.onPreparePanel
android.support.v7.internal.view.WindowCallbackWrapper.onPreparePanel
android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.onPreparePanel
android.support.v7.internal.view.WindowCallbackWrapper.onPreparePanel
android.support.v7.internal.app.ToolbarActionBar$ToolbarCallbackWrapper.onPreparePanel
经过几个小时的分析,我们发现每次我们使用片段中的工具栏设置支持操作栏时(主片段和详细片段都有不同的工具栏)
getActivity().setSupportActionBar(mToolBar);
创建一个新的ToolbarActionBar对象,并使用 new wrappedwindow callback 设置窗口回调,(以下代码片段是从类,AppCompatDelegateImplV7的android源代码复制的)
ToolbarActionBar tbab = new ToolbarActionBar(toolbar, ((Activity) mContext).getTitle(),
mWindow);
setSupportActionBar(tbab);
mWindow.setCallback(tbab.getWrappedWindowCallback());
在ToolbarActionBar类中创建了一个新的ToolbarCallbackWrapper(以下代码片段是从android源代码复制的),如下面的源代码所示,新的回调包装器将从之前的窗口回调中再次创建。
public ToolbarActionBar(Toolbar toolbar, CharSequence title, Window window) {
mDecorToolbar = new ToolbarWidgetWrapper(toolbar, false);
mWindowCallback = new ToolbarCallbackWrapper(window.getCallback());
mDecorToolbar.setWindowCallback(mWindowCallback);
toolbar.setOnMenuItemClickListener(mMenuClicker);
mDecorToolbar.setWindowTitle(title);
mWindow = window;
}
所以对于每次调用设置支持操作栏,它都会创建一个toolbarcallbackwrapper类的嵌套对象,如下面的调试'对象跟踪'所示
this = {ToolbarActionBar$ToolbarCallbackWrapper@5428}
this$0 = {ToolbarActionBar@5429}
mWrapped = {ToolbarActionBar$ToolbarCallbackWrapper@5423}
this$0 = {ToolbarActionBar@5424}
mWrapped = {ToolbarActionBar$ToolbarCallbackWrapper@5417}
this$0 = {ToolbarActionBar@5418}
mWrapped = {ToolbarActionBar$ToolbarCallbackWrapper@5412}
this$0 = {ToolbarActionBar@5413}
mWrapped = {ToolbarActionBar$ToolbarCallbackWrapper@5382}
this$0 = {ToolbarActionBar@5383}
mWrapped = {ToolbarActionBar$ToolbarCallbackWrapper@5309}
this$0 = {ToolbarActionBar@5310}
mWrapped = {ToolbarActionBar$ToolbarCallbackWrapper@5196}
this$0 = {ToolbarActionBar@5198}
mWrapped = {AppCompatDelegateImplV14$AppCompatWindowCallbackV14@5443}
所以每当工具栏为片段“准备好”时,就会再次调用回调,导致stackoverflow错误,(因为在大约100次导航之后,嵌套对象的深度已超过100)。
我们如何解决这个问题?