Comment passer des valeurs entre des fragments

109

Je suis assez nouveau dans l'utilisation de Fragments.

J'essaie juste de créer un exemple d'application simple qui utilise des fragments. Mon scénario est, j'ai deux activités avec un fragment à l'intérieur de chaque activité. Le premier fragment a un edittext et un bouton. Le deuxième fragment a une vue de texte. Lorsque j'entre un nom dans l'edittext et clique sur le bouton, la vue de texte dans le deuxième fragment doit afficher le nom entré dans l'edittext du premier fragment.

J'ai pu envoyer la valeur du premier fragment à son activité, puis de cette activité à la deuxième activité. Maintenant, comment utiliser cette valeur dans le deuxième fragment.

Voici le code Java :::

package com.example.fragmentexample;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class Fragment_1 extends Fragment{

    OnFragmentChangedListener mCallback;

    // Container Activity must implement this interface
    public interface OnFragmentChangedListener {
        public void onButtonClicked(String name);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {
            mCallback = (OnFragmentChangedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnHeadlineSelectedListener");
        }
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // TODO Auto-generated method stub      

        View view = inflater.inflate(R.layout.fragment_fragment_1, container, false);

        final EditText edtxtPersonName_Fragment = (EditText) view.findViewById(R.id.edtxtPersonName);
        Button btnSayHi_Fragment = (Button) view.findViewById(R.id.btnSayHi);

        btnSayHi_Fragment.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

                String name = edtxtPersonName_Fragment.getText().toString();

                FragmentManager fm = getFragmentManager();
                Fragment_2 f2 = (Fragment_2) fm.findFragmentById(R.id.fragment_content_2);

                Activity activity = getActivity();

                if(activity != null)
                {
                    Toast.makeText(activity, "Say&ing Hi in Progress...", Toast.LENGTH_LONG).show();
                }


                if(f2 != null && f2.isInLayout())
                {
                    f2.setName(name);
                }
                else
                {
                    mCallback.onButtonClicked(name);
                }
            }
        });

        return view;


    }

}

MainActivity.Java

package com.example.fragmentexample;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;

import android.view.Choreographer.FrameCallback;
import android.view.Menu;

public class MainActivity extends Activity implements Fragment_1.OnFragmentChangedListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);     
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    @Override
    public void onButtonClicked(String name) {
        // TODO Auto-generated method stub

        Intent i = new Intent(this, SecondActivity.class);
        i.putExtra("", name);
        startActivity(i);
    }

}

SecondActivity.Java

package com.example.fragmentexample;

import android.app.Activity;
import android.os.Bundle;

public class SecondActivity extends Activity{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_second);

        Bundle b = getIntent().getExtras();

        Fragment_2 f2 = new Fragment_2();
        f2.setArguments(b);
    }
}

Fragment_2.Java

package com.example.fragmentexample;

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class Fragment_2 extends Fragment{

    View view;
    TextView txtName;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // TODO Auto-generated method stub

        view = inflater.inflate(R.layout.fragment_fragment_2, container, false);

            // Exception at this line
        String name = getArguments().getString("message");
        txtName = (TextView) view.findViewById(R.id.txtViewResult);
        txtName.setText(name);

        return view;
    }

    @Override
    public void onAttach(Activity activity) {
        // TODO Auto-generated method stub
        super.onAttach(activity);       
    }

    public void setName(String name)
    {   
        txtName.setText("Hi " + name);
    }

}

J'obtiens l'exception suivante :::

