IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Android Discussion :

Communication Fragment - Activity dans le cadre d'un FragmentPagerAdapter


Sujet :

Android

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 23
    Par défaut Communication Fragment - Activity dans le cadre d'un FragmentPagerAdapter
    Bonjour,
    Pour illustrer un problème que j'ai avec l'utilisation d'un FragmentPagerAdapter, voici une appli basique.
    Elle utilise un seul onglet. Le fragment de cet onglet utilise une interface renseignée lors d'un onAttach() pour communiquer avec son activity. L'activity utilise un getItem() du FragmentPagerAdapter pour communiquer avec le fragment actif.

    Voici la procédure : je clique sur le menu "Settings", l'activity appelle une fonction du fragment, qui appelle elle-même une fonction de l'activity.
    Cela fonctionne sans aucun problème jusqu'à ce que l'on change de format d'affichage (on tourne l'appareil). Là j'ai l'impression que lorsque l'on reconstruit l'activity, on reconstruit bien un nouveau fragment, mais que l'ancien reste toujours actif... Et lorsque le fragment appelle l'activity, on utilise un pointeur null pour l'interface renseignée lors d'un onAttach()...

    J'aimerai comprendre pourquoi cela se passe ainsi pour avancer dans mes connaissances. De même, la mémorisation des fragments dans mon FragmentPagerAdapter n'est peut-être pas la meilleure solution. Il faudrait mieux rechercher le bon fragment par son nom ou id, mais comment faire ?

    Je vous remercie par avance pour votre aide, et veuillez me pardonner si ce sujet à déjà été traité...

    Voici le code pour l'activity :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
     
    public class MainActivity extends Activity implements ActionBar.TabListener,
            MainListGeneralFragment.mainListener
    {
        SectionsPagerAdapter mSectionsPagerAdapter;
     
        ViewPager mViewPager;
     
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_my);
     
            final ActionBar actionBar = getActionBar();
            actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
     
            mSectionsPagerAdapter = new SectionsPagerAdapter(getFragmentManager());
     
            mViewPager = (ViewPager) findViewById(R.id.pager);
            mViewPager.setAdapter(mSectionsPagerAdapter);
     
            mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener()
            {
                @Override
                public void onPageSelected(int position)
                {
                    actionBar.setSelectedNavigationItem(position);
                }
            });
     
            for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++)
            {
                actionBar.addTab(actionBar.newTab().setText(mSectionsPagerAdapter.getPageTitle(i))
                        .setTabListener(this));
            }
        }
     
        @Override
        public boolean onCreateOptionsMenu(Menu menu)
        {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.my, menu);
            return true;
        }
     
        @Override
        public boolean onOptionsItemSelected(MenuItem item)
        {
            final MainListGeneralFragment fragCurrentFragment =
                    (MainListGeneralFragment) mSectionsPagerAdapter.getItem(mViewPager.getCurrentItem());
            fragCurrentFragment.onTest();
     
            return true;//super.onOptionsItemSelected(item);
        }
     
        @Override
        public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
        {
            // When the given tab is selected, switch to the corresponding page in
            // the ViewPager.
            mViewPager.setCurrentItem(tab.getPosition());
        }
     
        @Override
        public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
        {
        }
     
        @Override
        public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
        {
        }
     
        private class SectionsPagerAdapter extends FragmentPagerAdapter
        {
            private Fragment[] priv_fragListPages;
     
            public SectionsPagerAdapter(FragmentManager fm)
            {
                super(fm);
     
                priv_fragListPages = new Fragment[1];
                priv_fragListPages[0] = null;
            }
     
            @Override
            public Fragment getItem(int intPosition)
            {
                if (priv_fragListPages[intPosition] == null)
                {
                    Fragment fNewFragment;
     
                    fNewFragment = MainListGeneralFragment.newInstance();
                    priv_fragListPages[intPosition] = fNewFragment;
                }
     
                return priv_fragListPages[intPosition];
            }
     
            @Override
            public int getCount()
            {
                return 1;
            }
     
            @Override
            public CharSequence getPageTitle(int position)
            {
                return "Test";
            }
        }
     
        public String getTextToShow()
        {
            return "A que coucou !!!";
        }
    }
    Pour le fragment :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
     
    public class MainListGeneralFragment extends Fragment
    {
        public interface mainListener
        {
            public String getTextToShow();
        }
     
        private mainListener priv_mlListener;
     
        public static MainListGeneralFragment newInstance()
        {
            MainListGeneralFragment fragment = new MainListGeneralFragment();
     
            return fragment;
        }
     
        public MainListGeneralFragment()
        {
        }
     
        @Override
        public void onAttach(Activity activity)
        {
            super.onAttach(activity);
     
            try
            {
                priv_mlListener = (mainListener) activity;
            }
            catch (ClassCastException e)
            {
                throw new ClassCastException(activity.toString() + " must implement mainListener");
            }
        }
     
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState)
        {
            return inflater.inflate(R.layout.fragment_my, container, false);
        }
     
        public void onTest()
        {
            priv_mlListener.getTextToShow();
        }
    }
    PS : Une coquille était resté dans le code de l'activity. J'ai retiré la ligne...

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    10
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 10
    Par défaut
    Effectivement ton fragment continue d'exister et tu recrée un nouveau fragment a chaque "onconfigchange".

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
            public SectionsPagerAdapter(FragmentManager fm)
            {
                super(fm);
     
                priv_fragListPages = new Fragment[1];
                priv_fragListPages[0] = null;
            }
     
            @Override
            public Fragment getItem(int intPosition)
            {
                if (priv_fragListPages[intPosition] == null)
                {
                    Fragment fNewFragment;
     
                    fNewFragment = MainListGeneralFragment.newInstance();
                    priv_fragListPages[intPosition] = fNewFragment;
                }
     
                return priv_fragListPages[intPosition];
            }
    Pour réutiliser ton fragment il faut que tu lui attribue un "tag" avec ton FragmentManager (ce qui te permettra de le retrouver par la suite).

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 23
    Par défaut
    Merci Poopaou.

    Finalement, j'utilise onSaveInstanceState() pour sauvegarder la liste des tags des fragments sauvegardés dans mon SectionsPagerAdapter, et je vais chercher manuellement ces fragments lors d'un onCreate avec le Bundle non null. Cela permet de libérer l'espace mémoire si besoin est pour les autres appli (non utilisation de setRetainInstance pour respecter les spec Google) et de ne pas savoir comment la librairie "code" le tag des fragments (pour éviter les problèmes du type passage Windows 3.11 à 95).

    Cela donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
     
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
        ...
            mSectionsPagerAdapter = new SectionsPagerAdapter(getFragmentManager());
     
            if (savedInstanceState != null)
            {
                mSectionsPagerAdapter.setFragSavedInstance(savedInstanceState);
            }
     
            ...
     
            if (actionBar.getTabCount() == 0)
            {
                for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++)
                {
                    actionBar.addTab(actionBar.newTab().setText(mSectionsPagerAdapter.getPageTitle(i))
                            .setTabListener(this));
                }
            }
        }
     
        @Override
        public void onSaveInstanceState(Bundle savedInstanceState)
        {
            mSectionsPagerAdapter.setBundleSavedInstance(savedInstanceState);
     
            super.onSaveInstanceState(savedInstanceState);
        }
     
        private class SectionsPagerAdapter extends FragmentPagerAdapter
        {
        ...
            public void setBundleSavedInstance(Bundle savedInstanceState)
            {
                String[] strArrayFragName = new String[1];
     
                for(int Bcl = (priv_fragListPages.length - 1); Bcl >= 0; Bcl--)
                {
                    if (priv_fragListPages[Bcl] != null)
                    {
                        strArrayFragName[Bcl] = priv_fragListPages[Bcl].getTag();
                    }
                }
     
                savedInstanceState.putStringArray(ACTIVITY_FRAG_LIST_TAG, strArrayFragName);
            }
     
            public void setFragSavedInstance(Bundle savedInstanceState)
            {
                String[] strArrayFragName = savedInstanceState.getStringArray(ACTIVITY_FRAG_LIST_TAG);
     
                for(int Bcl = (strArrayFragName.length - 1); Bcl >= 0; Bcl--)
                {
                    if (strArrayFragName[Bcl] != null)
                    {
                        FragmentManager fmFragManager = getFragmentManager();
                        priv_fragListPages[Bcl] = fmFragManager.findFragmentByTag(strArrayFragName[Bcl]);
                    }
                }
            }
        }
    Cependant, un truc me gêne encore avec ce SectionsPagerAdapter, après la lecture des deux liens. En effet, il est dit plusieurs fois que l'adapteur SectionsPagerAdapter n'est pas fait pour communiquer avec les fragments.
    Mais comment notifier un événement menu ou un onActivityResult() aux fragments sans utiliser le type de mécanisme décrit ci-dessus, puisque c'est l'activity qui reçoit ces notifications ?
    Autrement dit comment l'activity devrait communiquer avec les fragments... ?

    PS : J'ai modifié l'activity pour que cela fonctionne mieux...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Lancer une Activity dans un Fragment ?
    Par L'Atreide dans le forum Android
    Réponses: 2
    Dernier message: 10/03/2013, 00h21
  2. [XSLT] Utilisation de XML avec PHP dans le cadre d'un site
    Par nicolas66 dans le forum Bibliothèques et frameworks
    Réponses: 15
    Dernier message: 06/11/2005, 22h39
  3. Forcer l'affichage d'une page dans un cadre
    Par Thcan dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 02/11/2005, 10h58
  4. [Javascript] Javascript active dans navigateur
    Par nico33307 dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 07/08/2005, 14h31
  5. Comment écrire sur une image, dans un cadre ?
    Par Nutrino dans le forum Balisage (X)HTML et validation W3C
    Réponses: 7
    Dernier message: 20/05/2005, 00h55

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo