Как передать данные между фрагментами - PullRequest
73 голосов
/ 04 марта 2011

Я пытаюсь передать данные между двумя фрагментами в моей программе.Это просто простая строка, которая хранится в списке.Список публикуется во фрагментах A, и когда пользователь нажимает на элемент списка, мне нужно, чтобы он отображался во фрагменте B. Похоже, что поставщик контента поддерживает только идентификаторы, поэтому он не будет работать.Есть предложения?

Ответы [ 13 ]

57 голосов
/ 04 марта 2011

Я думаю, что связь между фрагментами должна осуществляться через активность.И связь между фрагментом и деятельностью может быть осуществлена ​​следующим образом: https://developer.android.com/training/basics/fragments/communicating.html https://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity

21 голосов
/ 09 августа 2012

Если вы используете Roboguice, вы можете использовать EventManager в Roboguice для передачи данных без использования Activity в качестве интерфейса.Это довольно чистое ИМО.

Если вы не используете Roboguice, вы также можете использовать Otto в качестве шины событий: http://square.github.com/otto/

Обновление 20150909: Вы также можете использовать шину событий Green Robot илидаже RxJava сейчас тоже.Зависит от вашего варианта использования.

17 голосов
/ 21 мая 2015

Почему бы вам не использовать комплект.Из вашего первого фрагмента, вот как его настроить:

Fragment fragment = new Fragment();
Bundle bundle = new Bundle();
bundle.putInt(key, value);
fragment.setArguments(bundle);

Затем во втором фрагменте извлеките данные, используя:

Bundle bundle = this.getArguments();
int myInt = bundle.getInt(key, defaultValue);

В Bundle есть методы для множества типов данных,Пожалуйста, смотрите http://developer.android.com/reference/android/os/Bundle.html

17 голосов
/ 17 декабря 2012

Из документации Fragment :

Часто вы хотите, чтобы один фрагмент связывался с другим, например, для изменения содержимого в зависимости от события пользователя. Вся связь фрагмента с фрагментом осуществляется через связанную активность. Два фрагмента никогда не должны общаться напрямую.

Поэтому я предлагаю вам взглянуть на базовые учебные документы по фрагментам в документации. Они довольно всеобъемлющие, с примером и кратким руководством.

11 голосов
/ 09 февраля 2013

Допустим, у вас есть Activity AB, которая контролирует Frag A и Fragment B. Внутри фрагмента A вам нужен интерфейс, который может реализовать Activity AB. В примере кода Android они имеют:

private Callbacks mCallbacks = sDummyCallbacks;

/ * Интерфейс обратного вызова, который должны реализовывать все действия, содержащие этот фрагмент. Этот механизм позволяет уведомлять действия о выборе элемента. * /

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

Интерфейс обратного вызова помещен в один из ваших фрагментов (скажем, фрагмент А). Я думаю, что цель этого интерфейса Callbacks подобна вложенному классу внутри Frag A, который может реализовать любая активность. Поэтому, если Фрагмент A был телевизором, CallBacks - это пульт дистанционного управления (интерфейс) телевизора, который позволяет использовать Фрагмент A в Activity AB. Я могу ошибаться в деталях, потому что я новичок, но я действительно заставил свою программу работать на всех размерах экрана, и это то, что я использовал.

Итак, внутри фрагмента А мы имеем: (Я взял это из примеров программ Android)

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

А внутри Activity AB мы переопределяем метод 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();
    }

Итак, внутри Activity AB вы в основном бросаете все в Bundle и передаете его B. Если вы не уверены, как использовать Bundle, посмотрите класс.

Я в основном использую пример кода, предоставленного Android. Тот, что с материалом DummyContent. Когда вы создаете новый пакет приложений для Android, он называется MasterDetailFlow.

7 голосов
/ 08 апреля 2016

1- Первый способ - определить интерфейс

public interface OnMessage{
    void sendMessage(int fragmentId, String message);
}

public interface OnReceive{
    void onReceive(String message);
}