04-16 18:10:24.573: E/AndroidRuntime(713): FATAL EXCEPTION: main
04-16 18:10:24.573: E/AndroidRuntime(713): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.fragmentexample/com.example.fragmentexample.SecondActivity}: android.view.InflateException: Binary XML file line #8: Error inflating class fragment
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1815)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1831)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.ActivityThread.access$500(ActivityThread.java:122)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1024)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.os.Handler.dispatchMessage(Handler.java:99)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.os.Looper.loop(Looper.java:132)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.ActivityThread.main(ActivityThread.java:4123)
04-16 18:10:24.573: E/AndroidRuntime(713):  at java.lang.reflect.Method.invokeNative(Native Method)
04-16 18:10:24.573: E/AndroidRuntime(713):  at java.lang.reflect.Method.invoke(Method.java:491)
04-16 18:10:24.573: E/AndroidRuntime(713):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
04-16 18:10:24.573: E/AndroidRuntime(713):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
04-16 18:10:24.573: E/AndroidRuntime(713):  at dalvik.system.NativeStart.main(Native Method)
04-16 18:10:24.573: E/AndroidRuntime(713): Caused by: android.view.InflateException: Binary XML file line #8: Error inflating class fragment
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:688)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.view.LayoutInflater.rInflate(LayoutInflater.java:724)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.view.LayoutInflater.inflate(LayoutInflater.java:479)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.view.LayoutInflater.inflate(LayoutInflater.java:391)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.view.LayoutInflater.inflate(LayoutInflater.java:347)
04-16 18:10:24.573: E/AndroidRuntime(713):  at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:223)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.Activity.setContentView(Activity.java:1786)
04-16 18:10:24.573: E/AndroidRuntime(713):  at com.example.fragmentexample.SecondActivity.onCreate(SecondActivity.java:13)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.Activity.performCreate(Activity.java:4397)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1048)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1779)
04-16 18:10:24.573: E/AndroidRuntime(713):  ... 11 more
04-16 18:10:24.573: E/AndroidRuntime(713): Caused by: java.lang.NullPointerException
04-16 18:10:24.573: E/AndroidRuntime(713):  at com.example.fragmentexample.Fragment_2.onCreateView(Fragment_2.java:24)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:754)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:956)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.FragmentManagerImpl.addFragment(FragmentManager.java:1035)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.app.Activity.onCreateView(Activity.java:4177)
04-16 18:10:24.573: E/AndroidRuntime(713):  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:664)
04-16 18:10:24.573: E/AndroidRuntime(713):  ... 21 more

Comment obtenir la valeur du bundle de SecondActivity.java vers Fragment_2.Java?

Vamsi Challa
la source
Veuillez mettre en évidence la partie où ru obtient le problème
Nikhil Agrawal
solution de travail avec un moyen facile: stackoverflow.com/a/59332751/10201722
Adil Siddiqui

Réponses:

203

étape 1 .pour envoyer les données du fragment à l'activité

Intent intent = new Intent(getActivity().getBaseContext(),
                        TargetActivity.class);
                intent.putExtra("message", message);
                getActivity().startActivity(intent);

Étape 2. pour recevoir ces données dans l'activité:

Intent intent = getIntent();
String message = intent.getStringExtra("message");

étape 3 . pour envoyer des données d'une activité à une autre activité suivre l'approche normale

Intent intent = new Intent(MainActivity.this,
                        TargetActivity.class);
                intent.putExtra("message", message);
                startActivity(intent);

étape 4 pour recevoir ces données en activité

     Intent intent = getIntent();
  String message = intent.getStringExtra("message");

Étape 5. À partir de l'activité, vous pouvez envoyer des données à Fragment avec l'intention comme:

Bundle bundle=new Bundle();
bundle.putString("message", "From Activity");
  //set Fragmentclass Arguments
Fragmentclass fragobj=new Fragmentclass();
fragobj.setArguments(bundle);

et pour recevoir en fragment dans la méthode Fragment onCreateView:

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
    Bundle savedInstanceState) {
          String strtext=getArguments().getString("message");

    return inflater.inflate(R.layout.fragment, container, false);
    }
