Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Save/Restore fragments state android

I am trying to create an app that uses Jack Wharton's ViewPager library (here) using only images for every page (something like Prixing (here) main screen). Everything works ok, except for the saveInstance in the Fragment.

In Jack Wharton's example, he stores the text in a String variable, named mContent, and restores it in onCreate, but in my case, what should I do? Save/Restore a bitmap?! Any objective answer would be much appreciated!

I'm quite new to this Fragment using applications, cause every example I look at, presents only the basics, and it's getting difficult upon more complex ones.

PS. If is it usefull to know, I'm using CirclePageIndicator.

Current Fragment Code here:

    public final class SpecialOfferFragment extends Fragment {

    private int imageResourceId;

    public static SpecialOfferFragment newInstance(int i) {

        //probably I'll use a bitmap(downloaded) as parameter instead of using static images
        SpecialOfferFragment fragment = new SpecialOfferFragment();

        fragment.imageResourceId = i;

        return fragment;
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // if ((savedInstanceState != null) { }

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        ImageView image = new ImageView(getActivity());
        image.setImageResource(imageResourceId);
        image.setScaleType(ScaleType.FIT_XY);

        LinearLayout layout = new LinearLayout(getActivity());
        layout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
                LayoutParams.FILL_PARENT));

        layout.setGravity(Gravity.CENTER);
        layout.addView(image);

        return layout;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        //smth to save here..
    }
}

In this current state of the app, I get the following Exception:

04-12 07:28:17.760: E/AndroidRuntime(31903): FATAL EXCEPTION: main 
04-12 07:28:17.760: E/AndroidRuntime(31903): java.lang.NullPointerException
04-12 07:28:17.760: E/AndroidRuntime(31903): at android.support.v4.app.FragmentManagerImpl.saveFragmentBasicState(FragmentManager.java:1576)
04-12 07:28:17.760: E/AndroidRuntime(31903):    at android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.java:1617)
04-12 07:28:17.760: E/AndroidRuntime(31903):    at android.support.v4.app.FragmentActivity.onSaveInstanceState(FragmentActivity.java:481)
04-12 07:28:17.760: E/AndroidRuntime(31903):    at android.app.Activity.performSaveInstanceState(Activity.java:1113)
04-12 07:28:17.760: E/AndroidRuntime(31903):    at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1188)
04-12 07:28:17.760: E/AndroidRuntime(31903):    at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:2804)
04-12 07:28:17.760: E/AndroidRuntime(31903):    at android.app.ActivityThread.handleStopActivity(ActivityThread.java:2862)
04-12 07:28:17.760: E/AndroidRuntime(31903):    at android.app.ActivityThread.access$900(ActivityThread.java:127)
04-12 07:28:17.760: E/AndroidRuntime(31903):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1175)
04-12 07:28:17.760: E/AndroidRuntime(31903):    at android.os.Handler.dispatchMessage(Handler.java:99)
04-12 07:28:17.760: E/AndroidRuntime(31903):    at android.os.Looper.loop(Looper.java:137)
04-12 07:28:17.760: E/AndroidRuntime(31903):    at android.app.ActivityThread.main(ActivityThread.java:4511)
04-12 07:28:17.760: E/AndroidRuntime(31903):    at java.lang.reflect.Method.invokeNative(Native Method)
04-12 07:28:17.760: E/AndroidRuntime(31903):    at java.lang.reflect.Method.invoke(Method.java:511)
04-12 07:28:17.760: E/AndroidRuntime(31903):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:980)
04-12 07:28:17.760: E/AndroidRuntime(31903):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:747)
04-12 07:28:17.760: E/AndroidRuntime(31903):    at dalvik.system.NativeStart.main(Native Method)

This happens whenever I pause/stop the activity containing this fragment, like pushing the Home button.

**

EDIT with code:

