Come passare valori tra frammenti


109

Sono abbastanza nuovo nell'usare i frammenti.

Sto solo cercando di creare una semplice applicazione di esempio che utilizzi Fragments. Il mio scenario è che ho due attività con un frammento all'interno di ciascuna attività. Il primo frammento ha un testo ed un pulsante. Il secondo frammento ha una visualizzazione del testo. Quando inserisco un nome nel testo edito e clicco sul pulsante, la vista di testo nel secondo frammento dovrebbe visualizzare il nome inserito nel testo editato del primo frammento.

Sono stato in grado di inviare il valore dal primo frammento alla sua attività e poi da quell'attività alla seconda attività. Ora come uso questo valore all'interno del secondo frammento.

Ecco il codice 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);
    }

}

Ottengo la seguente eccezione :::

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

Come ottengo il valore dal bundle in SecondActivity.java a Fragment_2.Java?


Si prega di evidenziare la parte in cui ru sta ottenendo il problema
Nikhil Agrawal

soluzione di lavoro con un modo semplice: stackoverflow.com/a/59332751/10201722
Adil Siddiqui

Risposte:


203

passaggio 1 per inviare i dati dal frammento all'attività

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

passaggio 2. per ricevere questi dati in Attività:

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

fase 3 . per inviare dati da un'attività a un'altra attività seguire l'approccio normale

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

passaggio 4 per ricevere questi dati in attività

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

Passaggio 5. Da Activity puoi inviare i dati a Fragment con intento come:

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

e per ricevere in frammento nel metodo 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);
    }

2
Ho provato il passaggio 5, che sto chiamando listactivity dal frammento e dopo aver selezionato l'elemento da quell'attività, voglio tornare nel frammento con il nome del file selezionato. Ma non funziona, mi dà l'eccezione Nullpointer su onCreateView. Qualche soluzione su questo per favore? Questa è la mia domanda stackoverflow.com/questions/18208771/...
OnkarDhane

come inserisco un POJO qui? bundle.putString("message", "From Activity");
jeet.chanchawat

31
Qualcuno è disgustato da quanto sia complicato fare qualcosa del genere
Ed Lee

1
Esattamente Eddie, questo non è il modo corretto. Devono utilizzare le interfacce per comunicare tra i frammenti tramite l'attività del contenitore.
Kaveesh Kanwal

Per quanto riguarda l'utilizzo delle interfacce per comunicare tra i frammenti: developer.android.com/training/basics/fragments/…
Andre L Torres,

49

Come indicato nel sito dello sviluppatore

Spesso si desidera che un frammento comunichi con un altro, ad esempio per modificare il contenuto in base a un evento utente. Tutta la comunicazione da frammento a frammento avviene tramite l'attività associata. Due frammenti non dovrebbero mai comunicare direttamente.

la comunicazione tra i frammenti dovrebbe essere effettuata tramite l'attività associata.

Abbiamo i seguenti componenti:

Un'attività ospita frammenti e consente la comunicazione di frammenti

Fragment Un primo frammento che invierà i dati

FragmentB secondo frammento che riceverà i dati da FragmentA

L'implementazione di FragmentA è:

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

L'implementazione di MainActivity è:

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'implementazione di FragmentB è:

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

Spero che questo ti aiuti ..


4
Che cos'è OnImageClickListener qui? e come viene eseguito il cast a una variabile DataPassListener?
Harsha

Ho scoperto che è "DataPassListener". L'ho fatto funzionare, ma solo per trovare a causa di ogni volta che si fa clic sul pulsante i dati vengono inviati. Quando viene inviato, sostituisce il frammento. Il che significa che l'elenco viene rinnovato ogni volta. Pertanto, non mantenere l'elenco degli elementi in memoria.
wesley franks il

44

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

// In Fragment_2.java

Bundle bundle = this.getArguments();

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

Spero che questo ti aiuti.


1
Risposta pulita per mostrare il punto principale. usare putString(o putInt) è la risposta!
Mehdi Dehghani

22

Dal sito web degli sviluppatori :

Spesso si desidera che un frammento comunichi con un altro, ad esempio per modificare il contenuto in base a un evento utente. Tutta la comunicazione da frammento a frammento avviene tramite l'attività associata. Due frammenti non dovrebbero mai comunicare direttamente.

Puoi comunicare tra i frammenti con l'aiuto della sua attività. È possibile comunicare tra attività e frammenti utilizzando questo approccio.

Si prega di controllare anche questo collegamento.


Il secondo collegamento che hai fornito mostra come comunicare tra i frammenti quando sono nella stessa attività. Come comunico quando entrambi sono impegnati in attività diverse?
Vamsi Challa

5

Innanzitutto tutte le risposte sono corrette, puoi passare i dati tranne gli oggetti personalizzati utilizzando Intent. Se vuoi passare gli oggetti personalizzati, devi implementare Serialazableo Parcelablealla tua classe di oggetti personalizzati. Pensavo fosse troppo complicato ...

Quindi, se il tuo progetto è semplice, prova a usare DataCache. Ciò fornisce un modo semplicissimo per il passaggio dei dati. Rif: progetto Github CachePot

1- Impostalo su Visualizza o Attività o Frammento che invierà i dati

DataCache.getInstance().push(obj);

2- Ottieni dati ovunque come sotto

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

Non sarebbe più facile usare una classe extra con valori statici all'interno? È quindi possibile accedere a questi valori da entrambi i frammenti, quindi non è necessario utilizzare una libreria aggiuntiva per memorizzare nella cache gli oggetti personalizzati.
Neph

4

