Передача об’єкта із дії у фрагмент


76

У мене є Activityякий використовує Fragment. Я просто хочу передати об'єкт з цього Activityв Fragment.

Як я міг це зробити? Усі підручники, які я бачив досі, де отримують дані з ресурсів.

РЕДАГУВАТИ:

Давайте будемо трохи точнішими:

Моя активність має ListViewліву частину. Коли ви натискаєте на неї, ідея полягає в тому, щоб завантажити Fragmentправу частину.

Коли я вводжу це Activity, Об'єкт Categoryвидається через Intent. Цей об’єкт містить список інших об’єктів Questions(який містить список рядків). Ці Questionsоб'єкти відображаються в ListView. Коли я натискаю на один елемент із ListView, я хочу відобразити Список Stringв Fragment(в а ListView).

Для цього я телефоную до setContentView()свого Activityз макетом. У цьому макеті визначено Fragmentправильний клас для виклику. Коли я викликаю це setContentView(), викликається the onCreateView()з my Fragment, але в цей час getArguments()повертається null.

Як я міг встиг наповнити його до дзвінка onCreateView()? (скажи мені, якщо я недостатньо чіткий)

Дякую

Відповіді:


133

Створіть статичний метод у, Fragmentа потім отримайте його за допомогою getArguments().

Приклад:

public class CommentsFragment extends Fragment {
  private static final String DESCRIBABLE_KEY = "describable_key";
  private Describable mDescribable;

  public static CommentsFragment newInstance(Describable describable) {
    CommentsFragment fragment = new CommentsFragment();
    Bundle bundle = new Bundle();
    bundle.putSerializable(DESCRIBABLE_KEY, describable);
    fragment.setArguments(bundle);

    return fragment;
  }

  @Override
  public View onCreateView(LayoutInflater inflater,
      ViewGroup container, Bundle savedInstanceState) {

    mDescribable = (Describable) getArguments().getSerializable(
        DESCRIBABLE_KEY);

    // The rest of your code
}

Згодом ви можете зателефонувати йому, Activityвиконавши щось на зразок:

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
Fragment fragment = CommentsFragment.newInstance(mDescribable);
ft.replace(R.id.comments_fragment, fragment);
ft.commit();

8
Що я хочу передати якомусь об’єкту, який не можна серіалізувати?
Bagusflyer

1
putParcelable - найкращий спосіб практики
panchicore

9
Я хотів би знати, чому б просто не встановити fragment.mDescribable = describable;newInstance? Це працює, але чи є щось, чого мені тут не вистачає?
Рахул Тхакур

2
@RahulThakur Вам не вистачає пункту mпрефіксу тут. Оскільки спільнота Java настійно заохочує концепцію інкапсуляції даних, слід зазначити, що приватні поля не повинні бути доступними зовні. Причиною тому, що воно передається як параметр із методу синглтона, є те, що це поле є обов'язковим у цьому контексті, і таким чином зменшується потенційний ризик того, що ви забудете призначити його значення.
mr5

16
Найкраща відповідь, але ви забуваєте сказати, що для роботи Objectпотрібні інструменти Serializable(у випадку, об'єкт Describable).
Габріель Стафока

12

Вам слід створити метод у своєму фрагменті, який приймає тип об’єкта, який ви хочете передати в нього. У цьому випадку я назвав його "setObject" (креативно, так? :)) Цей метод може потім виконувати будь-які потрібні дії з цим об'єктом.

MyFragment fragment;

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);

        if (getSupportFragmentManager().findFragmentById(android.R.id.content) == null) {
            fragment = new MyFragment();
            getSupportFragmentManager().beginTransaction().add(android.R.id.content, detailsFragment)
                    .commit();
        } else {
           fragment = (MyFragment) getSupportFragmentManager().findFragmentById(
                    android.R.id.content);
        }


        fragment.setObject(yourObject); //create a method like this in your class "MyFragment"
}

Зверніть увагу, що я використовую бібліотеку підтримки та дзвінки для getSupportFragmentManager () можуть бути для вас просто getFragmentManager () залежно від того, з чим ви працюєте


2
Тільки будьте обережні, використовуючи цей метод для фрагмента, який може пережити ваш вигляд хостингу (retainInstance true).
Jannie Theunissen

