2013-04-16 13 views
68

Jestem całkiem nowy w użyciu Fragmentów.Jak przekazywać wartości między Fragmentami

Po prostu próbuję zbudować prostą przykładową aplikację, która korzysta z Fragmentów. Mój scenariusz polega na tym, że mam dwie czynności z jednym fragmentem wewnątrz każdego działania. Pierwszy fragment zawiera editekst i przycisk. Drugi fragment ma widok tekstowy. Kiedy wprowadzam nazwę w edytorze tekstu i klikam przycisk, widok tekstowy w drugim fragmencie powinien wyświetlać nazwę wprowadzoną w edytorze pierwszego fragmentu.

Udało mi się wysłać wartość z pierwszego fragmentu do jego aktywności, a następnie z tego działania do drugiej aktywności. Teraz, jak mogę użyć tej wartości wewnątrz drugiego fragmentu.

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

} 

otrzymuję następujący wyjątek :::

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 

Jak mogę uzyskać wartość od wiązki w SecondActivity.java do Fragment_2.Java?

+0

Proszę zaznaczyć część, gdzie ru dostaniem problem –

Odpowiedz

157

etap 1 .to wysyłania danych z fragmentem aktywności

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

etapie 2 .to otrzymać te dane aktywności:

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

etap 3. aby przesłać dane z działalności innej aktywności wykonaj normalne podejście

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

krok 4 do otrzymania tych danych w działalności

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

Krok 5. z działalności można wysyłać dane do fragmentu z zamiarem jako:

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

i otrzymać w postaci fragmentu w Fragment onCreateView meth od:

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

    return inflater.inflate(R.layout.fragment, container, false); 
    } 
+1

próbowałem krok 5, że dzwonię listactivity z fragmentem i po wybraniu pozycji z tej działalności, chcę wrócić z fragmentem wybrana nazwa pliku. Ale to nie działa, daje mi wyjątek Nullpointer w onCreateView. Jakieś rozwiązanie tego problemu? To jest moje pytanie http://stackoverflow.com/questions/18208771/nullpointer-exception-while-returning-string-to-fragment-from-activity/18209614?noredirect=1#18209614 – OnkarDhane

+0

jak ustawić POJO tutaj? 'bundle.putString (" message "," From Activity "); ' –

+7

Czy ktoś jest zdegustowany tym, jak zawiłe robienie czegoś takiego jest –

22

Od Developers www:

Często będziemy chcieli jednego fragmentu do komunikowania się z innym, na przykład w celu zmiany zawartości w oparciu o zdarzenia użytkownika. Cała komunikacja Fragment-to-Fragment odbywa się poprzez powiązane działanie. Dwa Fragmenty nie powinny nigdy komunikować się bezpośrednio.

Możesz komunikować się między fragmentami za pomocą swojej działalności. Możesz komunikować się między aktywnością i fragmentem przy użyciu podejścia this.

Sprawdź również link this.

+0

Drugie dowiązanie, które podałeś, pokazuje jak komunikować się między fragmentami, gdy są one w tym samym czynność. Jak mogę się komunikować, gdy obie są w różnych działaniach? –

2

Komunikacja pomiędzy fragmentami jest dość skomplikowana (uważam, że koncepcja słuchaczy jest trudna do wdrożenia).

Powszechne jest stosowanie „Bus Event” abstrahować te komunikaty. To jest 3rd biblioteka Strona, która zajmuje się tego komunikatu dla Ciebie.

«Otto» to taki, który jest używany często, aby to zrobić i może być warto przyjrzeć się: http://square.github.io/otto/

25

Jak wspomniano na stronie dewelopera

Często będziemy chcieli jednego fragmentu do komunikowania się z innym, na przykład do zmiany treści na podstawie zdarzenia użytkownika Wszystko fragmentom. do-Fragmentowanie komunikacji odbywa się poprzez skojarzone Czynność. Dwa Fragmenty nie powinny nigdy komunikować się bezpośrednio.

Komunikacja między fragmentami powinna odbywać się za pomocą powiązanej czynności.

Rzućmy następujące składniki:

Działalność gospodarze fragmenty i pozwalają fragmenty komunikację

Fragmenta pierwszy fragment, który będzie wysyłał dane

FragmentB Drugi fragment, który będzie otrzymywać dane z FragmentA

realizacja Fragmenta jest:

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

realizacja główną działalność to:

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

realizacja FragmentB jest:

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

Mam nadzieję, że to pomoże ..

3

Po pierwsze wszystkie odpowiedzi są prawidłowe, możesz przekazać dane oprócz obiektów niestandardowych za pomocą Intent. Jeśli chcesz przekazać niestandardowe obiekty, musisz zaimplementować Serialazable lub Parcelable do niestandardowej klasy obiektów. Myślałem, że to zbyt skomplikowane ...

Więc jeśli twój projekt jest prosty, spróbuj użyć DataCache. Zapewnia to bardzo prosty sposób przekazywania danych. Ref:https://github.com/kimkevin/AndroidDataCache

1- Set to aby zobaczyć czy aktywny lub jego fragment, który wyśle ​​dane

DataCache.getInstance().push(obj); 

2- Uzyskaj dane nigdzie jak poniżej

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 
2

Podawanie argumentów między fragmentami. Jest to dość późno, aby odpowiedzieć na to pytanie, ale może pomóc komuś! 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(); 

Następnie w Fragment_2.java można uzyskać paramaters normalnie w swoim onActivityCreated np

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

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

// W Fragment_2.java

Bundle bundle = this.getArguments(); 

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

Mam nadzieję, że ci to pomoże.

+0

Oczyść odpowiedź, aby pokazać główny punkt. używanie 'putString' (lub' putInt') jest odpowiedzią! –

-1

Ive się coś naprawdę łatwe dla początkujących jak ja .. zrobiłem TextView w moim activity_main.xml i umieścić

id=index 
visibility=invisible 

następnie uzyskać ten TextView od pierwszego fragmentu

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

a następnie w drugim fragmencie uzyskać wartość

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

nadziei to pomaga!

0

Ta prosta implementacja pomaga w prosty sposób przekazywać dane między fragmentami. Pomyśl chcesz przekazać dane z 'Frgment1' do

W Fragment1 'Fragment2' (zestaw danych do wysłania)

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

W metodzie Fragment2 onCreateView (Get parameteres)

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

Passing dane z Fragmentu na inny Fragment

  • Od pierwszego Fragmentu

    // 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(); 
    
  • Na drugim fragmentem

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

Myślę, że dobrym sposobem na rozwiązanie tego problemu jest użycie interfejsu użytkownika.

Powiedzmy, że masz dwa fragmenty (A i B), które znajdują się wewnątrz tej samej działalności i chcesz przesłać dane z punktu A do B.

interfejs:

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

działalność:

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 
      } 
     }); 
    } 
} 
Powiązane problemy