There is a fragment that contains Spinners and Edit Texts. The user fills them in and then moves to another fragment to perform some actions there. When it comes back to the first fragment with data from frag2, you need to restore or write down programmatically what it entered before.

I do this:

Fragment 1

in onCreateView

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

in the transition code to frag2 (onClick implemented)

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

Fragment 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(); 

I think that the problem is in the second fragment (frag2), when I return to the first one. Because here you have to re-create a new instance of frag1. Therefore, null is displayed to me in LogCat.

Question: What needs to be changed in the code to implement the idea?

Sentence:
There was a thought to make a hardcode : transfer from frag1 to frag2, and then back from frag2 to frag1. But I think that there is a more humane way.

myUpdate 01 Part of my code, which is now working. I wrote about it above: http://pastebin.com/6cz1BL98

  • @web_alex is likely to destroy you. Try adding a fragment to the stack addToBackStack() . - tim_taller
  • @monomi, when switching from frag1 to frag2, register .addToBackStack (null); and all? - web_alex
  • Try setRetainInstance (true) on the fragment. - andreich
  • @monomi, did not help. ((( - web_alex

3 answers 3

I think that your problem is that the state should not be saved in the fragment arguments, but

 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: Working Example Sources

  • I added the code above in onCreateView, but after launching nothing appeared on the screen. Maybe I don’t know something, but I created it in this View method, on which I planted all my widgets. And after calling return super.onCreateView (inflater, container, savedInstanceState); I do not know how to call my rootView. - web_alex
  • @web_alex updated the response. - andreich
  • @Andreich, the first time the application initializes, it crashes. In my application, I create a fragment on the xml-layer, which I insert into the container. View rootView = inflater.inflate (R.layout.layout_fragment_layout, container, false); Then I initialize the objects from the layer and the work algorithm. - web_alex
  • one
    @web_alex I do not understand what your problem is. Here is a working example of how to transfer data between fragments back and forth. Updated the answer. - andreich

If you correctly understood your code, you have 3 errors:

  1. When replacing the 1st fragment with the second, the 1st one is not added to the FragmentManager memory by the addToBackStack(null) method (you need to commit( to the transaction commit( ) before the transaction commit( )).
  2. In the second fragment, it would not be necessary to create the new 1st fragment, but to find the old one by ID and already pass data through the setter or arguments to it.
  3. You give the arguments in the code of the second fragment (Bundle) to some "addNewTask_fragment" , and in the transaction you give a new copy of the 1st fragment ... What do you expect from this code?

Total: At a minimum, assign the arguments to the correct fragment instances.

Update 0:

Replace:

 Frag1 frag1 = new Frag1(); 

on

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

Next we need a setter in the first fragment:

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

We return to the second fragment. After finding the first one and checking it for "null", assign its desired value to the field:

 frag1.setMyValue(value); 

Now the 1st fragment received the necessary value of our field, and you can call it to the screen:

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

Update 1:

Total:

  1. You have not implemented data saving and recovery in the first fragment.
  2. By replacing the first fragment with the second, you do not save the first fragment in FragmentManager ().
  3. From the second fragment you do not call the old, but create a new one which, naturally, is empty.

Findings:

1) in the first fragment it is necessary to save the variables as follows:

 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) when calling the second fragment, do not forget to add the first one in the FragmentManager:

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

3) in the second fragment, call the saved 1st fragment with the saved state:

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

Last but not least:

All these questions usually do not arise if you read at least one book on Android, and if they do, they are solved by Google in 5 minutes. You are unlikely to learn how to program if you solve individual problems in the code on the forums, and not study the architecture and docks.

  • @Andreich, under item 2 - will you help with the code? on p.3 - "addNewTask_fragment" got out accidentally. For simplicity of the code I called frag1 and frag2 fragments. - web_alex
  • @web_alex, updated the answer. - Yuriy SPb
  • @Andreich, something didn’t get the idea at all. Why should I transfer from the 1st to the second? I need to save what was in the first to display again in the first. And it turned out that I pass from the 2nd to the first. I did this transfer using bundle, everything worked fine. - web_alex 6:39
  • @web_alex, updated the answer. - Yuriy SPb
  • @Yuriy SPb, android I study consistently. Just started working with fragments. And in the books are primitive examples that are propagated through sites and everywhere without detailed descriptions. Therefore, I study as I can. I updated the question. Added a link to the original code. - web_alex

Thank you all for your help, but in general your suggestions did not help me. I could not add it to BackStack, and then pull it out of it. Alas, on your advice nothing happened. But anyway thanks for the responsiveness. I decided to apply my own idea, which I consider correct and reasonable.

Summing up:

1. Required actions:

  • Save the previously entered / selected data in the fragment and restore it after returning to the fragment.

2. Actions to be performed by the user:

  • The data is entered into editText1, the spinner'a spin1 element is selected.

  • The transition to another fragment frag2 was performed, actions were performed on it, after which the user returns to the initial fragment frag1.

3. The code that I applied:

  • for frag1:

     EditText edit1; Spinner spin1; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.layout_frag1, container, false); edit1 = (EditText) rootView.findViewById(R.id.editText1); spin1 = (Spinner) rootView.findViewById(R.id.spiiner1); /** в теле одного из onClick получаю значения из edit1 и spin1 */ // в onClick добавляю метод, в котором все будет происходить. Мне так удобнее getAndSave(); /** bundle from Frag2() */ Bundle bdReStoreRx = getArguments(); if (bdReStoreRx != null) { // создаем переменную строку и сохраняем в нее значение из Bundle(). Затем записываем/назначаем его в edit1. String edit1Temp = bdReStoreRx.getString("edit1Temp"); edit1.setText(edit1Temp); // создаем переменную целое значение и сохраняем в нее значение позиции spinner'a. Затем назначаем его. Integer spin1Temp = bdReStoreRx.getInt("spin1Temp"); spin1.setSelection(spin1Temp); } return rootView; } public void getAndSave() { Bundle bdReStoreTx = new Bundle(); /** сохранить строку из edit1, если введена */ if (edit1.getText().length() != 0) { bdReStoreTx.putString("edit1Temp", edit1.getText().toString()); } /** сохранить выбранный элемент в spin1 */ Integer spin1_SelectedId = spin1.getSelectedItemPosition(); bdReStoreTx.putInt("spin1Temp", spin1_SelectedId); Frag2 frag2 = new Frag2(); frag2.setArguments(bdReStoreTx); android.app.FragmentManager fragmentManager = getFragmentManager(); fragmentManager.beginTransaction() .replace(R.id.content_frame, frag2).commit(); } 
  • for frag2:

