如何解决viewpager:指定的孩子已经有一个父母。 您必须先调用子对象的父对象的removeView()

在我的项目中,我使用了三个名为HistoryMainMap选项卡。 主要活动包括计时器,秒表等。 地图显示谷歌地图。 并进入历史现在我只使用简单的Textview。

Viewpagerstream向: 历史主要地图

我将Main设置为当前项目(Bydefault Main标签显示)。现在,当我从Main > Map and Map > Main中滑动时,它的工作非常完美。 但从主要 > 历史刷卡没有错误,但返回从历史logging 历史 > )日食给我错误如:

 E/AndroidRuntime( 533): java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first. 

而FYI我正在使用intent into Map Activity 。请检查下面的code.Please让我知道如何能解决我的问题。

ViewPager类:

 @Override public Fragment getItem(int position) { // return SwipeyTabFragment.newInstance(TITLES[position]); Fragment f = new Fragment(); switch (position) { case 0: f = History.newInstance(position); break; case 1: f = Main.newInstance(position); break; case 2: f = Map.newInstance(position); break; } return f; } 

历史课:

 public class History extends Fragment { public static Fragment newInstance(int position) { History f = new History(); Bundle args = new Bundle(); args.putInt("title", position); f.setArguments(args); return f; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ViewGroup root = (ViewGroup) inflater.inflate(R.layout.history, null); ( (TextView) root.findViewById(R.id.text)).setText("Hello"); return root; } } 

主要类别:

  public class Main extends Fragment implements GPSCallback { ...... public static Fragment newInstance(int position) { Main f = new Main(); Bundle args = new Bundle(); args.putInt("title", position); f.setArguments(args); return f; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final ViewGroup root = (ViewGroup) inflater .inflate(R.layout.main, null); ....... return root; } ........ } 

Map.class:

 public class Map extends Fragment { private static final String KEY_STATE_BUNDLE = "localActivityManagerState"; private LocalActivityManager mLocalActivityManager; protected LocalActivityManager getLocalActivityManager() { return mLocalActivityManager; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle state = null; if (savedInstanceState != null) { state = savedInstanceState.getBundle(KEY_STATE_BUNDLE); } mLocalActivityManager = new LocalActivityManager(getActivity(), true); mLocalActivityManager.dispatchCreate(state); } public static Fragment newInstance(int position) { Map f = new Map(); Bundle args = new Bundle(); args.putInt("title", position); f.setArguments(args); return f; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Intent i = new Intent(getActivity(), MapViewActivity.class); // Intent i = new Intent(getActivity(), hellogooglemap.class); Window w = mLocalActivityManager.startActivity("tag", i); View currentView=w.getDecorView(); currentView.setVisibility(View.VISIBLE); currentView.setFocusableInTouchMode(true); ((ViewGroup) currentView).setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); return currentView; /*ViewGroup root = (ViewGroup) inflater.inflate(R.layout.history, null); ( (TextView) root.findViewById(R.id.text)).setText("Hello"); return root;*/ } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putBundle(KEY_STATE_BUNDLE, mLocalActivityManager.saveInstanceState()); } @Override public void onResume() { super.onResume(); mLocalActivityManager.dispatchResume(); } @Override public void onPause() { super.onPause(); mLocalActivityManager.dispatchPause(getActivity().isFinishing()); } @Override public void onStop() { super.onStop(); mLocalActivityManager.dispatchStop(); } @Override public void onDestroy() { super.onDestroy(); mLocalActivityManager.dispatchDestroy(getActivity().isFinishing()); } } 

Logcat:

  E/AndroidRuntime( 533): java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first. E/AndroidRuntime( 533): at android.view.ViewGroup.addViewInner(ViewGroup.java:1976) E/AndroidRuntime( 533): at android.view.ViewGroup.addView(ViewGroup.java:1871) E/AndroidRuntime( 533): at android.view.ViewGroup.addView(ViewGroup.java:1828) E/AndroidRuntime( 533): at android.view.ViewGroup.addView(ViewGroup.java:1808) E/AndroidRuntime( 533): at android.support.v4.app.NoSaveStateFrameLayout.wrap(NoSaveStateFrameLayout.java:40) E/AndroidRuntime( 533): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:874) E/AndroidRuntime( 533): at android.support.v4.app.FragmentManagerImpl.attachFragment(FragmentManager.java:1240) E/AndroidRuntime( 533): at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:612) E/AndroidRuntime( 533): at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1416) E/AndroidRuntime( 533): at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:431) E/AndroidRuntime( 533): at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:139) E/AndroidRuntime( 533): at android.support.v4.view.ViewPager.populate(ViewPager.java:804) E/AndroidRuntime( 533): at android.support.v4.view.ViewPager.completeScroll(ViewPager.java:1280) E/AndroidRuntime( 533): at android.support.v4.view.ViewPager.computeScroll(ViewPager.java:1176) E/AndroidRuntime( 533): at android.view.ViewGroup.drawChild(ViewGroup.java:1562) E/AndroidRuntime( 533): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373) E/AndroidRuntime( 533): at android.view.ViewGroup.drawChild(ViewGroup.java:1644) E/AndroidRuntime( 533): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373) E/AndroidRuntime( 533): at android.view.View.draw(View.java:6883) E/AndroidRuntime( 533): at android.widget.FrameLayout.draw(FrameLayout.java:357) E/AndroidRuntime( 533): at android.view.ViewGroup.drawChild(ViewGroup.java:1646) E/AndroidRuntime( 533): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373) E/AndroidRuntime( 533): at android.view.ViewGroup.drawChild(ViewGroup.java:1644) E/AndroidRuntime( 533): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373) E/AndroidRuntime( 533): at android.view.View.draw(View.java:6883) E/AndroidRuntime( 533): at android.widget.FrameLayout.draw(FrameLayout.java:357) E/AndroidRuntime( 533): at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1862) E/AndroidRuntime( 533): at android.view.ViewRoot.draw(ViewRoot.java:1522) E/AndroidRuntime( 533): at android.view.ViewRoot.performTraversals(ViewRoot.java:1258) E/AndroidRuntime( 533): at android.view.ViewRoot.handleMessage(ViewRoot.java:1859) E/AndroidRuntime( 533): at android.os.Handler.dispatchMessage(Handler.java:99) E/AndroidRuntime( 533): at android.os.Looper.loop(Looper.java:130) E/AndroidRuntime( 533): at android.app.ActivityThread.main(ActivityThread.java:3683) E/AndroidRuntime( 533): at java.lang.reflect.Method.invokeNative(Native Method) E/AndroidRuntime( 533): at java.lang.reflect.Method.invoke(Method.java:507) E/AndroidRuntime( 533): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) E/AndroidRuntime( 533): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) E/AndroidRuntime( 533): at dalvik.system.NativeStart.main(Native Method) W/ActivityManager( 68): Force finishing activity com.android.gps/.viewpager.SwipeyTabsSampleActivity W/ActivityManager( 68): Activity pause timeout for HistoryRecord{40716740 com.android.gps/.viewpager.SwipeyTabsSampleActivity} 

