web-dev-qa-db-fra.com

Entrée récursive pour exécuterPendingTransactions

J'ai une activité MainDrawer to Fragment qui a une disposition pour un tiroir de navigation mon et mon contenu principal dans lequel je peux charger de nouveaux fragments. Un fragment que je charge est calle StatisticsTab Fragment. Ce fragment contient un tabhost dont chaque onglet est son propre fragment d'éléments listview. Une fois que j'ai cliqué sur un élément ListView, qui charge un autre nouveau fragment et que je ne suis plus dans tabHost et que j'essaie de revenir en utilisant le navigateur de navigation vers mon fragment StatisticsTab, j'obtiens cette erreur:

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)

Si je ne clique sur aucun de mes onglets sur le fragment StatisticsTab et que je navigue vers un autre fragment via le navdrawer, puis reviens à StatisticsTab, il ne sera pas activé. Aucun des autres fragments de la force NavDrawer ne se ferme également lorsque je reviens à eux, juste celui avec les onglets.

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

    }



}

Onglet Statistics:

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




}

Un de mes fragments pour un onglet dans le tabhost qui a une vue de liste:

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

    }


}

Ma tâche Async pour le fragment ci-dessus pour charger la vue de liste:

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



}
23
Mike

Vous essayez d'utiliser des fragments imbriqués dans d'autres fragments, via votre FragmentTabHost.

Dans votre fragment StatisticsTab, changez ceci:

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

pour ça:

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


Ensuite, assurez-vous d'utiliser le parent FragmentManager pour valider la modification du fragment principal, en remplaçant getFragmentManager() par getActivity().getSupportFragmentManager() dans BreweryStatistics.onArticleSelected().


Voir:
ViewPager: entrée récursive pour exécuterPendingTransactions
Fragments imbriqués utilisant la bibliothèque de support v4 révision 11

57
Bryan Dunlap