String edit1Temp; Integer spin1Temp;

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.layout_frag2, container, false); // в теле onClick фрагмента frag2 будет метод sendData(); } public void sedData() { Bundle bdReStoreTx = getArguments(); /** сохранить строку addTask, если введена */ if (bdReStoreTx != null) { edit1Temp = bdReStoreTx.getString("edit1Temp"); spin1Temp = bdReStoreTx.getInt("spin1Temp"); } Frag1 frag1 = new Frag1(); Bundle bdReStoreRx* = new Bundle(); /** from frag1 */ bdReStoreRx.putString("adit1Temp", edit1Temp); bdReStoreRx.putInt("spin1Temp", spin1Temp); /** from frag2 - данные, чтобы нужно передать из frag2 в frag1. Код приема tCo, sStrings в frag1 не рассматривается в данном вопросе, но ниже передача приведена */ bdReStoreRx.putInt("tCo", tCo); bdReStoreRx.putStringArrayList("checkT", sStrings); frag1.setArguments(bdReStoreRx); /** */ android.app.FragmentManager fragmentManager = getFragmentManager(); fragmentManager.beginTransaction() .replace(R.id.content_frame, frag1).commit(); } 

  • With bdReStoreTx, we transfer data from frag1 to frag2.
  • With bdReStoreRx, we transfer data from frag2 to frag1 (we return back what was in frag1 along with what was taken from frag2.

  • Maybe someone will call the code given strange or incorrect, but I do not care for it, since the code works. The goal is achieved. Use it if necessary.

  • PS: If you find errors in the code, then write. I will rule. The above code was written from the head. Could somewhere make a mistake of the following type, you need "spin1Temp", and wrote "spinTemp", etc.