2013-12-25 3 views
3

Я работаю над проектом, где мне нужно передавать данные между фрагментами. Все данные предоставлены из моего DatabaseHandler class (SQLiteOpenHelper). Я пишу этот пост вручную, поэтому игнорируем синтаксические ошибки, если они есть.Передача данных между вложенными фрагментами

Вот что мой Activity выглядит (содержит SelectionFragment и InfoFragment):

  • Фрагмент Selection (содержит GridView)
  • Info Фрагмент (ViewPager с о 5-6 child fragments)
    • childFragment1
    • childFragment2
    • childFragment3
    • ...

Вот что я сделал до сих пор:

SelectFrag расширяет фрагмент:

MyCommunicator communicator; 
GridView myGrid; 

onItemSelected(... int position, ...) { 
    communicator.respond("The id i get from getTag().."); 
} 
public void setCommunicator(MyCommunicator communicator) { 
    this.communicator = communicator; 
} 

public interface MyCommunicator { 
    public void respond(String id); 
} 



активность распространяется FragmentActivity реализует SelectFrag.MyCommunicator:

FragmentManager manager; 
SelectFrag selectFrag; 
InfoFrag infoFrag; 

onCreate() { 
    manager = getSupportFragmentManager(); 
    selectFrag = (SelectFrag) manager.findFragmentById(...); 
    selectFrag.setCommunicator(this); 
} 