Shiv
la source
2
J'ai essayé l'étape 5, que j'appelle listactivity à partir d'un fragment et après avoir sélectionné l'élément de cette activité, je veux revenir en fragment avec le nom de fichier sélectionné. Mais cela ne fonctionne pas, cela me donne une exception Nullpointer à onCreateView. Une solution à ce sujet s'il vous plaît? C'est ma question stackoverflow.com/questions/18208771/…
OnkarDhane
comment mettre un POJO ici? bundle.putString("message", "From Activity");
jeet.chanchawat
31
Quelqu'un est-il dégoûté de la complexité de faire quelque chose comme ça?
Ed Lee
1
Exactement Eddie, ce n'est pas la bonne manière. Ils doivent utiliser des interfaces pour communiquer entre les fragments via l'activité du conteneur.
Kaveesh Kanwal
Concernant l'utilisation d'interfaces pour communiquer entre fragments: developer.android.com/training/basics/fragments/…
Andre L Torres
49

Comme indiqué sur le site du développeur

Vous souhaiterez souvent qu'un fragment communique avec un autre, par exemple pour modifier le contenu en fonction d'un événement utilisateur. Toutes les communications de fragment à fragment se font via l'activité associée. Deux fragments ne doivent jamais communiquer directement.

la communication entre les fragments doit se faire via l'activité associée.

Ayons les composants suivants:

Une activité héberge des fragments et permet la communication de fragments

FragmentUn premier fragment qui enverra des données

FragmentB second fragment qui recevra les données de FragmentA

L'implémentation de FragmentA est:

public class FragmentA extends Fragment 
{
    DataPassListener mCallback;
    
    public interface DataPassListener{
        public void passData(String data);
    }

    @Override
    public void onAttach(Context context) 
    {
        super.onAttach(context);
        // This makes sure that the host activity has implemented the callback interface
        // If not, it throws an exception
        try 
        {
            mCallback = (OnImageClickListener) context;
        }
        catch (ClassCastException e) 
        {
            throw new ClassCastException(context.toString()+ " must implement OnImageClickListener");
        }
    }
    
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) 
    {
        // Suppose that when a button clicked second FragmentB will be inflated
        // some data on FragmentA will pass FragmentB
        // Button passDataButton = (Button).........
        
        passDataButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (view.getId() == R.id.passDataButton) {
                    mCallback.passData("Text to pass FragmentB");
                }
            }
        });
    }
}

La mise en œuvre de MainActivity est:

public class MainActivity extends ActionBarActivity implements DataPassListener{
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        if (findViewById(R.id.container) != null) {
            if (savedInstanceState != null) {
                return;
            }
            getFragmentManager().beginTransaction()
                    .add(R.id.container, new FragmentA()).commit();
        }
    }
    
    @Override
    public void passData(String data) {
        FragmentB fragmentB = new FragmentB ();
        Bundle args = new Bundle();
        args.putString(FragmentB.DATA_RECEIVE, data);
        fragmentB .setArguments(args);
        getFragmentManager().beginTransaction()
            .replace(R.id.container, fragmentB )
            .commit();
    }
}

L'implémentation de FragmentB est:

public class FragmentB extends Fragment{
    final static String DATA_RECEIVE = "data_receive";
    TextView showReceivedData;
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_B, container, false);
        showReceivedData = (TextView) view.findViewById(R.id.showReceivedData);
    }
    
    @Override
    public void onStart() {
        super.onStart();
        Bundle args = getArguments();
        if (args != null) {
            showReceivedData.setText(args.getString(DATA_RECEIVE));
        }
    }
}

J'espère que cela vous aidera.

Ozhanli
la source
4
Qu'est-ce que OnImageClickListener ici? et comment est-il converti en une variable DataPassListener?
Harsha
J'ai trouvé que c'était le "DataPassListener". Je l'ai fait fonctionner, mais seulement pour trouver à chaque fois que le bouton est cliqué, les données sont envoyées. Lorsqu'il est envoyé, il remplace le fragment. Ce qui signifie que la liste est renouvelée à chaque fois. Par conséquent, ne pas conserver la liste des éléments en mémoire.
wesley franks le
44

// Dans Fragment_1.java

