Передача объекта во фрагмент или DialogFragment при создании экземпляра

Я пытаюсь найти правильный способ передачи объекта в Фрагмент или DialogFragment без нарушения 'пустой конструктор' правило.

Например, я создал собственное представление, и для каждого экземпляра я хочу связать DiaglogFragment. Этот DialogFragment будет использоваться для отображения элементов управления, с помощью которых пользователь может изменять определенные аспекты пользовательского представления, с которым он связан. Поскольку представление является объектом, я понимаю, что не могу использовать setArguments().

Я мог бы реализовать метод newInstance(View) моего шаблона DialogFragment, т.е. Factory, но что тогда произойдет, если мой фрагмент будет сохранен системой, а затем восстановлен позже? Насколько я могу судить, не будет ссылки на объект View?

Может ли кто-нибудь сказать мне, неправильно ли я использую фрагменты или есть ли способ добиться передачи объекта во фрагмент, который также справится с системой, реконструирующей его в более позднее время.


person D-Dᴙum    schedule 06.05.2013    source источник
comment
Добавьте сеттер к вашему фрагменту, а затем вызовите этот сеттер после new Fragment()? Но вы не хотите устанавливать представления. Вы хотите сообщить фрагменту, что ему нужно показать, и он должен сам создавать представления. Если действие выполняет эту работу, это, вероятно, означает, что ваши фрагменты и действия не разделены должным образом.   -  person dmon    schedule 06.05.2013
comment
Фрагмент не будет отображать View, он просто тесно связан с ним. Однако фрагмент должен передавать данные обратно в представление (например, какая кнопка Radio выбрана)   -  person D-Dᴙum    schedule 07.05.2013
comment
Правильный способ сделать это — создать интерфейс, который реализует активность, а фрагмент может вызывать методы. По сути, действие должно организовывать любые взаимодействия между фрагментами и другими представлениями в действии.   -  person dmon    schedule 07.05.2013
comment
Да, вы заставили меня понять, что я использую фрагменты не так, как должен. Что я могу сделать, так это передать идентификатор представления, а также фрагмент, содержащий это представление. При необходимости мой DialogFragment может вернуться к содержащему Activity для передачи данных.   -  person D-Dᴙum    schedule 07.05.2013


Ответы (4)


В вашем классе DialogFragmnet вы создаете два метода:

  1. newInstance чтобы создать экземпляр вашего DialogFragment

  2. сеттер для инициализации вашего объекта

и добавьте setRetainInstance(true); в onCreate

public class YourDialogFragment extends DialogFragment {

    ComplexVariable complexVar;

    public static YourDialogFragment newInstance(int arg, ComplexVariable complexVar) {
        YourDialogFragment frag = new MoveSongDialogFragment();
        Bundle args = new Bundle();
        args.putInt("count", arg);
        frag.setArguments(args);
        frag.setComplexVariable(complexVar);
        return frag;
    }

    public void setComplexVariable(ComplexVariable complexVar) {
        this.complexVar = complexVar;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }
}

затем, чтобы показать диалог

FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();

Fragment prev = manager.findFragmentByTag("yourTag");
if (prev != null) {
    ft.remove(prev);
}

// Create and show the dialog.
DialogFragment newFragment = YourFragmentDialog.newInstance(argument, yourComplexObject);
newFragment.show(ft, "yourTag");
person Karim Aly    schedule 02.05.2014
comment
Не уверен, что это хороший подход, поскольку ваш DialogFragment может быть восстановлен автоматически (например, во время ротации), и тогда значение yourVar будет нулевым. Таким образом, DialogFragment будет отображаться некорректно в случае его автоматического создания системой. - person goRGon; 03.07.2015
comment
Похоже, размещение сериализованного объекта внутри аргументов фрагмента - единственное хорошее решение. Или стандартное общение с использованием подхода getActivity()+interface. - person goRGon; 03.07.2015
comment
@goRGon вы правы, если вы не вызывали в фрагменте onCreate setRetainInstance(true); - person Karim Aly; 05.07.2015
comment
Обновлен ответ и добавлен setRetainInstance(true); для дальнейшего использования - person Karim Aly; 05.07.2015
comment
или сохранить сложный var в компонентах архитектуры ViewModel - person YellowJ; 16.09.2019

Вы можете передать Object в дополнениях Bundle как Parcelable Objects (http://developer.android.com/reference/android/os/Parcelable.html ) и передать их в Bundle в файле onCreateView(Bundle savedInstanceState). Однако вы можете сохранить их, если пользователь перевернет экран.

EDIT: это Parcelable туториал был неплох!

Другой способ - получить объект данных из вашей ParentActivity, но я не уверен, что это хороший способ (но он работает..)

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    mYourObject = ((MainActivity) getActivity()).getYourObject();
}

вам нужно создать Getter в своей деятельности для этого

public YourObject getYourObject(){
   return mYourObecjt;
}

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

person longi    schedule 06.05.2013
comment
Не уверен, что Parcelable - это то, что мне нужно, но, прочитав ссылку, я понял, что, вероятно, не ясно изложил свой вопрос. Мне нужна ссылка на реальный объект. Объект Parcelable - это реконструкция/клон реального объекта? Мне нужна ссылка, чтобы я мог изменить представление в режиме реального времени. - person D-Dᴙum; 07.05.2013

Вы всегда можете использовать хорошую библиотеку JSON, такую ​​как GSON или Genson, для сериализации объектов — это мой подход к любому удаленно сложному объекту. GSON немного более компактен для простых операций, но если у вас есть какие-либо виды наследования/полиморфизма в ваших представлениях, я настоятельно рекомендую Genson. У вас может быть ctr с аргументом, если вы их документируете.

https://code.google.com/p/genson/ — скачайте JAR в раздел загрузки.

person mgibson    schedule 07.05.2013
comment
Спасибо за ваш ответ. Я понял, что мне просто нужна ссылка на реальный объект, поэтому любая форма сериализации усложняет ситуацию. Мне просто нужно общаться через активность, которая является внутренним способом. - person D-Dᴙum; 07.05.2013

Я исправил свою потребность с помощью sharepreference. YuzdeDataUser - это мой пользовательский класс, который я беру в onClickItemListener из My Listview.

Как отправить

  YuzdeDataUser clickedObj = (YuzdeDataUser) parent.getItemAtPosition(position);
            //clickedObj.setTarihim();
            SharedPreferences shp = getSharedPreferences("sam", MODE_PRIVATE);
            SharedPreferences.Editor editor = shp.edit();

            Gson gson = new Gson();
            String json = gson.toJson(clickedObj);
            editor.putString("yoklamaList", json);
            editor.commit();

            FragmentManager fragmentManager = getSupportFragmentManager();
            AylikRaporPop userPopUp = new AylikRaporPop();
            userPopUp.show(fragmentManager, "sam");

Как получить

    SharedPreferences shp = parent.getSharedPreferences("sam", MODE_PRIVATE);
    SharedPreferences.Editor editor = shp.edit();

    Gson gson = new Gson();
    String json = shp.getString("yoklamaList", "");
    YuzdeDataUser user = gson.fromJson(json, YuzdeDataUser.class);
    if (user != null) {
        txt_ad.setText(user.getAd());
        txt_tur_tarih.setText(Util.getInstance(parent).writeNameOfTur(user.getTur_id()));
        txt_var.setText("" + user.getVar());
        txt_gorevli.setText("" + user.getGorevli());
        txt_yok.setText("" + user.getYok());

    }
person Sam    schedule 12.07.2017