L'ultima soluzione per il passaggio di dati tra i frammenti può essere implementata utilizzando componenti architetturali Android come ViewModel e LiveData. Con questa soluzione, non è necessario definire l'interfaccia per la comunicazione e si possono ottenere i vantaggi dell'utilizzo di viewmodel come la sopravvivenza dei dati a causa delle modifiche alla configurazione.

In questa soluzione, i frammenti coinvolti nella comunicazione condividono lo stesso oggetto viewmodel che è legato al loro ciclo di vita dell'attività. L'oggetto del modello di visualizzazione contiene l'oggetto liveata. Un frammento imposta i dati da trasmettere all'oggetto liveata e il secondo osservatori di frammento ha vissuto la modifica e ha ricevuto i dati.

Ecco l'esempio completo http://www.zoftino.com/passing-data-between-android-fragments-using-viewmodel


3

Passaggio di argomenti tra i frammenti. È abbastanza tardi per rispondere a questa domanda, ma potrebbe aiutare qualcuno! 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();

Quindi nel tuo Fragment_2.javapuoi ottenere i parametri normalmente all'interno del tuo onActivityCreated es

 Intent intent = getActivity().getIntent();
    if (intent.getExtras() != null) {
        String name =intent.getStringExtra("name");
    }

3

Penso che un buon modo per risolvere questo problema sia utilizzare un'interfaccia personalizzata.

Supponiamo che tu abbia due frammenti (A e B) che si trovano all'interno della stessa attività e che desideri inviare dati da A a B.

Interfaccia:

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

Attività:

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

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

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

2

La comunicazione tra i frammenti è abbastanza complicata (trovo il concetto di ascoltatori un po 'difficile da implementare).

È comune utilizzare un "Event Bus" per astrarre queste comunicazioni. Questa è una libreria di terze parti che si occupa di questa comunicazione per te.

"Otto" è quello che viene usato spesso per fare questo e potrebbe valere la pena esaminarlo: http://square.github.io/otto/


2

Passaggio di dati da Fragment a un altro Fragment

  • Dal primo frammento

    // 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(); 
  • Sul secondo frammento

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

1

Questa semplice implementazione aiuta a passare i dati tra i frammenti in modo semplice. Pensi di voler passare i dati da "Frgment1" a "Fragment2"

In Fragment1 (Imposta dati da inviare)

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

In Fragment2 metodo onCreateView (Get parametri)

String value = this.getArguments().getString("key");//get your parameters
Toast.makeText(getActivity(), value+" ", Toast.LENGTH_LONG).show();//show data in tost

Nella mia app, sto cercando di farlo funzionare ma in qualche modo, sebbene il valore venga passato, non viene visualizzato su fragment2, penso di commettere un errore nell'impostare R.id.content_drawer. Qualcuno può guidarmi quale potrebbe essere l'identificatore giusto per R.id.content_drawer con l'esempio .xml.
falcon

1

Modo di Kotlin

Usa una SharedViewModelproposta nella documentazione ufficiale di ViewModel

È molto comune che due o più frammenti di un'attività debbano comunicare tra loro. Immagina un caso comune di frammenti master-detail, in cui hai un frammento in cui l'utente seleziona un elemento da un elenco e un altro frammento che visualizza il contenuto dell'elemento selezionato. Questo caso non è mai banale in quanto entrambi i frammenti devono definire una descrizione dell'interfaccia e l'attività del proprietario deve legarli insieme. Inoltre, entrambi i frammenti devono gestire lo scenario in cui l'altro frammento non è ancora stato creato o visibile.

Questo punto dolente comune può essere risolto utilizzando oggetti ViewModel. Questi frammenti possono condividere un ViewModel utilizzando il loro ambito di attività per gestire questa comunicazione

Per prima cosa implementa fragment-ktx per istanziare il tuo viewmodel più facilmente

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

Quindi, devi solo inserire nel viewmodel i dati che condividerai con l'altro frammento

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

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

Quindi, per finire, crea un'istanza del tuo viewModel in ogni frammento e imposta il valore di selected frammento di cui vuoi impostare i dati

Frammento 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)
      }

    }
}

E poi, ascolta semplicemente questo valore nella destinazione del frammento

Frammento 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
            })
        }
    }

Puoi anche farlo nel modo opposto


0

Soluzione funzionante al 100%: (se ti aiuta, non dimenticare di fare un voto positivo)

Nel tuo primo frammento metti questo pezzo di codice:

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

                }
            });

In Second Fragment, crea un metodo come di seguito:

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;

    }

quindi definire una variabile a livello di classe:

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

quindi crea un altro metodo nel secondo frammento per impostare il valore:

  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) {            }
        }
    }

0

Puoi raggiungere il tuo obiettivo tramite ViewModel e Live Data che vengono cancellati da Arnav Rao . Ora metto un esempio per chiarirlo in modo più ordinato.

In primo luogo, il presunto ViewModelviene nominato 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;
    }
}

Quindi il frammento di origine è il MasterFragment.javada cui vogliamo inviare i dati.

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

E infine il frammento di destinazione è il punto DetailFragment.javain cui vogliamo ricevere i dati.

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 

        });
    }
}

0

OK dopo così tanto scavare qui ho trovato una soluzione semplice, in realtà non dovresti mai passare i dati da un frammento all'altro è sempre una cattiva idea, puoi passare i dati dal frammento A all'attività e ottenere i dati dall'attività nel frammento 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();
        }
    });

// nell'attività 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
}

// ora in 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;

}

-2

ho creato qualcosa di veramente semplice per i principianti come me .. ho creato una visualizzazione di testo nel mio activity_main.xml e ho inserito

id=index
visibility=invisible

quindi ottengo questo textview dal primo frammento

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

e poi nel secondo frammento ottengo il valore

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

spero che sia d'aiuto!


La risposta non è correlata alla domanda posta
Kanagalingam
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.