Bundle bundle = new Bundle();
bundle.putString("key","abc"); // Put anything what you want

Fragment_2 fragment2 = new Fragment_2();
fragment2.setArguments(bundle);

getFragmentManager()
      .beginTransaction()
      .replace(R.id.content, fragment2)
      .commit();

// Dans Fragment_2.java

Bundle bundle = this.getArguments();

if(bundle != null){
     // handle your code here.
}

J'espère que cela vous aidera.

Nguyencse
la source
1
Réponse propre pour montrer le point principal. utiliser putString(ou putInt) est la réponse!
Mehdi Dehghani
22

Depuis le site Web des développeurs :

Vous souhaiterez souvent qu'un fragment communique avec un autre, par exemple pour modifier le contenu en fonction d'un événement utilisateur. Toutes les communications de fragment à fragment se font via l'activité associée. Deux fragments ne doivent jamais communiquer directement.

Vous pouvez communiquer entre les fragments à l'aide de son activité. Vous pouvez communiquer entre l'activité et le fragment en utilisant cette approche.

Veuillez vérifier également ce lien.

Jainendra
la source
Le deuxième lien que vous avez donné montre comment communiquer entre des fragments lorsqu'ils sont dans la même activité. Comment communiquer lorsque les deux participent à des activités différentes?
Vamsi Challa
5

Tout d'abord, toutes les réponses sont correctes, vous pouvez transmettre les données à l'exception des objets personnalisés en utilisant Intent. Si vous souhaitez transmettre les objets personnalisés, vous devez implémenter Serialazableou Parcelableà votre classe d'objets personnalisés. J'ai trouvé que c'était trop compliqué ...

Donc, si votre projet est simple, essayez d'utiliser DataCache. Cela fournit un moyen très simple de transmettre des données. Réf: Projet Github CachePot

1- Réglez ceci sur Afficher ou Activité ou Fragment qui enverra des données

DataCache.getInstance().push(obj);

2- Obtenez des données n'importe où comme ci-dessous

public class MainFragment extends Fragment
{
    private YourObject obj;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        obj = DataCache.getInstance().pop(YourObject.class);

    }//end onCreate()
}//end class MainFragment
Kimkevin
la source
Ne serait-il pas plus facile d'utiliser une classe supplémentaire avec des valeurs statiques à l'intérieur? Ces valeurs sont ensuite accessibles par les deux fragments, il n'est donc pas nécessaire d'utiliser une bibliothèque supplémentaire pour mettre en cache les objets personnalisés.
Néph
4

La dernière solution de transmission de données entre fragments peut être mise en œuvre à l'aide de composants architecturaux Android tels que ViewModel et LiveData. Avec cette solution, vous n'avez pas besoin de définir une interface pour la communication et pouvez bénéficier des avantages de l'utilisation de viewmodel comme la survie des données en raison des changements de configuration.

Dans cette solution, les fragments impliqués dans la communication partagent le même objet viewmodel qui est lié à leur cycle de vie d'activité. L'objet de modèle de vue contient un objet livingata. Un fragment définit les données à transmettre sur l'objet livingata et le second fragment observateurs a vécu les changements et a reçu les données.

Voici l'exemple complet http://www.zoftino.com/passing-data-between-android-fragments-using-viewmodel

Arnav Rao
la source
3

Passer des arguments entre les fragments. C'est assez tard pour répondre à cette question mais cela pourrait aider quelqu'un! Fragment_1.java

Bundle i = new Bundle(); 
            i.putString("name", "Emmanuel");

            Fragment_1 frag = new Fragment_1();
            frag.setArguments(i);
            FragmentManager fragmentManager = getFragmentManager();
            fragmentManager.beginTransaction()
                    .replace(R.id.content_frame
                            , new Fragment_2())
                    .commit();

Ensuite, dans votre, Fragment_2.javavous pouvez obtenir les paramètres normalement dans votre onActivityCreated par exemple

 Intent intent = getActivity().getIntent();
    if (intent.getExtras() != null) {
        String name =intent.getStringExtra("name");
    }
