I have been facing this problem when rotation of the screen happens.I have seen all the similar posts of the stackoverflow but no luck.
Here is my activity with two fragments NEwsList and NewsDetails NewsDetails fragment will get called when an item from the list is clicked.
public class MainActivity extends AppCompatActivity implements OnNewsItemClicked, PresenterLocator {
@Bind(R.id.news_list_fragment)
FrameLayout listFragmentContainer;
@Nullable
@Bind(R.id.news_details_fragment)
FrameLayout newsDetailsContainer;
private boolean isTablet;
private NewsScreenPresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
isTablet = newsDetailsContainer == null ? false : true;
presenter = (NewsScreenPresenter) getLastCustomNonConfigurationInstance();
if (presenter == null) {
presenter = new NewsScreenPresenter(new NewsRetrofitGateway(), this);
}
if (savedInstanceState == null) {
attachListFragment();
}
}
private void attachListFragment() {
Fragment listFragment = new NewsListFragment();
Bundle bundle = new Bundle();
bundle.putBoolean(NewsListFragment.IS_TABLET, isTablet);
listFragment.setArguments(bundle);
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.news_list_fragment, listFragment);
transaction.commit();
}
@Override
public Object onRetainCustomNonConfigurationInstance() {
return presenter;
}
@Override
public void onNewsItemClicked(String title, String summary, String picUrl, String storyUrl) {
if (!isFinishing()) {
Fragment fragment = new NewsDetailFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
fragment.setArguments(NewsDetailFragment.buildArguments(title, summary, picUrl, storyUrl));
if (!isTablet) {
transaction.add(R.id.news_list_fragment, fragment);
transaction.addToBackStack(null);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
} else {
transaction.replace(R.id.news_details_fragment, fragment);
}
transaction.commit();
}
}
@Override
public NewsScreenPresenter getPresenter() {
return presenter;
}}
NewsListFramgment
public class NewsListFragment extends Fragment implements NewsScreenView {
public static final String IS_TABLET = "is_tablet";
private NewsScreenPresenter presenter;
@Bind(R.id.progressBar)
LinearLayout progressBar;
@Bind(R.id.recycler_view)
RecyclerView recyclerView;
private boolean isTablet;
private PresenterLocator locator;
@Override
public void onAttach(Context context) {
super.onAttach(context);
locator = (PresenterLocator) context;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View listView = inflater.inflate(R.layout.new_list_layout, null);
ButterKnife.bind(this, listView);
return listView;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclerView.setHasFixedSize(true);
LinearLayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(mLayoutManager);
isTablet = getArguments().getBoolean(IS_TABLET);
}
@Override
public void onResume() {
super.onResume();
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
presenter = locator.getPresenter();
presenter.onViewCreated(this);
}
@Override
public void showProgressBar() {
progressBar.setVisibility(View.VISIBLE);
}
@Override
public void hideProgress() {
if (progressBar.getVisibility() == View.VISIBLE) {
progressBar.setVisibility(View.GONE);
}
}
@Override
public void populateNewsInList(final NewsResponseMapper news) {
NewsListAdapter adapter = new NewsListAdapter(news, new OnRecycleItemClick() {
@Override
public void onItemClick(int position) {
presenter.onItemClick(position);
}
});
recyclerView.setAdapter(adapter);
if (isTablet) {
presenter.onItemClick(0);
}
}
@Override
public void showError(String errorMsg) {
Toast.makeText(getActivity(), errorMsg, Toast.LENGTH_LONG).show();
}
interface OnRecycleItemClick {
void onItemClick(int position);
}
NewsDetialsFragment
public class NewsDetailFragment extends Fragment {
public static final String STORY_URL = "storyURL";
public static final String TITLE = "title";
public static final String SUMMARY = "summary";
public static final String IMAGE_URL = "imageURL";
private BrowserNavigation browserNavigation;
@Bind(R.id.title)
TextView titleView;
@Bind(R.id.summary_content)
TextView summaryView;
@Bind(R.id.news_image)
DraweeView imageView;
public static Bundle buildArguments(String title, String summary,
String picUrl, String storyUrl) {
Bundle bundle = new Bundle();
bundle.putString(TITLE, title);
bundle.putString(SUMMARY, summary);
bundle.putString(IMAGE_URL, picUrl);
bundle.putString(STORY_URL, storyUrl);
return bundle;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View detailsView = inflater.inflate(R.layout.activity_detail, null);
ButterKnife.bind(this, detailsView);
return detailsView;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Bundle extras = getArguments();
String storyURL = extras.getString(STORY_URL);
String title = extras.getString(TITLE);
String summary = extras.getString(SUMMARY);
String imageURL = extras.getString(IMAGE_URL);
browserNavigation = new BrowserNavigation(getActivity(), storyURL);
titleView.setText(title);
summaryView.setText(summary);
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
.setImageRequest(ImageRequest.fromUri(Uri.parse(imageURL)))
.setOldController(imageView.getController()).build();
imageView.setController(draweeController);
}
@OnClick(R.id.full_story_link)
public void fullStoryClicked() {
browserNavigation.navigate();
}
By Looking at the code you can understand that i am following MVP architecture and while i see the NewsListFragment and rotate the device i am saving my presenter in the activity using onRetianCustomNonConfiguration() callback, so as not to call the server again to fetch the list of news again. Everything works fine as expected but after the rotation whenever i try to click an item in the list to show the DetailsFragment(onNewsItemClick()) it crashes with illegalStateException "can't perform this action after OnSavedInstanceState".
Can anyone point out the mistake i am doing here?
FATAL EXCEPTION: main
Process: news.agoda.com.technewssample, PID: 24160
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1493)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1511)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:638)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:617)
at news.agoda.com.sample.presentation.MainActivity.onNewsItemClicked(MainActivity.java:96)
at news.agoda.com.sample.NewsScreenPresenter.onItemClick(NewsScreenPresenter.java:55)
at news.agoda.com.sample.presentation.NewsListFragment$1.onItemClick(NewsListFragment.java:89)
at news.agoda.com.sample.presentation.NewsListAdapter$1.onClick(NewsListAdapter.java:76)
at android.view.View.performClick(View.java:4785)
at android.view.View$PerformClick.run(View.java:19888)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5276)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:911)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:706)