递归进入executePendingTransactions

时间:2014-03-03 15:41:02

标签: android android-listview android-fragments forceclose

我有一个MainDrawer to Fragment活动,它有一个导航抽屉的布局我和我的主要内容,我可以在其中加载新的碎片。我加载的一个片段是calle StatisticsTab Fragment。这个Fragment包含一个tabhost,每个tab都是它自己的listview项的片段。一旦我点击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,那么它就不会FC上。此外,当我回到它们时,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中有一个列表视图的选项卡:

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();

    }


}

我的异步任务,上面的片段加载listview:

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();
    }



}

1 个答案:

答案 0 :(得分:57)

您正试图通过FragmentTabHost使用嵌套在其他片段中的片段。

在您的StatisticsTab片段中,更改此:

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

到此:

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


然后,通过将getFragmentManager()更改为getActivity().getSupportFragmentManager()内的BreweryStatistics.onArticleSelected(),确保使用父FragmentManager提交主要片段更改。


请参阅:
ViewPager: Recursive entry to executePendingTransactions
Nested Fragments using support library v4 revision 11