Ich versuche Daten zwischen zwei Fragmenten in meinem Programm zu übertragen. Es ist nur eine einfache Zeichenfolge, die in der Liste gespeichert ist. Die Liste wird in Fragment A veröffentlicht, und wenn der Benutzer auf ein Listenelement klickt, muss es in Fragment B angezeigt werden. Der Inhaltsanbieter scheint nur IDs zu unterstützen, sodass dies nicht funktioniert. Irgendwelche Vorschläge?
android
android-fragments
Shaun
quelle
quelle
Antworten:
Warum benutzt du kein Bundle? Von Ihrem ersten Fragment aus können Sie Folgendes einrichten:
Fragment fragment = new Fragment(); Bundle bundle = new Bundle(); bundle.putInt(key, value); fragment.setArguments(bundle);
Rufen Sie dann in Ihrem zweiten Fragment die Daten ab mit:
Bundle bundle = this.getArguments(); int myInt = bundle.getInt(key, defaultValue);
Bundle hat Methoden für viele Datentypen festgelegt. Weitere Informationen finden Sie unter http://developer.android.com/reference/android/os/Bundle.html
quelle
Wenn Sie Roboguice verwenden, können Sie den EventManager in Roboguice verwenden, um Daten weiterzugeben, ohne die Aktivität als Schnittstelle zu verwenden. Das ist ziemlich sauber IMO.
Wenn Sie Roboguice nicht verwenden, können Sie Otto auch als Veranstaltungsbus verwenden: http://square.github.com/otto/
Update 20150909: Sie können jetzt auch Green Robot Event Bus oder sogar RxJava verwenden. Hängt von Ihrem Anwendungsfall ab.
quelle
Aus der
Fragment
Dokumentation :Ich schlage daher vor, dass Sie sich die grundlegenden Fragment-Schulungsdokumente in der Dokumentation ansehen . Sie sind ziemlich umfassend mit einem Beispiel und einer Anleitung.
quelle
Nehmen wir also an, Sie haben Activity AB, das Frag A und Fragment B steuert. Innerhalb von Fragment A benötigen Sie eine Schnittstelle, die Activity AB implementieren kann. Im Beispiel-Android-Code haben sie:
private Callbacks mCallbacks = sDummyCallbacks;
/ * Eine Rückrufschnittstelle, die alle Aktivitäten, die dieses Fragment enthalten, implementieren müssen. Mit diesem Mechanismus können Aktivitäten über die Artikelauswahl benachrichtigt werden. * /
public interface Callbacks { /*Callback for when an item has been selected. */ public void onItemSelected(String id); } /*A dummy implementation of the {@link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity. */ private static Callbacks sDummyCallbacks = new Callbacks() { @Override public void onItemSelected(String id) { } };
Die Callback-Oberfläche befindet sich in einem Ihrer Fragmente (sagen wir Fragment A). Ich denke, der Zweck dieser Callbacks-Schnittstelle ist wie eine verschachtelte Klasse in Frag A, die jede Aktivität implementieren kann. Wenn also Fragment A ein Fernsehgerät war, ist CallBacks die TV-Fernbedienung (Schnittstelle), mit der Fragment A von Aktivität AB verwendet werden kann. Ich kann mich in Bezug auf Details irren, weil ich ein Neuling bin, aber ich habe mein Programm dazu gebracht, auf allen Bildschirmgrößen perfekt zu funktionieren, und das habe ich verwendet.
In Fragment A haben wir also: (Ich habe dies aus den Beispielprogrammen von Android genommen)
@Override public void onListItemClick(ListView listView, View view, int position, long id) { super.onListItemClick(listView, view, position, id); // Notify the active callbacks interface (the activity, if the // fragment is attached to one) that an item has been selected. mCallbacks.onItemSelected(DummyContent.ITEMS.get(position).id); //mCallbacks.onItemSelected( PUT YOUR SHIT HERE. int, String, etc.); //mCallbacks.onItemSelected (Object); }
In Activity AB überschreiben wir die onItemSelected-Methode:
public class AB extends FragmentActivity implements ItemListFragment.Callbacks { //... @Override //public void onItemSelected (CATCH YOUR SHIT HERE) { //public void onItemSelected (Object obj) { public void onItemSelected(String id) { //Pass Data to Fragment B. For example: Bundle arguments = new Bundle(); arguments.putString(“FragmentB_package”, id); FragmentB fragment = new FragmentB(); fragment.setArguments(arguments); getSupportFragmentManager().beginTransaction().replace(R.id.item_detail_container, fragment).commit(); }
In Activity AB werfen Sie also im Grunde alles in ein Bundle und übergeben es an B. Wenn Sie sich nicht sicher sind, wie Sie ein Bundle verwenden sollen, schlagen Sie die Klasse nach.
Ich gehe im Grunde genommen nach dem Beispielcode, den Android bereitgestellt hat. Der mit dem DummyContent-Zeug. Wenn Sie ein neues Android-Anwendungspaket erstellen, trägt es den Titel MasterDetailFlow.
quelle
1- Der erste Weg ist das Definieren einer Schnittstelle
public interface OnMessage{ void sendMessage(int fragmentId, String message); } public interface OnReceive{ void onReceive(String message); }
2- Implementieren Sie in Ihrer Aktivität die OnMessage-Schnittstelle
public class MyActivity implements OnMessage { ... @Override public void sendMessage(int fragmentId, String message){ Fragment fragment = getSupportFragmentManager().findFragmentById(fragmentId); ((OnReceive) fragment).sendMessage(); } }
3- Implementieren Sie in Ihrem Fragment die OnReceive-Schnittstelle
public class MyFragment implements OnReceive{ ... @Override public void onReceive(String message){ myTextView.setText("Received message:" + message); } }
Dies ist die Boilerplate-Version der Verarbeitung von Nachrichten, die zwischen Fragmenten übertragen werden.
Eine andere Möglichkeit, die Datenübertragung zwischen Fragmenten zu übergeben, ist die Verwendung eines Ereignisbusses.
1- Registrieren / Aufheben der Registrierung für einen Ereignisbus
@Override public void onStart() { super.onStart(); EventBus.getDefault().register(this); } @Override public void onStop() { EventBus.getDefault().unregister(this); super.onStop(); }
2- Definieren Sie eine Ereignisklasse
public class Message{ public final String message; public Message(String message){ this.message = message; } }
3- Veröffentlichen Sie dieses Ereignis an einer beliebigen Stelle in Ihrer Anwendung
EventBus.getDefault().post(new Message("hello world"));
4- Abonnieren Sie dieses Ereignis, um es in Ihrem Fragment zu erhalten
@Subscribe(threadMode = ThreadMode.MAIN) public void onMessage(Message event){ mytextview.setText(event.message); }
Weitere Informationen, Anwendungsfälle und ein Beispielprojekt zum Ereignisbusmuster.
quelle
In meinem Fall musste ich die Daten von FragmentB-> FragmentA rückwärts senden, daher war Intents keine Option, da das Fragment bereits initialisiert wurde. Obwohl alle oben genannten Antworten gut klingen , erfordert die Implementierung viel Kesselplattencode , also i ging mit einem viel einfacheren Ansatz der Verwendung von LocalBroadcastManager , es tut genau das oben Gesagte, aber ohne alll den bösen Boilerplate-Code. Ein Beispiel wird unten geteilt.
Beim Senden eines Fragments (Fragment B)
public class FragmentB { private void sendMessage() { Intent intent = new Intent("custom-event-name"); intent.putExtra("message", "your message"); LocalBroadcastManager.getInstance(this).sendBroadcast(intent); } }
Und in dem zu empfangenden Nachrichtenfragment (FRAGMENT A)
public class FragmentA { @Override public void onCreate(Bundle savedInstanceState) { ... // Register receiver LocalBroadcastManager.getInstance(this).registerReceiver(receiver, new IntentFilter("custom-event-name")); } // This will be called whenever an Intent with an action named "custom-event-name" is broadcasted. private BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String message = intent.getStringExtra("message"); } }; }
Hoffe es hilft jemandem
quelle
Das hängt davon ab, wie das Fragment aufgebaut ist. Wenn Sie einige der Methoden für die statische Fragmentklasse B und auch für das statische Ziel-TextView-Objekt haben können, können Sie die Methode direkt für die Fragmentklasse A aufrufen. Dies ist besser als ein Listener, da die Methode sofort ausgeführt wird und wir dies nicht tun. Es muss keine zusätzliche Aufgabe vorhanden sein, die während der gesamten Aktivität zuhört. Siehe Beispiel unten:
Fragment_class_B.setmyText(String yourstring);
In Fragment B können Sie die Methode wie folgt definieren lassen:
public static void setmyText(final String string) { myTextView.setText(string); }
Vergessen Sie nur nicht, myTextView in Fragment B als statisch festzulegen und die Fragment B-Klasse in Fragment A ordnungsgemäß zu importieren.
Ich habe gerade das Verfahren für mein Projekt durchgeführt und es hat funktioniert. Hoffe das hat geholfen.
quelle
Sie können dieses Dokument lesen. Dieses Konzept wird hier ausführlich erläutert. http://developer.android.com/training/basics/fragments/communicating.html
quelle
Ich arbeite an einem ähnlichen Projekt und ich denke, mein Code kann in der oben genannten Situation helfen
Hier ist die Übersicht darüber, was ich tue
Mein Projekt hat zwei Fragmente namens " FragmentA " und "FragmentB ".
- FragmentA Enthält eine Listenansicht, wenn Sie auf ein Element in FragmentA klicken. Der INDEX wird über die Communicator-Oberfläche an FragmentB übergeben
Ich löse die Antwortmethode () der Schnittstelle von FrgamentA unter Verwendung der Referenz von MainActivity aus .
Der Schnittstellenkommunikator ist in fragmentA definiert. Dies dient dazu, den geringsten Zugriff auf die Kommunikationsschnittstelle zu ermöglichen.
Unten ist mein vollständiger Arbeitscode
FragmentA.java
public class FragmentA extends Fragment implements OnItemClickListener { ListView list; Communicator communicater; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub return inflater.inflate(R.layout.fragmenta, container,false); } public void setCommunicator(Communicator c){ communicater=c; } @Override public void onActivityCreated(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onActivityCreated(savedInstanceState); communicater=(Communicator) getActivity(); list = (ListView) getActivity().findViewById(R.id.lvModularListView); ArrayAdapter<?> adapter = ArrayAdapter.createFromResource(getActivity(), R.array.items, android.R.layout.simple_list_item_1); list.setAdapter(adapter); list.setOnItemClickListener(this); } @Override public void onItemClick(AdapterView<?> arg0, View arg1, int index, long arg3) { communicater.respond(index); } public interface Communicator{ public void respond(int index); }
}}
fragmentB.java
public class FragmentA extends Fragment implements OnItemClickListener { ListView list; Communicator communicater; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub return inflater.inflate(R.layout.fragmenta, container,false); } public void setCommunicator(Communicator c){ communicater=c; } @Override public void onActivityCreated(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onActivityCreated(savedInstanceState); communicater=(Communicator) getActivity(); list = (ListView) getActivity().findViewById(R.id.lvModularListView); ArrayAdapter<?> adapter = ArrayAdapter.createFromResource(getActivity(), R.array.items, android.R.layout.simple_list_item_1); list.setAdapter(adapter); list.setOnItemClickListener(this); } @Override public void onItemClick(AdapterView<?> arg0, View arg1, int index, long arg3) { communicater.respond(index); } public interface Communicator{ public void respond(int index); } }
MainActivity.java
public class MainActivity extends Activity implements FragmentA.Communicator { FragmentManager manager=getFragmentManager(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); FragmentA fragA=(FragmentA) manager.findFragmentById(R.id.fragmenta); fragA.setCommunicator(this); } @Override public void respond(int i) { // TODO Auto-generated method stub FragmentB FragB=(FragmentB) manager.findFragmentById(R.id.fragmentb); FragB.changetext(i); } }
quelle
Implementieren Sie grundsätzlich die Schnittstelle, um zwischen Aktivität und Fragment zu kommunizieren.
1) Hauptaktivität
public class MainActivity extends Activity implements SendFragment.StartCommunication { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public void setComm(String msg) { // TODO Auto-generated method stub DisplayFragment mDisplayFragment = (DisplayFragment)getFragmentManager().findFragmentById(R.id.fragment2); if(mDisplayFragment != null && mDisplayFragment.isInLayout()) { mDisplayFragment.setText(msg); } else { Toast.makeText(this, "Error Sending Message", Toast.LENGTH_SHORT).show(); } } }
2) Absenderfragment (Fragment-zu-Aktivität)
public class SendFragment extends Fragment { StartCommunication mStartCommunicationListner; String msg = "hi"; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub View mView = (View) inflater.inflate(R.layout.send_fragment, container); final EditText mEditText = (EditText)mView.findViewById(R.id.editText1); Button mButton = (Button) mView.findViewById(R.id.button1); mButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub msg = mEditText.getText().toString(); sendMessage(); } }); return mView; } interface StartCommunication { public void setComm(String msg); } @Override public void onAttach(Activity activity) { // TODO Auto-generated method stub super.onAttach(activity); if(activity instanceof StartCommunication) { mStartCommunicationListner = (StartCommunication)activity; } else throw new ClassCastException(); } public void sendMessage() { mStartCommunicationListner.setComm(msg); } }
3) Empfängerfragment (Aktivität zu Fragment)
public class DisplayFragment extends Fragment { View mView; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub mView = (View) inflater.inflate(R.layout.display_frgmt_layout, container); return mView; } void setText(String msg) { TextView mTextView = (TextView) mView.findViewById(R.id.textView1); mTextView.setText(msg); } }
Ich habe diesen Link für dieselbe Lösung verwendet. Ich hoffe, jemand findet ihn nützlich. Sehr einfaches und einfaches Beispiel.
http://infobloggall.com/2014/06/22/communication-between-activity-and-fragments/
quelle
Fragmentklasse A.
public class CountryListFragment extends ListFragment{ /** List of countries to be displayed in the ListFragment */ ListFragmentItemClickListener ifaceItemClickListener; /** An interface for defining the callback method */ public interface ListFragmentItemClickListener { /** This method will be invoked when an item in the ListFragment is clicked */ void onListFragmentItemClick(int position); } /** A callback function, executed when this fragment is attached to an activity */ @Override public void onAttach(Activity activity) { super.onAttach(activity); try{ /** This statement ensures that the hosting activity implements ListFragmentItemClickListener */ ifaceItemClickListener = (ListFragmentItemClickListener) activity; }catch(Exception e){ Toast.makeText(activity.getBaseContext(), "Exception",Toast.LENGTH_SHORT).show(); } }
Fragmentklasse B.
public class CountryDetailsFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { /** Inflating the layout country_details_fragment_layout to the view object v */ View v = inflater.inflate(R.layout.country_details_fragment_layout, null); /** Getting the textview object of the layout to set the details */ TextView tv = (TextView) v.findViewById(R.id.country_details); /** Getting the bundle object passed from MainActivity ( in Landscape mode ) or from * CountryDetailsActivity ( in Portrait Mode ) * */ Bundle b = getArguments(); /** Getting the clicked item's position and setting corresponding details in the textview of the detailed fragment */ tv.setText("Details of " + Country.name[b.getInt("position")]); return v; } }
Hauptaktivitätsklasse zum Übergeben von Daten zwischen Fragmenten
public class MainActivity extends Activity implements ListFragmentItemClickListener { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } /** This method will be executed when the user clicks on an item in the listview */ @Override public void onListFragmentItemClick(int position) { /** Getting the orientation ( Landscape or Portrait ) of the screen */ int orientation = getResources().getConfiguration().orientation; /** Landscape Mode */ if(orientation == Configuration.ORIENTATION_LANDSCAPE ){ /** Getting the fragment manager for fragment related operations */ FragmentManager fragmentManager = getFragmentManager(); /** Getting the fragmenttransaction object, which can be used to add, remove or replace a fragment */ FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); /** Getting the existing detailed fragment object, if it already exists. * The fragment object is retrieved by its tag name * */ Fragment prevFrag = fragmentManager.findFragmentByTag("in.wptrafficanalyzer.country.details"); /** Remove the existing detailed fragment object if it exists */ if(prevFrag!=null) fragmentTransaction.remove(prevFrag); /** Instantiating the fragment CountryDetailsFragment */ CountryDetailsFragment fragment = new CountryDetailsFragment(); /** Creating a bundle object to pass the data(the clicked item's position) from the activity to the fragment */ Bundle b = new Bundle(); /** Setting the data to the bundle object */ b.putInt("position", position); /** Setting the bundle object to the fragment */ fragment.setArguments(b); /** Adding the fragment to the fragment transaction */ fragmentTransaction.add(R.id.detail_fragment_container, fragment,"in.wptrafficanalyzer.country.details"); /** Adding this transaction to backstack */ fragmentTransaction.addToBackStack(null); /** Making this transaction in effect */ fragmentTransaction.commit(); }else{ /** Portrait Mode or Square mode */ /** Creating an intent object to start the CountryDetailsActivity */ Intent intent = new Intent("in.wptrafficanalyzer.CountryDetailsActivity"); /** Setting data ( the clicked item's position ) to this intent */ intent.putExtra("position", position); /** Starting the activity by passing the implicit intent */ startActivity(intent); } } }
Detaillierte Aktivitätsklasse
public class CountryDetailsActivity extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /** Setting the layout for this activity */ setContentView(R.layout.country_details_activity_layout); /** Getting the fragment manager for fragment related operations */ FragmentManager fragmentManager = getFragmentManager(); /** Getting the fragmenttransaction object, which can be used to add, remove or replace a fragment */ FragmentTransaction fragmentTransacton = fragmentManager.beginTransaction(); /** Instantiating the fragment CountryDetailsFragment */ CountryDetailsFragment detailsFragment = new CountryDetailsFragment(); /** Creating a bundle object to pass the data(the clicked item's position) from the activity to the fragment */ Bundle b = new Bundle(); /** Setting the data to the bundle object from the Intent*/ b.putInt("position", getIntent().getIntExtra("position", 0)); /** Setting the bundle object to the fragment */ detailsFragment.setArguments(b); /** Adding the fragment to the fragment transaction */ fragmentTransacton.add(R.id.country_details_fragment_container, detailsFragment); /** Making this transaction in effect */ fragmentTransacton.commit(); } }
Array von Contries
public class Country { /** Array of countries used to display in CountryListFragment */ static String name[] = new String[] { "India", "Pakistan", "Sri Lanka", "China", "Bangladesh", "Nepal", "Afghanistan", "North Korea", "South Korea", "Japan", "Bhutan" }; }
Weitere Informationen finden Sie unter diesem Link [ http://wptrafficanalyzer.in/blog/itemclick-handler-for-listfragment-in-android/] . Es gibt vollständige Beispiele ..
quelle
getParentFragmentManager().setFragmentResultListener
ist der Weg 2020, dies zu tun. Ihre einzige Einschränkung besteht darin, ein Bundle zum Weitergeben der Daten zu verwenden. Weitere Informationen und Beispiele finden Sie in den Dokumenten .Einige andere Möglichkeiten
getActivity()
und übertragen Sie es auf die gemeinsame Aktivität zwischen Ihren Fragmenten. Verwenden Sie es dann als Brücke, um die Daten zu übergeben. Diese Lösung wird dringend empfohlen, da zwischen der Aktivität und den Fragmenten ein Cupelling erforderlich ist. In den KitKat-Tagen war dies jedoch die beliebte Methode, dies zu tun ...FragmentManager
ist, dass es nicht auf Bundles beschränkt ist. Der Nachteil ist jedoch, dass Sie möglicherweise auf Fehler in Randfällen stoßen, bei denen Sie den Aktivitätslebenszyklus durcheinander bringen und Ausnahmen erhalten, z. B.IllegalStateException
wenn sich der Fragmentmanager mitten im Speicherzustand befindet oder die Aktivität zerstört wurde. Außerdem wird keine verarbeitungsübergreifende Kommunikation unterstützt.quelle
Grundsätzlich geht es hier um die Kommunikation zwischen Fragmenten. Die Kommunikation zwischen Fragmenten kann niemals direkt möglich sein. Es handelt sich um Aktivitäten, in deren Kontext beide Fragmente erstellt werden.
Sie müssen eine Schnittstelle im sendenden Fragment erstellen und die Schnittstelle in der Aktivität implementieren, die die Nachricht erneut entlastet und an das empfangende Fragment überträgt.
quelle