Рекурсивная запись в executePendingTransactions

У меня есть функция MainDrawer to Fragment, в которой есть макет для ящика nav и моего основного содержимого, где я могу загружать новые фрагменты. Один фрагмент, который я загружаю, представляет собой фрагмент StatisticsTab фрагмента. Этот фрагмент содержит табуст, который каждой вкладкой является собственным фрагментом элементов списка. Как только я нажму на элемент ListView, который загружает новый новый фрагмент и больше не находится в tabHost, и я пытаюсь вернуться с помощью навигатора к моему фрагменту StatisticsTab, я получаю эту ошибку:

03-03 10:32:06.884 24185-24185/com.beerportfolio.beerportfoliopro E/AndroidRuntime﹕ FATAL EXCEPTION: main java.lang.IllegalStateException: Recursive entry to executePendingTransactions at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1439) at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:472) at android.support.v4.app.FragmentTabHost.onAttachedToWindow(FragmentTabHost.java:283) at android.view.View.dispatchAttachedToWindow(View.java:12307) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2457) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2464) at android.view.ViewGroup.addViewInner(ViewGroup.java:3567) at android.view.ViewGroup.addView(ViewGroup.java:3399) at android.view.ViewGroup.addView(ViewGroup.java:3344) at android.view.ViewGroup.addView(ViewGroup.java:3320) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:938) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104) at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682) at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1467) at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:440) at android.os.Handler.handleCallback(Handler.java:730) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:158) at android.app.ActivityThread.main(ActivityThread.java:5789) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:525) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:843) at dalvik.system.NativeStart.main(Native Method) 

Если я не нажимаю ни одну из моих вкладок, а на фрагмент StatisticsTab и перехожу к другому фрагменту через navdrawer, а затем обратно в StatisticsTab, тогда он не будет включен. Кроме того, ни один из других фрагментов в силе NavDrawer не закрывается, когда я возвращаюсь к ним, только тот, у которого есть вкладки.

