2013-11-15 43 views
8

prima di iniziare, devo guardare attraverso domanda del tipo:Android: Passaggio di oggetti tra Frammenti

Passing data between fragments: screen overlap How to pass values between Fragments

così come docs Android:

http://developer.android.com/training/basics/fragments/communicating.html

così come questo articolo:

http://manishkpr.webheavens.com/android-passing-data-between-fragments/

Anche se tutti i casi sopra menzionati sono simili a quello che ho, non è del tutto identico. Ho seguito un buon tutorial qui (Una parte del mio codice si basa su questo articolo):

http://www.androidhive.info/2013/10/android-tab-layout-with-swipeable-views-1/

ho i seguenti file:

RegisterActivity.java
NonSwipeableViewPager.java
ScreenSliderAdapter .java
RegisterOneFragment.java
RegisterTwoFragment.java

E i seguenti layout:

activity_register.xml
fragment_register_one.xml
fragment_register_two.xml

Quello che sto cercando di realizzare è passando un oggetto Serializable da RegisterFragmentOne a RegisterFragmentTwo.

Finora questo è quello che ho fatto (alcuni codici sono omessi):

RegisterActivity.java

public class RegisterActivity extends FragmentActivity 
      implements RegisterOneFragment.OnEmailRegisteredListener{ 

    public static NonSwipeableViewPager viewPager; 
    private ScreenSliderAdapter mAdapter; 

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

     // Initilization 
     mAdapter = new ScreenSliderAdapter(getSupportFragmentManager()); 
     viewPager = (NonSwipeableViewPager) findViewById(R.id.pager); 
     viewPager.setAdapter(mAdapter); 
    } 

    public void onEmailRegistered(int position, Registration regData){ 
     Bundle args = new Bundle(); 
     args.putSerializable("regData", regData); 
     viewPager.setCurrentItem(position, true); 
    } 
} 

ScreenSliderAdapter.java

public class ScreenSliderAdapter extends FragmentPagerAdapter{ 

    public ScreenSliderAdapter(FragmentManager fm) { 
     super(fm); 
    } 

    @Override 
    public Fragment getItem(int index) { 

     switch (index) { 
     case 0: 
      return new RegisterOneFragment(); 
     case 1: 
      return new RegisterTwoFragment(); 
     case 2: 
      return new RegisterThreeFragment(); 
     } 

     return null; 
    } 

    @Override 
    public int getCount() { 
     return 3; 
    } 
} 

NonSwipeableViewPager. java (estensione Classe ViewPager, e sostituisce il seguente)

@Override 
public boolean onInterceptTouchEvent(MotionEvent arg0) { 
    // Never allow swiping to switch between pages 
    return false; 
} 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    // Never allow swiping to switch between pages 
    return false; 
} 

RegisterOneFragment.java

public class RegisterOneFragment extends Fragment { 
    OnEmailRegisteredListener mCallBack; 
    public interface OnEmailRegisteredListener { 
     /** Called by RegisterOneFragment when an email is registered */ 
     public void onEmailRegistered(int position, Registration regData); 
    } 

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 = (OnEmailRegisteredListener) activity; 
    } catch (ClassCastException e) { 
     throw new ClassCastException(activity.toString() 
       + " must implement OnEmailRegisteredListener"); 
    } 
} 

... And some to execute some HTTP request via separate thread... 
} 

quello che sto cercando di realizzare è che, quando mai un utente preme un pulsante sul RegisterOneFragment, un dato verrà inviato a un server (e restituisce alcune convalide su JSON). Se i dati restituiti sono validi, l'applicazione dovrebbe passare al frammento successivo che è RegistrationTwoFragment.

Sto avendo un po 'di confusione su come passare oggetti tra i frammenti, dal momento che i miei frammenti vengono creati utilizzando un adattatore.E quell'adattatore è quindi collegato alla mia attività.

Qualcuno può aiutarmi con questo? Thx

Edit 1:

ho cercato di creare un collegamento (purtroppo non funziona) in questo modo:

In RegisterActivity ho creato:

public Registration regData; 

e in RegisterOneFragment:

/* PLACED ON POST EXECUTE */ 
((RegisterActivity)getActivity()).regData = regData; 

Finall y ha chiamato in RegisterTwoFragment

Registration regData; 
regData = ((RegisterActivity) getActivity()).regData; 

Si getta una NullPointerExceptions

Edit 2

Giusto per essere chiari, RegisterActivty contiene più frammenti. E l'unico modo in cui l'utente può navigare tra i frammenti è facendo clic su un pulsante. L'attività non ha una barra delle schede.

+0

si può raccontare http://stackoverflow.com/questions/40126867/how-to-access-custom-arraylist-in-fragment – albert

risposta

3

Avrei normalmente setter o metodi simili a questo nell'attività di contenimento.

