Basically i tried doing a fragment transaction inside a background thread, and i get can't perform this action after onSavedInstanceState. This is what i have done:
I have an activity with two fragments, Fragment A (Contains UI all elements) and Fragment B(contains progress bar) . When the activity is created fragment A is added so the user sees UI elements(Buttons and Edittexts). Then when a button is clicked in Fragment A, (1) a background task is started in the parent activity, and (2) Fragment A is replaced with Fragment B. All this works fine.
But when the task is finished if the task was successful i would like to start a new activity and if it fails i want the current fragment to be replaced with the original one. I have no problem with starting the activity, but when i try to do the fragment transaction, the app crashes saying can't perform this action after onSavedInstanceState
.
I did a lot of research on this and found a lot of useful things here, here, but i still haven't been able to solve my problem. The first link is a question on SO, one of the answers was to shift calling the fragment transaction to the onResume method of the activity, but i don't know how to do this. Also i tried using commitAllowingStateLoss
and the app still crashes, but the logcat says Activity has been destroyed
.
Note: If there is no configuration change, everything runs smoothly.
Here is my Code:
Containing Activity
public class MainActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i("tag", "mainActivity onCreate");
Fragment taskf =getSupportFragmentManager().findFragmentByTag("taskfrag");
//Put the Fragment A if Fragment B is not showing
if(savedInstanceState == null){
if(taskf == null){
Log.i("tag", "MainFragment added");
FragmentTransaction fragmentTransaction= getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.wrapper, new MainFragment() , "mainfrag").commit();
}
}
}
//Fragment B is added here
public void addFragment(){
Log.i("tag", "fragment added");
this.getSupportFragmentManager().beginTransaction().replace(R.id.wrapper, new TaskFragment(), "taskfrag").commit();
}
// My dummy Task
public void startTask(){
Log.i("tag", "start Task");
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 100; i++) {
Log.i("tag", "publishProgress(" + i + "%)");
SystemClock.sleep(100);
}
getSupportFragmentManager().beginTransaction().replace(R.id.wrapper, new MainFragment(), "mainfrag").commitAllowingStateLoss();
}
}).start();
}
}
Fragment A
public class MainFragment extends Fragment {
View fView;
ProgressBar bar;
TextView textView;
Button button;
@Override
public void onCreate(Bundle savedInstanceState) {
Log.i("tag", "onCreate in Main Fragment ");
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
Log.i("tag", "onCreate View in Mainfragment");
fView = inflater.inflate(R.layout.mainfragment, container, false);
textView = (TextView) fView.findViewById(R.id.textview);
button = (Button) fView.findViewById(R.id.button);
//Button Click Listener
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Log.i("tag", "button clicked");
((MainActivity)getActivity()).startTask();
((MainActivity)getActivity()).addFragment();
}
});
return fView;
}
}
Fragment B
public class TaskFragment extends Fragment{
View fview;
ProgressBar bar;
@Override
public void onCreate(Bundle savedInstanceState) {
Log.i("tag", "TaskFragment Created");
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
Log.i("tag", "onCreateView in TaskFragment");
fview = inflater.inflate(R.layout.progressfragment, container, false);
bar = (ProgressBar) fview.findViewById(R.id.sendingSmsProgress);
return fview;
}
}
Thanks.