@Override 
public void respond(String id) { 
    DatabaseHandler db = new DatabaseHandler(this); 
    try { 
     CustomObject obj = db.getObj(id); 
    } finally { 
     db.close(); 
    } 
    infoFrag = (InfoFrag) manager.findFragmentById(...); 
    if(obj != null) 
     infoFrag.changeObj(id) 
    setTitle(obj.getName(); 
} 


InfoFrag расширяет фрагмент:

ViewPager pager; 
Context context; 
MyObj obj; 

public void changeObj(String id) { 
    DatabaseHandler db = new DatabaseHandler(context); 
    this.obj = db.getObj(id); 
    db.close(); 
} 

protect class MyPagerAdapter extends FragmentPagerAdapter{ 
    public Fragment getItem(int i) { 
     Fragment frag = null; 
     switch(i) { 
      case 0: 
       frag = new ChildFrag1(); 
      break; 
      case 1: 
       frag = new ChildFrag2(); 
      break; 
      ... Goes to case 6 for now. 
     } 
     return frag; 
    } 
} 

Вот мои Макеты:

select_frag.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context=".SelectFrag" > 

    <GridView 
     android:id="@+id/selectGridView" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:columnWidth="56dp" 
     android:background="#dd5500" 
     android:horizontalSpacing="5dp" 
     android:numColumns="auto_fit" 
     android:paddingLeft="10dp" 
     android:paddingRight="2dp" 
     android:paddingTop="3dp" 
     android:stretchMode="columnWidth" 
     android:verticalSpacing="5dp" > 
    </GridView> 

</RelativeLayout> 

main_activity.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context=".MyActivity" 
    android:orientation="vertical" > 

    <fragment 
     android:id="@+id/selectFragment" 
     android:name="my.package.SelectFragment" 
     android:layout_width="wrap_content" 
     android:layout_height="0dp" 
     android:layout_weight="3" /> 

    <fragment 
     android:id="@+id/infoFragment" 
     android:name="my.package.InfoFragment" 
     android:layout_width="wrap_content" 
     android:layout_height="0dp" 
     android:layout_weight="7" /> 

</LinearLayout> 

info_fragment.xml:

<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:id="@+id/myPager" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" > 

    <android.support.v4.view.PagerTitleStrip 
     android:id="@+id/my_pager_title_strip" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_gravity="top" 
     android:background="#33b5e5" 
     android:paddingBottom="4dp" 
     android:paddingTop="4dp" 
     android:textColor="#fff" /> 

</android.support.v4.view.ViewPager> 

приложение в настоящее время проходит информация от selectFrag к деятельности, которая передает его infoFrag. Я хотел бы, чтобы этот идентификатор достиг цели До детского фрагмента. Я думал о том, что возможно реализовать MyCommunicator для InfoFrag и передать данные дочерним фрагментам, но не будет ли это вызывать исключение NullPointerException для дочерних фрагментов, которые не видны.

* Примечание: * Элементы selectFrag и InfoFrag всегда видны в Управлении. InfoFrag должен обновляться, когда в элементе selectFrag GridView выбран новый элемент.

Благодарим за помощь!

EDIT:
Я пробовал использовать «интерфейс связи», но я теряюсь каждый раз :(lol ..Может ли кто-нибудь дать мне короткий способ сделать это? Могут ли все мои childrenFragments реализовать коммуникатор от selectFrag? Если да, то это правильный способ сделать это? Я думаю, что InfoFragment должен реализовать интерфейс и передать данные своим «детям». Но я не знаю, как это сделать и освежить детей. Еще одна вещь, о которой я думал - это сохранить lastItemClicked в sharedPreferences, а затем получить доступ к объекту из моего db. Я действительно смущен:/Спасибо еще раз!

+1

https://github.com/greenrobot/EventBus. проверьте это или используйте интерфейс в качестве обратного вызова и сообщите значение фрагменту, которое уже упоминалось в документах, с примером – Raghunandan

+0

довольно хорошо! Но что было бы правильным путем без использования каких-либо библиотек? –

+0

с использованием интерфейса в качестве обратного вызова http://developer.android.com/training/basics/fragments/communicating.html – Raghunandan

ответ

6

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

Вам нужно создать следующие компоненты:

  1. интерфейс для реализации в ваших фрагментов.
  2. Список слушателей, реализующих этот интерфейс.
  3. Добавить/удалить элементы из этого списка.
  4. В конце концов сообщите своим слушателям, что что-то произошло.

Я опишу упрощенную версию.

Интерфейс: Это просто:

public interface DataChangeListener { 
    void onDataChanged(); 
} 

Список слушателей: Это слишком легко ... в контроллерах/Мероприятия/Singletons или где вам нужно выполнять действия и уведомить слушателей ...

protected List<DataChangeListener> mListeners = new ArrayList<DataChangeListener>(); 
    public void addDataChangeListener(DataChangeListener listener) { 
     if (listener != null && !mListeners.contains(listener)) { 
      mListeners.add(listener); 
     } 
    } 
    public void removeDataChangeListener(DataChangeListener listener) { 
     if (listener != null) { 
      mListeners.remove(listener); 
     } 
    } 

Тогда ваши фрагменты ... (например)

public class YourFragment extends Fragment implements DataChangeListener { 

private SomeControllerForExample mController; 

    @Override 
    public void onPause() { 
     super.onPause(); 
     mController.removeDataChangeListener(this); 
    } 
    @Override 
    public void onResume() { 
     super.onResume(); 
     mController.addDataChangeListener(this); 
     } 

} 

До сих пор вы регистрируетесь при возобновлении и удалении, когда вы больше не видите.

Кроме того, необходимо реализовать метод ...

@Override 
public void onDataSetChanged() { 
     // DO WHATEVER YOU NEED TO DO 
} 

И, наконец, есть известить метод в контроллере (тот же тот, который был в списке)

private void notifyListeners(){ 
    for (DataChangeListener listener : mListeners) { 
     if (listener != null) { 
      listener.onDataSetChanged(); 
     } 
    } 
} 

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

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

+1

ПОЛУЧИТЕ РАБОТУ! ДА! СПАСИБО LOL. Просто нужно небольшое объяснение, что делать. Не могу поверить, что я делал тупая ошибка (последние раз я пытался). Еще раз спасибо! Говорит, что я должен ждать 19 часов, чтобы наградить награду:/ –

+0

Рад узнать, что у вас это работает;) –

1

Нашли решение пока. Вместо того, чтобы общаться с дочерним фрагментом. Я закончил рестайлинг ViewPager каждый раз, когда элемент был выбран в GridView (вызывает changeObj в infoFrag). Я предполагаю, что раньше я должен был использовать разные ключевые слова, чтобы найти решение! :/ Replacing a fragment from ViewPager android

+2

Да, но это ужасно плохая идея. Он использует CPU, Battery, заставляет целую коллекцию мусора объекта и т. Д. Почему бы вам просто не реализовать базовый интерфейс прослушивателя/обратного вызова для связи с вашими фрагментами? –

+0

Если это так, я не одобрил свой ответ! Я новичок в андроиде, и я не могу понять, как это сделать. Я сделал это через Activity, но не знаю, как отправить информацию в childFragment из фрагмента. –

Смежные вопросы