Quindi, se ho capito bene, si desidera che l'utente per accedere RegistrationOneFragment, poi, quando completata, utilizzare questi dati, convalidare e, se valida, passarlo insieme a RegistrationTwoFragment e spostare l'utente a questo Fragment.

Potresti semplicemente chiamare validateJson(regData) nel tuo metodo onEmailRegistered per gestire la convalida nella tua attività, se riesce, effettuare una transazione su RegistrationTwoFragment.

Quindi tutto ciò che serve sono getter e setter nella tua attività o Frammento per dire getRegistrationOneData() nell'attività o setData(Registration args) nel frammento come i tuoi esempi mostrano sopra.

Non conosco alcun modo per passare gli argomenti direttamente nel frammento.

+0

Sì che è esattamente quello che sto cercando di fare con il mio codice Riferendosi alla tua soluzione, vuol dire che non devo usare adattatori? Nel frattempo cercherò di seguire il tuo consiglio. Thx ... – Jeremy

+0

Se si desidera mantenere il cercapersone e l'adattatore, è necessario mantenerlo, ma penso che si possa anche gestirlo facilmente con supportFragmentManager() e le transazioni. – sturrockad

+0

Suppongo che tu abbia ragione, solo che sto cercando di ottenere questo risultato con il minimo sforzo possibile ... – Jeremy

1

ho trovato una soluzione alla mia domanda, che io sono sicuro che non è il modo corretto per farlo ...

Così in RegisterActivity.java aggiungo + modificato le seguenti righe (thx a @sturrockad):

public Registration getRegistrationData(){ 
    return this.regData; 
} 

public void onEmailRegistered(int position, Registration regData){ 
    this.regData = regData; 
    viewPager.setCurrentItem(position, true); 
} 

Poi nel RegisterTwoFragments.java (o nel frammento a cui voglio ricevere l'oggetto):

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

    View rootView = inflater.inflate(R.layout.fragment_register_two, container, false); 
    regData = ((RegisterActivity) getActivity()).getRegistrationData(); 
    ... 
+0

Felice di aiutare. Accetta la risposta se sei soddisfatto della soluzione dei metodi get(). – sturrockad

8

e 'facile condividere oggetti tramite attuazione Serializable al tuo oggetto personalizzato. Ho scritto un tutorial su questo here.

Da Frammento Uno:

android.support.v4.app.FragmentTransaction ft = 
    getActivity().getSupportFragmentManager().beginTransaction(); 
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); 
OfficeCategoryFragment frag = new OfficeCategoryFragment(); 

Bundle bundles = new Bundle(); 
Division aDivision = divisionList.get(position); 

// ensure your object has not null 
if (aDivision != null) { 
    bundles.putSerializable("aDivision", aDivision); 
    Log.e("aDivision", "is valid"); 
} else { 
    Log.e("aDivision", "is null"); 
} 
frag.setArguments(bundles); 
ft.replace(android.R.id.content, frag); 
ft.addToBackStack(null); 
ft.commit(); 

In Frammento due:

Bundle bundle = getArguments(); 
Division division= (Division) bundle.getSerializable("aDivision"); 
Log.e("division TEST", "" + division.getName()); 
+0

Per qualcuno che cerca di fare qualcosa di simile con meno sforzo: usa google gson per serializzare il tuo pojo su json e inviarlo con il pacchetto. È meglio perché non è necessario implementare serializzabile per ogni oggetto e quando si modificano le proprietà degli oggetti (sul back-end) non è necessario modificare l'implementazione serializzabile. – sagits

0

Ho usato per impostare oggetto con Pacelable o Serializable trasferire, ma ogni volta aggiungo altre variabili di opporsi (modello), Devo registrarlo tutto. È così inopportuno.

È estremamente semplice trasferire l'oggetto tra attività o frammenti.

Android DataCache

  1. mettere il vostro oggetto di dati per esempio KimchiDataCache nella vostra attività o un frammento.

    User userItem = new User(1, "KimKevin"); // Sample Model 
    
    KimchiDataCache.getInstance().put(userItem); 
    
    // add your activity or fragment 
    
  2. Ottieni il tuo oggetto dati nell'attività di frammento che hai aggiunto.

    public class MainFragment extends Fragment{ 
        private User userItem; 
    
        @Override 
        public void onCreate(Bundle savedInstanceState) { 
         super.onCreate(savedInstanceState); 
    
         userItem = KimchiDataCache.getInstance().get(User.class); 
        } 
    
+1

Questo ha il comportamento del pattern singleton, che è molto antipattern, il suo dolore con unit test. –

+0

Per qualcuno che cerca di fare qualcosa di simile con meno sforzo: usa google gson per serializzare il tuo pojo su json e inviarlo con il pacchetto (setArguments). – sagits

Problemi correlati