Emmanuel R
la source
3

Je pense qu'un bon moyen de résoudre ce problème est d'utiliser une interface personnalisée.

Disons que vous avez deux fragments (A et B) qui sont à l'intérieur de la même activité et que vous souhaitez envoyer des données de A à B.

Interface:

public interface OnDataSentListener{
    void onDataSent(Object data);
}

Activité:

    public class MyActivity extends AppCompatActivity{

            private OnDataSentListener onDataSentListener;

            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_activity);

                FragmentTransaction trans = getFragmentManager().beginTransaction();

                FragmentA fa = new FragmentA();
                FragmentB fb = new FragmentB();

               fa.setOnDataSentListener(new Listeners.OnDataSentListener() {
                    @Override
                    public void onDataSent(Object data) {
                         if(onDataSentListener != null)  onDataSentListener.onDataSent(data);
                    }
               });

                transaction.add(R.id.frame_a, fa);
                transaction.add(R.id.frame_b, fb);

                transaction.commit();
            }

            public void setOnDataSentListener(OnDataSentListener listener){
                this.onDataSentListener = listener;
            }
        }

Fragment A:

public class FragmentA extends Fragment{

    private OnDataSentListener onDataSentListener;

    private void sendDataToFragmentB(Object data){
        if(onDataSentListener != null) onDataSentListener.onDataSent(data);
    }

    public void setOnDataSentListener(OnDataSentListener listener){
        this.onDataSentListener = listener;
    }
}

Fragment B:

public class FragmentB extends Fragment{

    private void initReceiver(){
        ((MyActivity) getActivity()).setOnDataSentListener(new OnDataSentListener() {
            @Override
            public void onDataSent(Object data) {
                //Here you receive the data from fragment A
            }
        });
    }
}
simpleApps
la source
2

La communication entre les fragments est assez compliquée (je trouve le concept d'auditeurs un peu difficile à mettre en œuvre).

Il est courant d'utiliser un "bus d'événements" pour résumer ces communications. Il s'agit d'une bibliothèque tierce qui s'occupe de cette communication pour vous.

«Otto» est celui qui est souvent utilisé pour ce faire, et pourrait valoir la peine d'être consulté: http://square.github.io/otto/

crotte de nez
la source
2

Passer des données d'un fragment à un autre fragment

  • Du premier fragment

    // Set data to pass
    MyFragment fragment = new MyFragment(); //Your Fragment
    Bundle bundle = new Bundle();
    bundle.putInt("year", 2017)  // Key, value
    fragment.setArguments(bundle); 
    // Pass data to other Fragment
    getFragmentManager()
     .beginTransaction()
     .replace(R.id.content, fragment)
     .commit(); 
  • Sur le deuxième fragment

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
    
         Bundle bundle = this.getArguments();
         if (bundle != null) {
             Int receivedYear = bundle.getInt("year", ""); // Key, default value
         } 
    }
Esprit de solution
la source
1

Cette implémentation simple permet de transmettre des données entre les fragments de manière simple. Vous pensez que vous souhaitez transmettre des données de «Frgment1» à «Fragment2»

Dans Fragment1 (définir les données à envoyer)

 Bundle bundle = new Bundle();
 bundle.putString("key","Jhon Doe"); // set your parameteres

 Fragment2 nextFragment = new Fragment2();
 nextFragment.setArguments(bundle);

 FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
 fragmentManager.beginTransaction().replace(R.id.content_drawer, nextFragment).commit();

Dans la méthode Fragment2 onCreateView (obtenir les paramètres)

String value = this.getArguments().getString("key");//get your parameters
Toast.makeText(getActivity(), value+" ", Toast.LENGTH_LONG).show();//show data in tost
Janaka
la source
Dans mon application, j'essaie de faire fonctionner cela, mais d'une manière ou d'une autre, bien que la valeur soit transmise, elle n'est pas affichée sur fragment2, je pense que je fais une erreur en définissant R.id.content_drawer. Quelqu'un peut-il me guider quel pourrait être le bon identifiant pour R.id.content_drawer avec l'exemple .xml.
falcon
1