2- В своей деятельности реализовать интерфейс OnMessage

public class MyActivity implements OnMessage {
   ...
   @Override
   public void sendMessage(int fragmentId, String message){
       Fragment fragment = getSupportFragmentManager().findFragmentById(fragmentId);
       ((OnReceive) fragment).sendMessage();
   }
}

3- В своем фрагменте реализовать интерфейс OnReceive

public class MyFragment implements OnReceive{
    ...
    @Override
    public void onReceive(String message){
        myTextView.setText("Received message:" + message);
    }
}

Это базовая версия обработки сообщений, передаваемых между фрагментами.

Другой способ передачи данных между фрагментами - использование шины событий.

1 - Регистрация / отмена регистрации дляшина событий

@Override
public void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
}

@Override
public void onStop() {
    EventBus.getDefault().unregister(this);
    super.onStop();
}

2- Определить класс событий

public class Message{
    public final String message;

    public Message(String message){
        this.message = message;
    }
}

3- Опубликовать это событие в любом месте вашего приложения

EventBus.getDefault().post(new Message("hello world"));

4- Подписаться наэто событие для получения его в вашем фрагменте

@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessage(Message event){
    mytextview.setText(event.message);
}

Для получения более подробной информации о , вариантах использования и примере проекта о шаблоне шины событий.

2 голосов
/ 09 ноября 2016

В моем случае мне пришлось отправить данные обратно из FragmentB-> FragmentA, поэтому Intents не был вариантом, так как фрагмент уже был бы инициализирован Все, хотя все ответа выше Звучит хорошо, что для реализации нужно много *1006* кода, поэтому я выбрал более простой подход использования LocalBroadcastManager , это точно соответствует вышеприведенному, нобез всего неприятного шаблонного кода.Ниже приведен пример.

В отправляющем фрагменте (фрагмент B)

public class FragmentB {

    private void sendMessage() {
      Intent intent = new Intent("custom-event-name");
      intent.putExtra("message", "your message");
      LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    }
 }

и в фрагменте сообщения, которое будет получено (ФРАГМЕНТ 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");
      }
    };
}

Надеюсь, это кому-нибудь поможет

1 голос
/ 24 марта 2015

В основном реализовать интерфейс для взаимодействия между Activity и фрагментом.

1) Основная деятельность

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) фрагмент отправителя (фрагмент-активность)

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) фрагмент получателя (активность к фрагменту)

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

}

Я использовал эту ссылку для того же решения, надеюсь, кто-нибудь найдет ее полезной. Очень простой и простой пример.

http://infobloggall.com/2014/06/22/communication-between-activity-and-fragments/

1 голос
/ 06 августа 2014

Я работаю над аналогичным проектом, и я думаю, что мой код может помочь в вышеуказанной ситуации

Вот обзор того, что я делаю

В моем проекте есть два фрагмента: " FragmentA " и "FragmentB "

- FragmentA Содержит одно представление списка, когда вы щелкаете элемент в FragmentA Это INDEX передается FragmentB с использованием интерфейса коммуникатора

  • Шаблон проектирования полностью основан на концепции Java-интерфейсов, которая говорит « переменные ссылки интерфейса могут ссылаться на объект подкласса»
  • Пусть MainActivity реализует интерфейс, предоставляемый фрагментA (в противном случае мы не можем сделать ссылку на интерфейс переменной, указывающей на MainActivity)
  • В приведенном ниже коде объект коммуникатора сделан для ссылки на объект MainActivity с использованием метода " setCommunicator (Communicatot c) ", присутствующего в фрагментA .
  • Я запускаю response () метод интерфейса из FrgamentA , используя ссылку MainActivity.

    Интерфейсный коммуникатор определен внутри фрагмента A, чтобы обеспечить наименьшее преимущество доступа к коммуникатору интерфейсу.

ниже мой полный рабочий код

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



}
1 голос
/ 21 июля 2014

Вы можете прочитать этот документ. Эта концепция хорошо объяснена здесь http://developer.android.com/training/basics/fragments/communicating.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...