Comment transmettre des données entre fragments
j'essaie de passer des données entre deux fragments de mon programme. C'est juste une chaîne simple qui est stockée dans la liste. La liste est rendue publique dans les fragments A, et lorsque l'utilisateur clique sur un élément de liste, j'en ai besoin pour apparaître dans le fragment B. Le fournisseur de contenu ne semble prendre en charge que les ID, donc cela ne fonctionnera pas. Toutes les suggestions?
13 réponses
je pense que la communication entre fragments devrait se faire par l'activité. Et la communication entre fragment et activité peut se faire de cette façon: https://developer.android.com/training/basics/fragments/communicating.html https://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity
si vous utilisez Roboguice, vous pouvez utiliser L'EventManager de Roboguice pour transmettre des données sans utiliser L'activité comme interface. C'est tout à fait propre, de l'OMI.
si vous n'utilisez pas Roboguice, vous pouvez aussi utiliser Otto comme bus d'événements: http://square.github.com/otto /
mise à jour 20150909: vous pouvez également utiliser le robot vert Event Bus ou même RxJava maintenant aussi. Dépend de votre cas d'utilisation.
De la Fragment
documentation :
souvent vous voudrez qu'un Fragment communique avec un autre, par exemple pour changer le contenu basé sur un événement utilisateur. Toute communication Fragment-à-Fragment se fait par L'activité associée. Deux Fragments ne doivent jamais communiquer directement.
donc je vous suggère de regarder sur le basic fragment training docs dans la documentation. Ils sont assez complets avec un exemple et un guide pratique.
pourquoi tu n'utilises pas un paquet. À partir de votre premier fragment, voici comment le configurer:
Fragment fragment = new Fragment();
Bundle bundle = new Bundle();
bundle.putInt(key, value);
fragment.setArguments(bundle);
puis dans votre second Fragment, récupérez les données en utilisant:
Bundle bundle = this.getArguments();
int myInt = bundle.getInt(key, defaultValue);
Bundle a mis des méthodes pour beaucoup de types de données. S'il vous plaît voir http://developer.android.com/reference/android/os/Bundle.html
donc disons que vous avez une activité AB qui contrôle Fraga et Fragment B. A l'intérieur du Fragment A, vous avez besoin d'une interface que Activity AB peut implémenter. Dans l'exemple de code android, ils ont:
private Callbacks mCallbacks = sDummyCallbacks;
/ *une interface de rappel que toutes les activités contenant ce fragment doivent implémenter. Ce mécanisme permet d'informer les activités de la sélection des articles. * /
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) {
}
};
l'interface de rappel est placée à l'intérieur un de vos Fragments (disons Fragment A). Je pense que le but de cette interface de Callbacks est comme une classe imbriquée à L'intérieur de Fraga que n'importe quelle activité peut implémenter. Donc si le Fragment a était un TV, les CallBacks sont la télécommande TV (interface) qui permet au Fragment a d'être utilisé par L'activité AB. Je peux me tromper sur les détails parce que je suis un noob mais j'ai fait fonctionner mon programme parfaitement sur toutes les tailles d'écran et c'est ce que j'ai utilisé.
donc à L'intérieur du Fragment A, Nous avons: (J'ai pris cette de Android Sample programs)
@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);
}
et activité intérieure AB nous supplantons la méthode onItemSelected:
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();
}
donc à L'intérieur de L'activité AB, vous jetez essentiellement tout dans un paquet et le passer à B. Si u ne sont pas sûr comment utiliser un paquet, regarder la classe vers le haut.
j'utilise le code fourni par Android. Celui avec le truc du DummyContent. Lorsque vous faites une nouvelle application Android Package, C'est celui qui s'appelle MasterDetailFlow.
1 - la première façon est de définir une interface
public interface OnMessage{
void sendMessage(int fragmentId, String message);
}
public interface OnReceive{
void onReceive(String message);
}
2 - En vous de l'activité mettre en œuvre OnMessage interface
public class MyActivity implements OnMessage {
...
@Override
public void sendMessage(int fragmentId, String message){
Fragment fragment = getSupportFragmentManager().findFragmentById(fragmentId);
((OnReceive) fragment).sendMessage();
}
}
3 - Dans votre fragment de mettre en œuvre OnReceive interface
public class MyFragment implements OnReceive{
...
@Override
public void onReceive(String message){
myTextView.setText("Received message:" + message);
}
}
c'est la version boilerplate de la manipulation du message passant entre les fragments.
une autre façon de transmettre le passage de données entre fragments est d'utiliser un bus d'événements.
1- Inscription / non-inscription à un bus d'événements
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
2-Définir une classe d'événement
public class Message{
public final String message;
public Message(String message){
this.message = message;
}
}
3 - postez cet événement n'importe où dans votre application
EventBus.getDefault().post(new Message("hello world"));
4 - abonnez-vous à cet événement pour le recevoir dans votre Fragment
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessage(Message event){
mytextview.setText(event.message);
}
pour plus de détails, cas d'utilisation, et un exemple de projet sur le modèle de bus d'événement.
cela dépend de la structure du fragment. Si vous pouvez avoir certaines des méthodes sur la classe de Fragment B statique et aussi l'objet cible TextView statique, vous pouvez appeler la méthode directement sur la classe de Fragment A. c'est mieux qu'un auditeur car la méthode est exécutée instantanément, et nous n'avons pas besoin d'avoir une tâche supplémentaire qui effectue l'écoute tout au long de l'activité. Voir l'exemple ci-dessous:
Fragment_class_B.setmyText(String yourstring);
sur Fragment B vous pouvez avoir la méthode défini comme suit:
public static void setmyText(final String string) {
myTextView.setText(string);
}
n'oubliez pas de définir myTextView comme statique sur le Fragment B, et importez correctement la classe de Fragment B sur le Fragment A.
vient de faire la procédure sur mon projet et il a fonctionné. Espérons que cela a aidé.
vous pouvez lire ce doc .ce concept est bien expliqué ici http://developer.android.com/training/basics/fragments/communicating.html
je travaille sur un projet similaire et je suppose que mon code peut aider dans la situation ci-dessus
Voici l'aperçu de ce que je fais
mon projet a deux fragments appelés " FragmentA " et "FragmentB
- FragmentA contient une vue de liste,lorsque vous cliquez sur un élément dans FragmentA son INDEX est passé à FragmentB utilisant L'interface de communication
- Le modèle de conception est totalement basé sur le concept d'interfaces java qui dit " les variables de référence de l'interface peuvent renvoyer à un objet de la sous-classe "
- Let MainActivity mettre en œuvre l'interface fournie par fragmentA (sinon on ne peut pas faire référence à l'interface de la variable au point de MainActivity)
- dans le code ci-dessous l'objet communicateur est fait pour renvoyer à l'objet de" Mainactivity's en utilisant setCommunicator(Communicatot c) "méthode présente dans fragmentA .
-
je suis le déclenchement de répondre() méthode de l'interface à partir de FrgamentA à l'aide de la MainActivity de référence.
interface communcator est défini à l'intérieur de fragmentA, il s'agit de fournir l'accès le moins previlage à communicateur interface.
ci-dessous est mon code de travail complet
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);
}
}
activité principale.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);
}
}
essentiellement mettre en œuvre l'interface pour communiquer entre L'activité et le fragment.
1) activité principale
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) fragment émetteur (fragment-to-Activity)
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) fragment récepteur (activité à 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);
}
}
j'ai utilisé ce lien pour la même solution, j'espère que quelqu'un va le trouver utile. Exemple très simple et basique.
http://infobloggall.com/2014/06/22/communication-between-activity-and-fragments /
dans mon cas , j'ai dû envoyer les données à rebours de FragmentB->FragmentA par conséquent intention N'était pas une option car le fragment serait déjà initialisé tout bien que tout le ci-dessus réponses sonne bien , il faut un lot de code de Plaque de chaudière pour mettre en œuvre , donc je suis allé avec un beaucoup approche plus simple de en utilisant localbroadcastmanager , il fait exactement le ci-dessus dit mais sans tout le code de la mauvaise passe. Un exemple est partagée ci-dessous.
Dans L'Envoi De Fragment(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);
}
}
et dans le message à recevoir Fragment(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");
}
};
}
Espère que cela aide quelqu'un
classe de fragments 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();
}
}
Classe De Fragments 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;
}
}
Classe D'activité principale pour la transmission de données entre fragments
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);
}
}
}
classe de précision
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();
}
}
Tableau De Pays
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"
};
}
pour plus de détails visitez ce lien [ http://wptrafficanalyzer.in/blog/itemclick-handler-for-listfragment-in-android/] . Il ya plein d'exemple ..
il S'agit essentiellement ici de la communication entre Fragments. La Communication entre fragments ne peut jamais être directement possible. Elle implique une activité dans le contexte de laquelle les deux fragments sont créés.
vous devez créer une interface dans le fragment émetteur et mettre en œuvre l'interface dans l'activité qui va réécrire le message et transférer au fragment récepteur.