谢谢。

编辑:

没有意图进入地图活动它的作品pwrfect。我的意思是,当我使用相同的历史进入地图没有任何错误。

Solutions Collecting From Web of "如何解决viewpager:指定的孩子已经有一个父母。 您必须先调用子对象的父对象的removeView()"

我也遇到了这个问题。

你可以通过添加单行mViewPager.setOffscreenPageLimit(3);来解决这个问题mViewPager.setOffscreenPageLimit(3);

 public class SwipeyTabsSampleActivity extends FragmentActivity { ... @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mViewPager = (ViewPager) findViewById(R.id.viewpager); mTabs = (SwipeyTabs) findViewById(R.id.swipeytabs); SwipeyTabsPagerAdapter adapter = new SwipeyTabsPagerAdapter(this, getSupportFragmentManager()); mViewPager.setAdapter(adapter); mViewPager.setOffscreenPageLimit(3); <------ Add this one } } 

祝你好运。

我用过的时候也有同样的问题

 View res = inflater.inflate(R.layout.fragment_guide_search, container); 

里面Fragment.onCreateView(…

你必须打电话

 View res = inflater.inflate(R.layout.fragment_guide_search, container, false); 

要么

 View res = inflater.inflate(R.layout.fragment_guide_search, null); 

首先,RB Patel给出的插入代码(如下所示)的答案就像一个魅力,但是当我读到这个特性时,我意识到这是一个潜在的优化,实际上并不是这个bug的解决scheme。

 mViewPager.setOffscreenPageLimit(3); 

Android开发人员网站对此方法进行了如下说明:

setOffscreenPageLimit(int limit) – 设置在空闲状态下应该保留在视图层次结构中当前页面任一侧的页数。

看来这只是设置caching在当前页面左侧或右侧的页面数量的限制。 在我的情况下,这只是一个乐队援助的问题,是的错误停下来,事情顺利,但我仍然有不好的代码潜伏在我的程序,根本没有被执行。 我相信这个方法的目的是作为一个优化,而不是一个实际的错误修复。

当尝试重载扩展PagerAdapter的自定义类中的instantiateItem()方法时,我遇到了这个问题。 在我回到之前访问/实例化的标签/页面后,我的错误被抛出。

我是Android新手,但我会尽我所能解释我的解决scheme。 抛出这个错误的代码如下:

 v.addView(child); 

如果我正确地理解了这一点,那就是窒息了,因为这个孩子以前已经被实例化了,并被分配了一个父亲。

当我将导航回到以前访问的视图/页面我试图添加一个视图,已经有一个父布局视图到一个新的布局,因此错误。

解决scheme:我只是检查,看看我试图显示(实例化)的子视图已经实例化在别的地方,看看它是否有一个父视图集。 如果子视图已经被创build,那么我只使用了子视图的父视图,而不是创build一个新的视图。

这是我的代码(我很抱歉,如果它冒犯任何专家):

 @Override public Object instantiateItem(View container, int position) { LinearLayout v = new LinearLayout(mContext); //the view being loaded (unless it already was then we have to handle it) View child = mViews.get(position); //If the child view was loaded already then it will have a parent view it belongs to //We return the parent view instead of adding the child to the LinearLayout we just created and returning that new layout. if(child.getParent() != null) { View parent = (View) child.getParent(); ((ViewPager) container).addView(parent); return parent; } //first time instantiating a child view/page v.addView(child); // These lines execute the first time a given page is instantiated ((ViewPager) container).addView(v); return v; } 

这里是我的解决scheme(在每个片段中使用),它允许平滑和避免内存问题:

 ... private LayoutInflater mInflater; private WeakReference<View> mRootView = null; ... @Override public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { if (inflater != null) mInflater = inflater; else mInflater = LayoutInflater.from(getActivity()); View rootView = mRootView == null ? null : mRootView.get(); if (rootView != null) { final ViewParent parent = rootView.getParent(); if (parent != null && parent instanceof ViewGroup) ((ViewGroup) parent).removeView(rootView); } else { rootView = mInflater.inflate(R.layout.fragment_test, null, false); mRootView = new WeakReference<View>(rootView); } return rootView; } 
 @Override public Object instantiateItem(View arg0, int arg1) { Log.d("instantiateItem", ""+arg0+" "+arg1); try { if(mListViews.get(arg1).getParent()==null) ((ViewPager) arg0).addView(mListViews.get(arg1), 0); else{ // I am new to android, it is strange that the view to be added is already bound to a parent // Through trials and error I solve this problem with the following codes // Add that the element of mlistviews is listview in pagerview; ((ViewGroup)mListViews.get(arg1).getParent()).removeView(mListViews.get(arg1)); ((ViewPager) arg0).addView(mListViews.get(arg1), 0); } } catch (Exception e) { Log.d("parent=", ""+mListViews.get(arg1).getParent()); e.printStackTrace(); } return mListViews.get(arg1); } 

如果您正在使用FragmentPagerAdapter,那么只需在FragmentPagerAdapter中使用destroyItem方法即可。

 @Override public void destroyItem(ViewGroup container, int position, Object object) { FragmentTransaction ft=fm.beginTransaction(); ft.remove((Fragment) object); ft.commit(); } 

setOffscreenPageLimit(int limit)消耗更多的内存,在某些情况下它不能正常工作。 其任何一方的保留状态见说明。 setOffscreenPageLimit(int limit) – 设置在空闲状态下应该保留在视图层次结构中当前页面任一侧的页数。

//如果要添加的子视图已经绑定到父项,则从父项中移除子项,然后再次添加到容器中。

 if (v.getParent() != null) { ((ViewGroup) v.getParent()).removeView(v); } container.addView(v);