Voie Kotlin

Utilisez une SharedViewModelproposition dans la documentation officielle de ViewModel

Il est très courant que deux fragments ou plus d'une activité aient besoin de communiquer entre eux. Imaginez un cas courant de fragments maître-détails, où vous avez un fragment dans lequel l'utilisateur sélectionne un élément dans une liste et un autre fragment qui affiche le contenu de l'élément sélectionné. Ce cas n'est jamais anodin car les deux fragments doivent définir une description d'interface et l'activité du propriétaire doit lier les deux ensemble. En outre, les deux fragments doivent gérer le scénario dans lequel l'autre fragment n'est pas encore créé ou visible.

Ce problème commun peut être résolu à l'aide d'objets ViewModel. Ces fragments peuvent partager un ViewModel en utilisant leur étendue d'activité pour gérer cette communication

Commencez par implémenter fragment-ktx pour instancier votre viewmodel plus facilement

dependencies {
    implementation "androidx.fragment:fragment-ktx:1.2.2"
} 

Ensuite, il vous suffit de mettre dans le viewmodel les données que vous partagerez avec l'autre fragment

class SharedViewModel : ViewModel() {
    val selected = MutableLiveData<Item>()

    fun select(item: Item) {
        selected.value = item
    }
}

Ensuite, pour terminer, instanciez simplement votre viewModel dans chaque fragment et définissez la valeur de à selectedpartir du fragment dont vous souhaitez définir les données

Fragment A

class MasterFragment : Fragment() {

    private val model: SharedViewModel by activityViewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        itemSelector.setOnClickListener { item ->
        model.select(item)
      }

    }
}

Et puis, écoutez simplement cette valeur à votre destination Fragment

Fragment B

 class DetailFragment : Fragment() {

        private val model: SharedViewModel by activityViewModels()

        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            model.selected.observe(viewLifecycleOwner, Observer<Item> { item ->
                // Update the UI
            })
        }
    }

Vous pouvez également le faire dans le sens inverse

Gastón Saillén
la source
0

Solution 100% fonctionnelle: (si vous aidez, n'oubliez pas de voter pour)

Dans votre premier fragment, mettez ce morceau de code:

    editprofile.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    Fragment_editprofile Fragment = new Fragment_editprofile();
.
.
.
.
.


                Fragment.getintentdetails(tv_name.getText().toString(),
                            tv_mob.getText().toString(), tv_email.getText().toString(), tv_dob.getText().toString(),
                            tv_gender.getText().toString(), photointent);

                }
            });

Dans Second Fragment, faites une méthode comme ci-dessous:

public void getintentdetails(String name, String mobile, String email, String dob, String gender,
                                 String photointent) {

        this.name_str= name;
        this.mob_str= mobile;
        this.email_str= email;
        this.dob_str= dob;
        this.gender_str= gender;
        this.photo_str= photointent;

    }

puis définissez une variable au niveau de la classe:

String name_str, mob_str, dob_str, photo_str, email_str, gender_str;

puis faites une autre méthode dans le second fragment pour définir la valeur:

  setexistingdetails();


private void setexistingdetails() {

        if(!name_str.equalsIgnoreCase(""))
            (et_name).setText(name_str);
        if(!mob_str.equalsIgnoreCase(""))
            et_mobile.setText(mob_str);
        if(!email_str.equalsIgnoreCase(""))
            email_et.setText(email_str);
        if(!dob_str.equalsIgnoreCase(""))
            dob_et.setText(dob_str);
        if(!gender_str.equalsIgnoreCase("")){
            if (gender_str.equalsIgnoreCase("m")){
                male_radio.setChecked(true);
            }else {
                female_radio.setChecked(true);
            }
        }
        if(!photo_str.equalsIgnoreCase("")){
            try {
                Picasso.get().load(Const.BASE_PATH+"include/sub-domain/GENIUS/"+photo_str).into(adminpropic_edit);
            } catch (Exception e) {            }
        }
    }