7
Це не спрацює. Коли ваша програма вмирає у фоновому режимі, і користувач повертає її на передній план, setObjectне обов'язково буде викликатися.
Martin Konecny

5
@MartinKonecny, у цьому випадку метод onCreate буде викликаний знову (оскільки дія буде відтворена), а отже, буде також викликаний setObject. Якщо це не так, будь ласка, поясніть свій коментар. Дякую.
fklappan

Це не працює у разі перегляду фрагментів пейджера. оскільки об'єкт не утримується при переході.
rafa

12

У вашому класі активності:

public class BasicActivity extends Activity {

private ComplexObject co;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_page);

    co=new ComplexObject();
    getIntent().putExtra("complexObject", co);

    FragmentManager fragmentManager = getFragmentManager();
    Fragment1 f1 = new Fragment1();
    fragmentManager.beginTransaction()
            .replace(R.id.frameLayout, f1).commit();

}

Примітка: Ваш об’єкт повинен реалізувати інтерфейс, який можна серіалізувати

Потім у вашому фрагменті:

public class Fragment1 extends Fragment {

ComplexObject co;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    Intent i = getActivity().getIntent();

    co = (ComplexObject) i.getSerializableExtra("complexObject");

    View view = inflater.inflate(R.layout.test_page, container, false);
    TextView textView = (TextView) view.findViewById(R.id.DENEME);
    textView.setText(co.getName());

    return view;
}
}

4

Передача аргументів за пакетом обмежується деякими типами даних. Але ви можете передати будь-які дані у свій фрагмент таким чином:

У своєму фрагменті створіть такий публічний метод

public void passData(Context context, List<LexItem> list, int pos) {
    mContext = context;
    mLexItemList = list;
    mIndex = pos;
}

а у вашій діяльності зателефонуйте passData () з усіма необхідними типами даних після створення екземпляра фрагмента

        WebViewFragment myFragment = new WebViewFragment();
        myFragment.passData(getApplicationContext(), mLexItemList, index);
        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.add(R.id.my_fragment_container, myFragment);
        ft.addToBackStack(null);
        ft.commit();

Примітка: Мій фрагмент розширює "android.support.v4.app.Fragment", тому я повинен використовувати "getSupportFragmentManager ()". Звичайно, цей принцип буде працювати і з класом фрагментів, що розширює "Fragment", але тоді вам доведеться використовувати "getFragmentManager ()".


4

Отримати посилання з наступного прикладу.

1. У фрагменті : Створіть посилальну змінну для класу, об’єкт якого ви хочете у фрагменті. Просто створіть метод сеттера для посилальної змінної та зателефонуйте сетеру перед заміною фрагмента з активності.

 MyEmployee myEmp;
 public void setEmployee(MyEmployee myEmp)
 {
     this.myEmp = myEmp;
 }

2. У діяльності :

   //we need to pass object myEmp to fragment myFragment

    MyEmployee myEmp = new MyEmployee();

    MyFragment myFragment = new MyFragment();

    myFragment.setEmployee(myEmp);

    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    ft.replace(R.id.main_layout, myFragment);
    ft.commit();

1

Щоб передати об’єкт фрагменту, виконайте наступне:

Спочатку збережіть об’єкти в Bundle, не забудьте поставити серіалізуються знаряддя в клас.

            CategoryRowFragment fragment = new CategoryRowFragment();

            // pass arguments to fragment
            Bundle bundle = new Bundle();

            // event list we want to populate
            bundle.putSerializable("eventsList", eventsList);

            // the description of the row
            bundle.putSerializable("categoryRow", categoryRow);

            fragment.setArguments(bundle);

Потім дістаньте пакети у фрагменті

       // events that will be populated in this row
        mEventsList = (ArrayList<Event>)getArguments().getSerializable("eventsList");

        // description of events to be populated in this row
        mCategoryRow = (CategoryRow)getArguments().getSerializable("categoryRow");


0

Якщо дані повинні зберегтись протягом усього життєвого циклу програми та розподілятись між кількома фрагментами чи діями, Modelможе бути врахований клас, який має менші витрати на серіалізацію.

Перевірте цей приклад дизайну


0

Цей працював у мене:

В діяльності:

User user;
public User getUser(){ return this.user;}

У методі onCreateView Fragment:

User user = ((MainActivity)getActivity()).getUser(); 

Замініть на MainActivityсвоє ім'я діяльності.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.