**

 public class MainMenu extends FragmentActivity {

    //private List<CategoriesHolder> categoriesList = new ArrayList<CategoriesHolder>();
    //private CategoriesAdapter categoriesAdapter = null;
    //private GridView gv_mainmenu_categories;

    SpecialOfferFragmentAdapter mAdapter;
    ViewPager mPager;
    PageIndicator mIndicator;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_mainmenu);

        linkUI();
        setAction();

        // just for testing
        String[] imagesUrls = null;

        mAdapter = new SpecialOfferFragmentAdapter(getSupportFragmentManager(),
                this, imagesUrls);

        //categoriesAdapter = new CategoriesAdapter(this, categoriesList);

        // used for Categories GridView
        //gv_mainmenu_categories.setAdapter(categoriesAdapter);

        // used for ViewPager
        mPager.setAdapter(mAdapter);
        mIndicator.setViewPager(mPager);

    }

    private void linkUI() {
        mPager = (ViewPager) findViewById(R.id.vp_mainmenu_special_offers);
        mIndicator = (CirclePageIndicator) findViewById(R.id.indicator);

        //gv_mainmenu_categories = (GridView) findViewById(R.id.gv_mainmenu_categories);

    }

    private void setAction() {

    }
} 

    public class SpecialOfferFragmentAdapter extends FragmentPagerAdapter implements
        IconPagerAdapter {

    private int[] mCarouselImages = new int[] { R.drawable.pic1,
            R.drawable.pic2, R.drawable.pic3, R.drawable.pic4, R.drawable.pic5

    };

    private String[] imagesUrls;
    private Context context;

    public static final int[] ICONS = new int[] {
            R.drawable.perm_group_calendar, R.drawable.perm_group_camera,
            R.drawable.perm_group_device_alarms, R.drawable.perm_group_location };

    private int mCount = mCarouselImages.length;

    public SpecialOfferFragmentAdapter(FragmentManager fm, Context context,
            String[] imagesUrls) {
        super(fm);
        this.context = context;
        this.imagesUrls = imagesUrls;
    }

    @Override
    public Fragment getItem(int position) {

        return SpecialOfferFragment.newInstance(mCarouselImages[position]);
    }

    @Override
    public int getCount() {
        return mCount;
    }

    @Override
    public int getIconResId(int index) {
        return ICONS[index % ICONS.length];
    }

    public void setCount(int count) {
        if (count > 0 && count <= 10) {
            mCount = count;
            notifyDataSetChanged();
        }
    }
}
like image 978
DoruAdryan Avatar asked Apr 12 '13 07:04

DoruAdryan


People also ask

How can I save an activity state using the Save instance state?

When the activity goes into the background, the system calls onSaveInstanceState() . You should save the search query in the onSaveInstanceState() bundle. This small amount of data is easy to save. It's also all the information you need to get the activity back into its current state.

How do you restore the state of an Android activity?

State can be restored in either the onCreate() or the onRestoreInstanceState() methods of the activity by extracting values from the Bundle object and updating the activity based on the stored values.

What is retained fragment Android?

A Fragment represents a reusable portion of your app's User Interface. Retained Fragment consists of the configuration change that causes the underlying Activity to be destroyed. The term "retained" refers to the fragment that will not be destroyed on configuration changes.

How do you save kotlin state?

Saving the State The first step in extending the StateChange application is to make sure that the text entered by the user is extracted from the EditText component within the onSaveInstanceState() method of the StateChangeActivity activity, and then saved as a key-value pair into the Bundle object.


2 Answers

To achieve the thing which you want, you should use integer value to store the current position in your ViewPager, and after that use this value to set the right position to your ViewPager.

For example do something like this in your FragmentActivity:

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
  super.onSaveInstanceState(savedInstanceState);
  savedInstanceState.putInt("mMyCurrentPosition", mPager.getPosition());
}

@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
  super.onRestoreInstanceState(savedInstanceState);
  mMyCurrentPosition = savedInstanceState.getInt("mMyCurrentPosition");
  // where mMyCurrentPosition should be a public value in your activity.
}

which will saved your ViewPager's last position. And after that in your onResume() for example you can check

if(mMyCurrentPosition != 0){
    mPager.setCurrentItem(mMyCurrentPosition);
}

I think this should work , it's not a good practice to save images / bitmaps in bundle (and I don't think you are able to do it).

like image 124
hardartcore Avatar answered Oct 22 '22 06:10

hardartcore


Ok first id like to clear something up that might solve your confusion about savedinstancestate. Savedinstancestate can only handle primitives ( int, double, float, byte..) and the String object. This should be all you need but in some cases you want to save instances of other objects as well. For this you would need some other pattern to accomplish the job, for example a factory pattern wich holds an array of all your bitmaps. Like for instance create a class ImageFactory that holds a static ArrayList of bitmaps. Whenever you rotate your device the oncreateview and onactivitycreated methods are called again and this is the moment to check if you want to retrieve information from your factory or not. for example

if(savedInstanceState != null) { //we have a savedinstancestate so there probably are saved images ImageFactory.getBMPs(); }

hope you can do something with this info. good luck

like image 24
JanCor Avatar answered Oct 22 '22 05:10

JanCor