Adil Siddiqui
la source
0

Vous pouvez atteindre votre objectif avec ViewModel et Live Data qui est effacé par Arnav Rao . Maintenant, je mets un exemple pour le clarifier plus nettement.

Tout d'abord, le supposé ViewModelest nommé SharedViewModel.java.

public class SharedViewModel extends ViewModel {
    private final MutableLiveData<Item> selected = new MutableLiveData<Item>();

    public void select(Item item) {
        selected.setValue(item);
    }
    public LiveData<Item> getSelected() {
        return selected;
    }
}

Ensuite, le fragment source est l' MasterFragment.javaendroit d'où nous voulons envoyer une donnée.

public class MasterFragment extends Fragment {
    private SharedViewModel model;

    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
        itemSelector.setOnClickListener(item -> {

            // Data is sent

            model.select(item);
        });
    }
}

Et enfin, le fragment de destination est l' DetailFragment.javaendroit où nous voulons recevoir les données.

public class DetailFragment extends Fragment {

    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        SharedViewModel model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
        model.getSelected().observe(getViewLifecycleOwner(), { item ->

           // Data is received 

        });
    }
}
Gk Mohammad Emon
la source
0

OK après tant de fouilles ici, j'ai trouvé une solution simple, en fait, vous ne devriez jamais transmettre les données d'un fragment à un fragment, c'est toujours une mauvaise idée, vous pouvez transmettre les données du fragment A à l'activité et obtenir les données de l'activité dans le fragment B.

For Example
//fragment A
//your method that will be called in Main Activity for getting data from this fragment
public List<customDataModel> getlist(){
return mlist; //your custom list 
}
buttonopen.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //before calling  your new fragment, send a Broadcast signal to your main activity
 mContext.sendBroadcast(new Intent("call.myfragment.action"));
//here you are now changing the fragment
Fragment fragment1 = new VolunteerListDetailsFragment();

            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            ft.replace(R.id.content_frame, fragment1);
            ft.commit();
        }
    });

// dans l'activité principale

this.registerReceiver(mBroadcastReceiver, new IntentFilter("call.myfragment.action"));//this line should be in your onCreate method
   BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
//init the fragment A
FragmenA fragment =
                (FragmentA) getSupportFragmentManager().findFragmentById(R.id.content_frame);
        mlistdetails = fragment.getlist();//this is my method in fragmentA which is retuning me a custom list, init this list type in top of on create fragment


    }
};
//here you are creating method that is returning the list that you just recieved From fragmentA
public List<customDataModel> getcustomlist(){
return mlistdetails; //you are returning the same list that you recived from fragmentA
}

// maintenant dans FragmentB

 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    View rootView = (View) inflater.inflate(R.layout.vol_listdetails, container, false);

    mlistdetails=((MainActivity)getActivity()).getcustomlist();//here you are calling the method that you have created in Main Activity

    Toast.makeText(getActivity().getApplicationContext(), mlistdetails.get(0).getItemqty(), Toast.LENGTH_SHORT).show();
    return rootView;

}
Mubashir Murtaza
la source
-2

J'ai fait quelque chose de vraiment facile pour les débutants comme moi .. j'ai fait une vue de texte dans mon activity_main.xml et mis

id=index
visibility=invisible

puis j'obtiens cette vue de texte du premier fragment

index= (Textview) getActivity().findviewbyid(R.id.index)
index.setText("fill me with the value")

puis dans le deuxième fragment j'obtiens la valeur

index= (Textview) getActivity().findviewbyid(R.id.index)
String get_the_value= index.getText().toString();

J'espère que ça aide!

user7933515
la source
La réponse n'est pas liée à la question posée
Kanagalingam