MainDrawer2:

 public class MainDrawer2 extends FragmentActivity { private static final String EXTRA_NAV_ITEM = "extraNavItem"; private static final String STATE_CURRENT_NAV = "stateCurrentNav"; private ActionBarDrawerToggle mDrawerToggle; private DrawerLayout mDrawerLayout; private NavDrawerListAdapter mDrawerAdapter; private ListView mDrawerList; private CharSequence mTitle; private CharSequence mDrawerTitle; private MainNavItem mCurrentNavItem; public static Intent createLaunchFragmentIntent(Context context, MainNavItem navItem) { return new Intent(context, MainDrawer2.class) .putExtra(EXTRA_NAV_ITEM, navItem.ordinal()); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.fragment_main); mTitle = mDrawerTitle = getTitle(); mDrawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout); mDrawerList = (ListView)findViewById(R.id.drawer); getActionBar().setDisplayHomeAsUpEnabled(true); enableHomeButtonIfRequired(); mDrawerAdapter = new NavDrawerListAdapter(getApplicationContext()); mDrawerList.setAdapter(mDrawerAdapter); mDrawerList.setOnItemClickListener(new ListView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { displayNavFragment((MainNavItem)parent.getItemAtPosition(position)); } }); mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_drawer, R.string.app_name, R.string.app_name) { public void onDrawerClosed(View view) { getActionBar().setTitle(mTitle); invalidateOptionsMenu(); } public void onDrawerOpened(View drawerView) { getActionBar().setTitle(mDrawerTitle); invalidateOptionsMenu(); } }; mDrawerLayout.setDrawerListener(mDrawerToggle); if(getIntent().hasExtra(EXTRA_NAV_ITEM)){ MainNavItem navItem = MainNavItem.values() [getIntent().getIntExtra(EXTRA_NAV_ITEM, MainNavItem.STATISTICS.ordinal())]; displayNavFragment(navItem); } else if(savedInstanceState != null){ mCurrentNavItem = MainNavItem.values() [savedInstanceState.getInt(STATE_CURRENT_NAV)]; setCurrentNavItem(mCurrentNavItem); } else{ displayNavFragment(MainNavItem.STATISTICS); } } @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) private void enableHomeButtonIfRequired() { if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH){ getActionBar().setHomeButtonEnabled(true); } } @Override public void setTitle(CharSequence title) { mTitle = title; getActionBar().setTitle(mTitle); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); // Sync the toggle state after onRestoreInstanceState has occurred. mDrawerToggle.syncState(); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // Pass any configuration change to the drawer toggles mDrawerToggle.onConfigurationChanged(newConfig); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt(STATE_CURRENT_NAV, mCurrentNavItem.ordinal()); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } /* @Override public boolean onPrepareOptionsMenu(Menu menu) { // if nav drawer is opened, hide the action items boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList); menu.findItem(R.id.action_settings).setVisible(!drawerOpen); return super.onPrepareOptionsMenu(menu); } */ private void displayNavFragment(MainNavItem navItem) { if(navItem == mCurrentNavItem){ return; } Fragment fragment = Fragment.instantiate(this, navItem.getFragClass().getName()); if(fragment != null){ getSupportFragmentManager().beginTransaction() .replace(R.id.main, fragment) .commit(); setCurrentNavItem(navItem); } } private void setCurrentNavItem(MainNavItem navItem) { int position = navItem.ordinal(); // If navItem is in DrawerAdapter if(position >= 0 && position < mDrawerAdapter.getCount()){ mDrawerList.setItemChecked(position, true); } else{ // navItem not in DrawerAdapter, de-select current item if(mCurrentNavItem != null){ mDrawerList.setItemChecked(mCurrentNavItem.ordinal(), false); } } mDrawerLayout.closeDrawer(mDrawerList); setTitle(navItem.getTitleResId()); mCurrentNavItem = navItem; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: if(mDrawerLayout.isDrawerOpen(mDrawerList)) { mDrawerLayout.closeDrawer(mDrawerList); } else { mDrawerLayout.openDrawer(mDrawerList); } return true; default: return super.onOptionsItemSelected(item); } } public void goToSearch(MenuItem item){ //go to search page Fragment Fragment_one; FragmentManager man= getSupportFragmentManager(); FragmentTransaction tran = man.beginTransaction(); Fragment_one = new Search(); tran.replace(R.id.main, Fragment_one);//tran. tran.addToBackStack(null); tran.commit(); } } 

StatisticsTab:

 public class StatisticsTab extends Fragment { private FragmentTabHost mTabHost; //Mandatory Constructor public StatisticsTab() { } public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_tabs,container, false); mTabHost = (FragmentTabHost)rootView.findViewById(android.R.id.tabhost); mTabHost.setup(getActivity(), getFragmentManager(), R.id.realtabcontent); mTabHost.addTab(mTabHost.newTabSpec("Basic").setIndicator("Basic"), StatisticsPage.class, null); mTabHost.addTab(mTabHost.newTabSpec("Brewery").setIndicator("Brewery"), BreweryStatistics.class, null); mTabHost.addTab(mTabHost.newTabSpec("Style").setIndicator("Style"), StyleStatistics.class, null); mTabHost.addTab(mTabHost.newTabSpec("Taste").setIndicator("Taste"), TasteStatisticsPage.class, null); return rootView; } } 

Один из моих фрагментов для вкладки в tabhost, который имеет listview:

 public class BreweryStatistics extends Fragment implements GetBreweryStatisticsJSON.OnArticleSelectedListener { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.brewery_statistics_layout, container, false); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); String userName = prefs.getString("userName", null); String userID = prefs.getString("userID", null); String url = "myURL"; //async task to get beer taste tag percents GetBreweryStatisticsJSON task = new GetBreweryStatisticsJSON(getActivity()); task.setOnArticleSelectedListener(this); task.execute(url); // Inflate the layout for this fragment return v; } @Override public void onArticleSelected(String bID){ //code to execute on click Fragment Fragment_one; FragmentManager man= getFragmentManager(); FragmentTransaction tran = man.beginTransaction(); Fragment_one = new BreweryPage2(); final Bundle bundle = new Bundle(); bundle.putString("breweryIDSent", bID); Fragment_one.setArguments(bundle); tran.replace(R.id.main, Fragment_one);//tran. tran.addToBackStack(null); tran.commit(); } } 

