Сохранить состояние полей во фрагменте android

Рейтинг: 1Ответов: 2Опубликовано: 06.11.2014

Есть фрагмент, который содержит Spinner'ы и EditText'ы. Пользователь их заполняет и затем переходит на другой фрагмент для произведения некоторых действий там. Когда он возвращается обратно на первый фрагмент с данными из frag2, нужно восстановить или записать программно то, что было им введено ранее.

Делаю так:

Фрагмент 1

в onCreateView

Bundle bdReStore = getArguments();
if (bdReStore != null) {
     String fs = bdReStore.getString("editTemp");
     Log.i(LOG_TAG, "recieve: " + editTemp);
     editTemp.setText(fs);
}

в коде перехода на frag2 (onClick реализован)

Frag1 frag1 = new Frag1();
Frag2 frag2 = new Frag2();
Bundle bundleStore = new Bundle();
if (addTask.getText().length() != 0) { 
   bundleStore.putString("editTemp", editTemp.getText().toString();); /** сохранить строку, если введена */ 
}
frag1.setArguments(bdReStore);
android.app.FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
 .replace(R.id.content_frame, frag2).commit();

Фрагмент 2

Frag1 frag1 = new Frag1();
Bundle bundle = new Bundle();
bundle.putInt("tag", toothCount);
frag1.setArguments(bundle);
android.app.FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
   .replace(R.id.content_frame,  frag1).commit();

Думаю, что проблема во втором фрагменте (frag2), когда возвращаюсь на первый. Потому что здесь приходится создавать заново новый экземпляр frag1. Поэтому и null мне выводится в LogCat.

Вопрос: Что нужно изменить в коде, чтобы реализовать идею?

Предложение:
Была мысль сделать хардкод: передать из frag1 во frag2, а потом обратно из frag2 во frag1. Но думаю, что есть более гуманный способ.

myUpdate 01 Часть моего кода, которая сейчас есть рабочей.О ней я писал выше: http://pastebin.com/6cz1BL98

Ответы

▲ 2

Думаю, что ваша проблема в том, что состояние сохранять надо не в аргументах фрагмента, а вот так

public class FragmentBase extends Fragment
{

    @Override
    public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState)
    {
        final View rootView = inflater.inflate(R.layout.my_layout,null);

        //Если у вас базовый фрагмент создает View, то делаете так
        //View rootView = super.onCreateView(inflater,container,savedInstanceState);

        //тут делаете что надо
        if(savedInstanceState!=null)
        {
            //были сохраненные состояния, надо восстановить
        }
        return rootView;
    }

    @Override
    public void onSaveInstanceState(final Bundle outState)
    {
        //тут пишете необходимые вещи в outState
        if(outState == null)
            outState = new Bundle();
        super.onSaveInstanceState(outState);
    }
}

UPD: Исходники рабочего примера

▲ 2

У вас, если я правильно понял ваш код, 3 ошибки:

  1. При замене 1-го фрагмента вторым 1-й не добавляется в память FragmentManager методом addToBackStack(null) (надо до commit() в transaction вызвать).
  2. Во втором фрагменте надо бы не новый 1-й фрагмент создавать, а старый по ID находить и ему уже передавать через сеттер или аргументы данные.
  3. Вы аргументы в коде второго фрагмента (Bundle) передаёте какому-то "addNewTask_fragment", а в трансакцию отдаёте новый экземпляр 1-го фрагмента... Чего вы ожидаете от этого кода?

Итого: Как минимум присваивайте аргументы правильным экземплярам фрагментов.

Обновление 0:

Замените:

Frag1 frag1 = new Frag1();

на

Frag1 frag1 = (Frag1)getFragmentManager().findFragmentById(R.id.yours_fragment_container);

Далее нам нужен сеттер в первом фрагменте:

public void setMyValue(int value)
{
this.myValue=value;
}

Возвращаемся ко второму фрагменту. После нахождения первого и проверки его на "null" присваиваем его полю нужное значение:

frag1.setMyValue(value);

Теперь 1-й фрагмент получил нужное значение нашего поля, и можно его призвать на экран:

fragmentManager.beginTransaction().replace(R.id.yours_fragment_container,  frag1).commit();

Обновление 1:

Итого:

  1. У вас не реализовано сохранение и восстановление данных в первом фрагменте.
  2. Заменяя первый фрагмент вторым, вы не сохраняете первый фрагмент во FragmentManager().
  3. Со второго фрагмента вы не вызываете старый, а создаёте новый который, естественно, пуст.

Выводы:

1) в первом фрагменте надо сохранять переменные так:

public class FragmentBase extends Fragment
{
//Переменные, которые надо сохранить
String myString;
int myInt;

    @Override
    public View onCreat(Bundle savedInstanceState)
    {

        //здесь восстанавливаем сохранённые переменные.
        if(savedInstanceState!=null)
        {
            //восстанавливаем
this.myString=savedInstanceState.getString("myStringKey");
this.myInt=savedInstanceState.geInt("myIntKey");
        }
    }

    @Override
    public void onSaveInstanceState(final Bundle outState)
    {
        super.onSaveInstanceState(outState);
//Сохраняем данные
outState.putString("myStringKey", this.myString);
outState.putInt("myIntKey", this.myInt);

    }
}

2) вызывая второй фрагмент, не забывайте добавить первый в FragmentManager:

FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction transaction=fragmentManager.beginTransaction();
transaction.addToBackStack(null);
transaction.replace(R.id.content_frame,  frag2);
transaction.commit();

3) во втором фрагменте вызывайте сохранённый 1-й фрагмент с сохранённым состоянием:

FragmentManager fragmentManager = getFragmentManager();
Fragment1 frag1=fragmentManager.findFragmentById(R.id.content_frame);
FragmentTransaction transaction=fragmentManager.beginTransaction();
transaction.replace(R.id.content_frame,  frag1);
transaction.commit();

И последнее, но не по важности:

Все эти вопросы обычно и не возникают, если прочитать хотя бы одну книгу по Андроид, а если и возникают, то решаются гуглом за 5 минут. Вы вряд ли научитесь программировать, если будете решать отдельные проблемы в коде на форумах, а не изучать архитектуру и доки.