I've got a problem with my android app crashing when trying to restore my fragments. I have not added any custom variables to the bundle that I'm trying to restore, It's all default. I'm using Fragments and ViewPager. See my code snippets below:
public static class MyAdapter extends FragmentStatePagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return NUM_ITEMS;
}
public int getCurrentItemPosition(Fragment fragment){
return getItemPosition(fragment);
}
#Override
public Fragment getItem(int position) {
return ContentFragment.newInstance(position);
}
}
public class MyActivity extends FragmentActivity {
static final int NUM_ITEMS = 100000;
public int currentSelectedPage;
private int changeToFragmentIndex;
public DateTime midDate;
MyAdapter mAdapter;
ViewPager mPager;
/** Called when the activity is first created. */
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.diary);
MyApplication application = (MyApplication)getApplication();
application.dataController.myActivity = this;
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = (ViewPager)findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
int newDay = application.daysBetween(DateTime.now(), DateTime.parse(application.day.dateToShortString()));
this.currentSelectedPage = NUM_ITEMS/2+newDay;
mPager.setCurrentItem(NUM_ITEMS/2+newDay);
mPager.setOnPageChangeListener(new SimpleOnPageChangeListener(){
public void onPageSelected(int position){
currentSelectedPage = position;
ContentFragment fragment = (ContentFragment) mAdapter.instantiateItem(mPager, currentSelectedPage);
fragment.loadData();
}
});
}
}
public class ContentFragment extends Fragment {
private View v;
static final int NUM_ITEMS = 100000;
static ContentFragment newInstance(int num) {
ContentFragment f = new ContentFragment();
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (container == null)
return null;
v = inflater.inflate(R.layout.diarycontent, container, false);
return v;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState){
super.onSaveInstanceState(savedInstanceState);
setUserVisibleHint(true);
}
}
I receive this stackstrace:
Caused by: java.lang.NullPointerException
at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:519)
at android.support.v4.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:1 55)
at android.support.v4.view.ViewPager.onRestoreInstanceState(ViewPager.java:522)
As I have understood this may be a known problem with the support package and that one possible solution would be to use setUserVisibleHint(true) in onSaveInstanceState. But that didn't help.
Does anyone know another solution to the problem or what I've done wrong?
I have faced same type of issue once I started using ViewPager with FragmentStatePagerAdapter inside Tab.
Then I played with all forums related to this issue and break my head for two days to find out why this issue is occurred and how to resolve it but does not found any perfect solution that fulfills as per my requirement.
I got the solution as in order to avoid the NPE crash use FragmentPagerAdapter instead of FragmentStatePagerAdapter. When I replace FragmentPagerAdapter instead of FragmentStatePagerAdapter then not faced NPE crash issue but the same page is not refreshed itself for further navigation(which is my requirement).
Finally override the saveState method on FragmentStatePagerAdapter and everything working fine as expected.
#Override
public Parcelable saveState() {
// Do Nothing
return null;
}
How I reproduce this issue easily :
I am using the higher version(4.1) device and followed the below steps:
1. Go to Settings -> Developer Options.
2. Click the option "Do not keep activities".
Now I played with my app.
Before override the saveState() method each time the app is crashing due to the NPE at android.support.v4.app.FragmentManagerImpl.getFragment(Unknown Source). But after override saveState() no crash is registered.
I hope by doing so you will not having any issue.
I initially used solution suggested by #Lalit Kumar Sahoo. However, I noticed a serious issue: every time I rotated the device, the Fragment Manager added new fragments without removing the old ones. So I searched further and I found a bug report with a workaround suggestion (post #1). I used this fix and tested with my app, the issue appears to be resolved without any side-effects:
Workaround: Create custom FragmentStatePagerAdapter in project's src/android/support/v4/app folder and use it.
package android.support.v4.app;
import android.os.Bundle;
import android.view.ViewGroup;
public abstract class FixedFragmentStatePagerAdapter extends FragmentStatePagerAdapter {
public FixedFragmentStatePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment f = (Fragment)super.instantiateItem(container, position);
Bundle savedFragmentState = f.mSavedFragmentState;
if (savedFragmentState != null) {
savedFragmentState.setClassLoader(f.getClass().getClassLoader());
}
return f;
}
}
Why exactly are you doing:
mPager.setOnPageChangeListener(new SimpleOnPageChangeListener(){
public void onPageSelected(int position){
currentSelectedPage = position;
ContentFragment fragment = (ContentFragment) mAdapter.instantiateItem(mPager, currentSelectedPage);
fragment.loadData();
}
});
This:
#Override
public Fragment getItem(int position) {
return ContentFragment.newInstance(position);
}
Instantiates the fragment.
You can load data like this in the fragment :
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
loadData();
}
Related
I have an Activity with three tabs and three Fragments. First Fragment shows the list of song titles and the second tab displays the selected song. The details of the songs is coming from a database.
I am implementing SearchView feature so that whatever search text user enters, only those songs should be displayed in the index.
This is exactly like the way phone book work in our devices.
I'm not able to understand how to refresh the first Fragment when the search query changes.
I'm basically looking for the method that I can call to refresh the first Fragment.
Got my answer here Android refresh a fragment list from its parent activity as suggested by #Prem. Works perfectly fine for me.
Its is achievable by making an interface
MainActivity.java
public class MainActivity extends Activity {
public FragmentRefreshListener getFragmentRefreshListener() {
return fragmentRefreshListener;
}
public void setFragmentRefreshListener(FragmentRefreshListener fragmentRefreshListener) {
this.fragmentRefreshListener = fragmentRefreshListener;
}
private FragmentRefreshListener fragmentRefreshListener;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button b = (Button)findViewById(R.id.btnRefreshFragment);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(getFragmentRefreshListener()!=null){
getFragmentRefreshListener().onRefresh();
}
}
});
}
public interface FragmentRefreshListener{
void onRefresh();
}}
MyFragment.java
public class MyFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = null; // some view
/// Your Code
((MainActivity)getActivity()).setFragmentRefreshListener(new MainActivity.FragmentRefreshListener() {
#Override
public void onRefresh() {
// Refresh Your Fragment
}
});
return v;
}}
Below is the one way, you can easily do it. You just have to save the fragment instance. That's all.
private class ViewPagerAdapter extends FragmentStatePagerAdapter {
private SparseArray<Fragment> array = new SparseArray<>();
ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
array.setValueAt(position, myFragment);
return myFragment;
}
#Override
public int getCount() {
return 3;
}
public SparseArray<Fragment> getFragmentArray() {
return array;
}
}
Then from your activity, you can get all viewpager fragment easily from adapter instance.
MyFragment fragment = (MyFragment) adapter.getFragmentArray().get(0); // get first fragment and casting it to your origin fragment
Then create a method on that fragment. Call like below:
fragment.myFragmentMethod(String myData){}
Have a nice day!
I am trying to call the functions frag.updateButtons() etc from within GameScreen (Main Activity) as ten times a second, the game cycles through these things and updates the variables accordingly.
The code is as it currently is. The frag.*** functions work when it is set up as a fragment, but now that I am wanting to use it as viewPager, it keeps having the following error:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.support.v4.app.FragmentActivity.findViewById(int)' on a null object reference
I am fairly new to programming and Android code, and clearly don't entirely understand fragments and viewPager etc, so any help here would be very much appreciated.
I have not included the whole code, just the code that I think is relevant to the problem. If you need more code or info, please ask me and I'll get you what you need.
Thank you
public class GameScreen extends FragmentActivity implements GameScreenFragment.FragInterface{
ViewPager mViewPager;
GameScreenFragment frag;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game_screen);
mViewPager = (ViewPager) findViewById(R.id.bottomFragment);
/** set the adapter for ViewPager */
mViewPager.setAdapter(new SamplePagerAdapter(getSupportFragmentManager()));
startRepeatingTask();
//the code here calls the mainLoop() function 10 times a second
}
}
//for the fragment functions
public void displayCompany(String companyName){}
public void displayCompanyIncome(){}
public void checkTeamImage(){}
public void getCostOfEmployees(){}
public void updateButtons(){}
public void mainLoop(){
//display company name and company income in fragment
frag = (GameScreenFragment) getSupportFragmentManager().findFragmentById(R.id.bottomFragment);
frag.updateButtons();
frag.displayCompanyIncome();
frag.getCostOfEmployees();
frag.displayCompany(Global.companyName[Global.companyNumber]);
//updates the picture for that company
frag.checkTeamImage();
}
public class SamplePagerAdapter extends FragmentPagerAdapter {
public SamplePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public android.support.v4.app.Fragment getItem(int position) {
/** Show a Fragment based on the position of the current screen */
Global.companyNumber = position;
return new GameScreenFragment();
}
#Override
public int getCount() {
// Show 2 total pages.
return 2;
}
}
}
and then in the fragment whose ID in the .xml is bottomFragment
public class GameScreenFragment extends Fragment {
FragInterface fragStuff;
public interface FragInterface {
void displayCompany(String companyName);
void displayCompanyIncome();
void checkTeamImage();
void getCostOfEmployees();
void displayCompanyName();
void updateButtons();
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState){
View view = inflater.inflate(R.layout.game_screen_fragment, container, false);
//other code here
return view;
}
}
I must clear that I am looking for an example or answer where I can use various differnt layout designs in a viewpager and the data in all the pages would be dynamic and all pages can be interacted by the user.
My Use Case and current approach towards the problem :
So I have got 8 different types of question types and so I have created layouts for all of them. Also I the data in the views for these layouts has to be populated via java Map that has fetched data from the sqlite DB.
But a test may contain 25 questions with different layouts out of the above 8. And for all these 25 questions I want to use a Viewpager and a Fragment that will return the required layout based on the passed question type value out of my java map.
My apporach towards this :
I have created an activity and have inflated it with a viewpager layout :
R.layout.practice_pager
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/test_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
*Activity Edited code *
public class TestActivity extends FragmentData implements FragmentData{
FragmentManager manager=getSupportFragmentManager();
private ViewPager mViewPager;
private MyFragmentPagerAdapter mMyFragmentPagerAdapter;
int PAGE_COUNT = 0;
GrePracticeTestRecord p=new GrePracticeTestRecord();
private HashMap<Integer, GrePracticeResultRecord> mPracResultMap;
public static int fragmentToReturn=0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.practice_pager);
mViewPager = (ViewPager) findViewById(R.id.test_container);
//This function is called to fetch the data from sqlite db and fill the map with data
LoadingTestView();
PAGE_COUNT=mPracRecordMap.size();
initPager();
}
//here I initialize the pager and set the adapter to it
public void initPager()
{
p.setQUES(mPracRecordMap.get(1).getQUES());
p.setEXPL(mPracRecordMap.get(1).getEXPL());
fragmentToReturn=Integer.parseInt(mPracRecordMap.get(1).getQTYPE());
setData(p);
mMyFragmentPagerAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager(),fList);
mViewPager.setAdapter(mMyFragmentPagerAdapter);
mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int arg0) {
mMyFragmentPagerAdapter.notifyDataSetChanged();
p.setQUES(mPracRecordMap.get(mViewPager.getCurrentItem()+1).getQUES());
p.setEXPL(mPracRecordMap.get(mViewPager.getCurrentItem()+1).getEXPL());
setData(p);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
#Override
public void setData(GrePracticeTestRecord p) {
// TODO Auto-generated method stub
}
#Override
public GrePracticeTestRecord getData() {
// TODO Auto-generated method stub
return p;
}
}
My Adapter Edited code
public class MyFragmentPagerAdapter extends FragmentStatePagerAdapter{
private List<Fragment> fragments;
public MyFragmentPagerAdapter(FragmentManager fm,List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
/** This method will be invoked when a page is requested to create */
#Override
public Fragment getItem(int position) {
System.out.println("value of position "+position);
return this.fragments.get(position);
}
/** Returns the number of pages */
#Override
public int getCount() {
return this.fragments.size();
}
#Override
public int getItemPosition(Object object) {
// TODO Auto-generated method stub
return MyFragmentPagerAdapter.POSITION_NONE;
}
}
Interface FragmentData
public interface FragmentData {
public void setData(GrePracticeTestRecord p);
public GrePracticeTestRecord getData();
}
TestFragment Edited code
public class TestFragment extends Fragment {
AnswerEnterListener callBack;
FragmentData fD;
Button submitAnswer;
EditText userAnswer;
TextView qText,expl;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.qtype1, container, false);
}
public interface AnswerEnterListener
{
public void onInputAnswer(String ans);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
callBack=(AnswerEnterListener) activity;
fD=(FragmentData) activity;
} catch (Exception e) {
// TODO: handle exception
}
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
qText=(TextView) getActivity().findViewById(R.id.question_text);
expl=(TextView)getActivity().findViewById(R.id.explanation_text);
qText.setText(Html.fromHtml(fD.getData().getQUES()));
expl.setText(Html.fromHtml(fD.getData().getEXPL()));
}
}
Similar to TestFragment , I have not the other fragments too. Each for a layout type.
Issues :
The first layout is repeated two times at the first time , and also when I swipe back then the position of data is misplaced.
Is this the right approach, I have been suggested by someone that you should use three fragments and update the left and right fragments with data , but this actually bounced off me. Can anyone share a good example of it or a blog.
I must clear that I am looking for an example or answer where I can
use various differnt layout designs in a viewpager and the data in all
the pages would be dynamic and all pages can be interacted by the
user.
This should be quite easy to make but you seem to have complicated this a lot. You need to do something like this:
Get the data from the database with the LoadingTestView(); function.
Initialize the ViewPager and set it's adapter. The adapter will return the proper fragment instance in the getItem() method, based on whatever criteria you have.
In the fragments, retrieve the data from the activity which should expose the data through some method.
I've made a simple example that you can find here.
I'm having a strange issue with fragment views not refreshing properly, but it only happens after the app is closed and re-opened after some amount of time.
I have a TabSwitcherActivity which contains a ViewPager. The ViewPager switches between 3 fragments, and each fragment represents a different view of the same information. There are certain events that can happen which will cause the information to become stale, so the fragments need to be notified to refresh the view. To accomplish this, my TabSwitcherActivity has a method called notifyDataSetChanged() which will iterate the 3 fragments and tell them to refresh. Here is (I think) the most relevant code:
public class TabSwitcherActivity extends FragmentActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Used to keep track of the child fragments of this activity so we can update their list adapters.
mFragments = new ArrayList<Fragment>();
// Set up the view pager and tab adapter.
setContentView(R.layout.pager_layout);
mViewPager = (ViewPager) super.findViewById(R.id.pager);
mFragments.add(Fragment.instantiate(this, FragmentOne.class.getName()));
mFragments.add(Fragment.instantiate(this, FragmentTwo.class.getName()));
mFragments.add(Fragment.instantiate(this, FragmentThree.class.getName()));
mViewPager.setAdapter(new ListPagerAdapter(super.getSupportFragmentManager(), mFragments));
}
public void notifyDataSetChanged() {
for (Fragment fragment : mFragments) {
if (fragment instanceof IDataSetChangedListener) {
((IDataSetChangedListener) fragment).notifyDataSetChanged();
}
}
}
}
Now, this works as intended the first time the app is launched. The problem is that after the app is closed and re-opened some time later, calling TabSwitcherActivity.notifyDataSetChanged() while the app is running does not update the fragment views (this works the first time the app is started after a reboot). This leads me to believe that there is a life cycle situation with the fragments that I'm not handling correctly. Any idea what this might be? It occurs to me that If the fragments are destroyed and recreated, they are probably not correctly stored in my mFragments array.
I'm answering my own question in case others have a similar problem to what I had. I was able to resolve the problem based on the comments from invertigo. I'll post some generified pieces of the important parts of the code.
As I suspected, the fragments stored in the array were not correctly updated if they were destroyed and re-created by the application. (This would sometimes happen when the application was closed and re-opened.) It was a little bit tricky to remove the array since I was using it to store the fragments for my tabs in my FragmentPagerAdapter implementation.
Here is my old ListPagerAdapter class:
public class ListPagerAdapter extends FragmentPagerAdapter {
private List<Fragment> mFragments;
public ListPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
mFragments = fragments;
}
#Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
#Override
public int getCount() {
return mFragments.size();
}
#Override
public String getPageTitle(int position) {
return ((ITitledFragment) mFragments.get(position)).getTitle();
}
}
Here is my new implementation, which removes the problem caused by the array holding bad fragment references:
public class ListPagerAdapter extends FragmentPagerAdapter {
private static final int FRAGMENT_ONE_POSITION = 0;
private static final int FRAGMENT_TWO_POSITION = 1;
private static final int FRAGMENT_THREE_POSITION = 2;
private static final int COUNT = 3;
public ListPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case FRAGMENT_ONE_POSITION:
return new FragmentOne();
case FRAGMENT_TWO_POSITION:
return new FragmentTwo();
case FRAGMENT_THREE_POSITION:
return new FragmentThree();
}
return null;
}
#Override
public int getCount() {
return COUNT;
}
#Override
public String getPageTitle(int position) {
switch (position) {
case 0:
return FragmentOne.getTitle();
case 1:
return FragmentTwo.getTitle();
case 2:
return FragmentThree.getTitle();
}
return null;
}
}
Then, the only remaining problem is how to have the my TabSwitcherActivity class update all of the fragments when they are stale. As invertigo pointed out, this can be done with tags. However, I decided to use an approach where each fragment registers itself with the activity when it is created, and unregisters itself before it is destroyed. The activity can iterate registered fragments to update them.
The Relevant code from TabSwitcherActivity:
class TabSwitcherActivity extends FragmentActivity {
private List<Fragment> mFragments;
private void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Used to keep track of the child fragments of this activity so we can update their list adapters.
mFragments = new ArrayList<Fragment>();
// Set up the view pager and tab adapter.
setContentView(R.layout.pager_layout);
mViewPager = (ViewPager) super.findViewById(R.id.pager);
mViewPager.setAdapter(new ListPagerAdapter(super.getSupportFragmentManager()));
}
public void startTrackingFragment(Fragment f) {
mFragments.add(f);
}
public void stopTrackingFragment(Fragment f) {
mFragments.remove(f);
}
public void notifyDataSetChanged() {
for (Fragment fragment : mFragments) {
if (fragment instanceof IDataSetChangedListener) {
((IDataSetChangedListener) fragment).notifyDataSetChanged();
}
}
}
}
With that, all that remains is to have the fragments register themselves for updates:
public class FragmentOne extends Fragment implements IDataSetChangedListener {
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
((TabSwitcherActivity) getActivity()).startTrackingFragment(this);
}
public void onDestroy() {
((TabSwitcherActivity) getActivity()).stopTrackingFragment(this);
super.onDestroy();
}
}
You could always just refresh the data in onResume() of your fragments, or call notifyDataSetChanged() in onResume() of your activity.
re: "It occurs to me that If the fragments are destroyed and recreated, they are probably not correctly stored in my mFragments array."
Instead of storing the fragments in an array, use the fragment manager to fetch the fragments by tag or id.
http://developer.android.com/guide/components/fragments.html#Managing
http://developer.android.com/reference/android/app/FragmentManager.html#findFragmentByTag(java.lang.String)
I'm currently trying to work with fragment, but I'm stuck with an issue I can't solve.
I have one activity, which holds 4 different fragment. From this activity, I launch an ASyncTask which goes to the web and get different data I need, and then will send it to the fragments.
But, when my app gets killed and opened again, or when I change the orientation, my fragments are apparently recreated and my custom FragmentAdapter doesn't hold the good reference to the fragment.
Here is the code of my main activity.
public class MainActivity extends FragmentActivity {
MyPagerAdapter fgsAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//...
FragmentManager fm = super.getSupportFragmentManager();
fgsAdapter = new MyPagerAdapter(fm,this);
ViewPager myPager = (ViewPager) findViewById(R.id.home_pannels_pager);
myPager.setAdapter(fgsAdapter);
myPager.setCurrentItem(0);
}
#Override
protected void onResume() {
super.onResume();
ATaskGetUser task = new ATaskGetUser(callback, (ProgressBar) findViewById(R.id.PB_AsyncTask));
task.execute();
}
//What's called by the ASyncTask onPostExecute()
private void notifyDataChanged() {
fgsAdapter.notifyFragments(user.getItems());
}
private class MyPagerAdapter extends FragmentPagerAdapter {
private List<CardFragment> fragments = new ArrayList<CardFragment>();
private Context c;
public MyPagerAdapter(FragmentManager fm, Context c) {
super(fm);
CardFragment h = new HabitFragment();
CardFragment d = new DailyFragment();
CardFragment t = new ToDoFragment();
CardFragment r = new RewardFragment();
fragments.add(h);
fragments.add(d);
fragments.add(t);
fragments.add(r);
}
public int getCount() {
return fragments.size();
}
#Override
public CardFragment getItem(int position) {
Log.v("MainActivity_fgsmanager", "getItem()");
CardFragment f = (CardFragment) this.fragments.get(position);
return f;
}
public void notifyFragments(List<HabitItem> items) {
for(OnTasksChanged f : fragments) {
f.onChange(items);
}
}
}
}
So, what I want to be able to do, is to be able to call the onChange (an interface implemented by my four fragments), in my notifyDataChanged function. Is this possible, are am I thinking the wrong way?
I got the same problems once with Fragments, I was losing the current fragment after every screen rotation.
I simply solved it by adding one line in the Fragment class (not in the parent FragmentActivity class):
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.rate_fragment, container,false);
setRetainInstance(true);//Added not to lose the fragment instance during screen rotations
(...)
For your case where your app gets killed and opened again, I am not sure it will work though.