Моя задача Async для вышеприведенного фрагмента для загрузки списка:

 public class GetBreweryStatisticsJSON extends AsyncTask<String, Void, String> { Context c; private ProgressDialog Dialog; public GetBreweryStatisticsJSON(Context context) { c = context; Dialog = new ProgressDialog(c); } //***************************code for on click OnArticleSelectedListener listener; public interface OnArticleSelectedListener{ public void onArticleSelected(String myString); } public void setOnArticleSelectedListener(OnArticleSelectedListener listener){ this.listener = listener; } //*****************************end code for onClick protected void onPreExecute() { Dialog.setMessage("Analyzing breweries"); Dialog.setTitle("Loading"); Dialog.setCancelable(false); Dialog.show(); } @Override protected String doInBackground(String... arg0) { // TODO Auto-generated method stub return readJSONFeed(arg0[0]); } protected void onPostExecute(String result){ //decode json here try{ JSONArray jsonArray = new JSONArray(result); //acces listview ListView lv = (ListView) ((Activity) c).findViewById(R.id.yourBreweryStatistics); //make array list for beer final List<BreweryInfo> tasteList = new ArrayList<BreweryInfo>(); for(int i = 0; i < jsonArray.length(); i++) { String brewery = jsonArray.getJSONObject(i).getString("brewery"); String rate = jsonArray.getJSONObject(i).getString("rate"); String breweryID = jsonArray.getJSONObject(i).getString("id"); int count = i + 1; brewery = count + ". " + brewery; Log.d("brewery stats", brewery); //create object BreweryInfo tempTaste = new BreweryInfo(brewery, breweryID, rate); //add to arraylist tasteList.add(tempTaste); //add items to listview BreweryInfoAdapter adapter1 = new BreweryInfoAdapter(c ,R.layout.brewer_stats_listview, tasteList); lv.setAdapter(adapter1); //set up clicks lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { BreweryInfo o=(BreweryInfo)arg0.getItemAtPosition(arg2); String bID = o.breweryID; Log.d("breweryID" , bID); //todo: add brewery page link //********************* add listener listener.onArticleSelected(bID); } }); } } catch(Exception e){ } Dialog.dismiss(); } public String readJSONFeed(String URL) { StringBuilder stringBuilder = new StringBuilder(); HttpClient httpClient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(URL); try { HttpResponse response = httpClient.execute(httpGet); StatusLine statusLine = response.getStatusLine(); int statusCode = statusLine.getStatusCode(); if (statusCode == 200) { HttpEntity entity = response.getEntity(); InputStream inputStream = entity.getContent(); BufferedReader reader = new BufferedReader( new InputStreamReader(inputStream)); String line; while ((line = reader.readLine()) != null) { stringBuilder.append(line); } inputStream.close(); } else { Log.d("JSON", "Failed to download file"); } } catch (Exception e) { Log.d("readJSONFeed", e.getLocalizedMessage()); } return stringBuilder.toString(); } } 

Вы пытаетесь использовать фрагменты, вложенные в другие фрагменты, посредством FragmentTabHost.

В своем фрагменте StatisticsTab измените это:

 mTabHost.setup(getActivity(), getFragmentManager(), R.id.realtabcontent); 

к этому:

 mTabHost.setup(getActivity(), getChildFragmentManager(), R.id.realtabcontent); 

Затем обязательно используйте родительский FragmentManager для фиксации изменения основного фрагмента, изменив getFragmentManager() на getActivity().getSupportFragmentManager() внутри BreweryStatistics.onArticleSelected() .

Видеть:
ViewPager: рекурсивная запись в executePendingTransactions
Вложенные фрагменты с использованием библиотеки поддержки v4 версии 11