how to retain images in fragments on orientation changes

200 views Asked by At

i have a fragment in which in which i have image button "product image", I am loading an image into that imagebutton with gallery intent and loading that image using Glide library, in order to retain images i'm using onSavedInstanceState() but the problem is that when i change the orientation to landscape it retains the image, but when i again switch back to portrait mode it doesn't retains the image and gives me a null pointer exeption, if there is some technical thing which i'm doing wrong please guide because i'm kind of new to android development. here is my fragemnt code.

public class NoteEditFragment extends Fragment {

ImageButton productImage;
private static final int REQUEST_OPEN_RESULT_CODE = 0;
private Uri mImageUri;
EditText productName;
EditText productPrice;
EditText productDescription;
AlertDialog confirmDialogObject;
Uri myuri;




public NoteEditFragment() {
    // Required empty public constructor
}



@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment


    View FragmentLayout = inflater.inflate(R.layout.fragment_note_edit, container, false);
    productImage = (ImageButton) FragmentLayout.findViewById(R.id.editNoteButton);

    if(savedInstanceState != null){
           myuri = Uri.parse(savedInstanceState.getString("imageuri"));

        Glide.with(this)
                .load(myuri)
                .into(productImage);
    }

    productName = (EditText) FragmentLayout.findViewById(R.id.EditNoteTitle);

    Intent intent = getActivity().getIntent();

            });

    productImage.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent1 = new Intent(Intent.ACTION_OPEN_DOCUMENT);
            intent1.addCategory(Intent.CATEGORY_OPENABLE);
            intent1.setType("image/*");
            startActivityForResult(intent1, REQUEST_OPEN_RESULT_CODE);
        }
    });

    return FragmentLayout;
}
@Override
public void onSaveInstanceState(Bundle outState) {

    if(mImageUri != null){
        outState.putString("imageuri",mImageUri.toString());}
    super.onSaveInstanceState(outState);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
    if(requestCode == REQUEST_OPEN_RESULT_CODE && resultCode == Activity.RESULT_OK ) {
        if(resultData != null) {
            mImageUri = resultData.getData();

            Glide.with(this)
                    .load(mImageUri)
                    .into(productImage);
        }
    }
}

and here is the error i m getting

E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.example.ibrahim_01.notebookapp, PID: 4102
                  java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.ibrahim_01.notebookapp/com.example.ibrahim_01.notebookapp.NoteDetailActivity}: java.lang.NullPointerException: uriString
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
                      at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4077)
                      at android.app.ActivityThread.-wrap15(ActivityThread.java)
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1350)
                      at android.os.Handler.dispatchMessage(Handler.java:102)
                      at android.os.Looper.loop(Looper.java:148)
                      at android.app.ActivityThread.main(ActivityThread.java:5417)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
                   Caused by: java.lang.NullPointerException: uriString
                      at android.net.Uri$StringUri.<init>(Uri.java:475)
                      at android.net.Uri$StringUri.<init>(Uri.java)
                      at android.net.Uri.parse(Uri.java:437)
                      at com.example.ibrahim_01.notebookapp.NoteEditFragment$override.onCreateView(NoteEditFragment.java:66)
                      at com.example.ibrahim_01.notebookapp.NoteEditFragment$override.access$dispatch(NoteEditFragment.java)
                      at com.example.ibrahim_01.notebookapp.NoteEditFragment.onCreateView(NoteEditFragment.java:0)
                      at android.app.Fragment.performCreateView(Fragment.java:2220)
                      at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:973)
                      at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1148)
                      at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1130)
                      at android.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1953)
                      at android.app.FragmentController.dispatchActivityCreated(FragmentController.java:152)
                      at android.app.Activity.performCreateCommon(Activity.java:6232)
                      at android.app.Activity.performCreate(Activity.java:6239)
                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
                      at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4077) 
                      at android.app.ActivityThread.-wrap15(ActivityThread.java) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1350) 
                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                      at android.os.Looper.loop(Looper.java:148) 
                      at android.app.ActivityThread.main(ActivityThread.java:5417) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
2

There are 2 answers

0
ataulm On BEST ANSWER

When you rotate the first time, the field (imageUri) is set. onSaveInstanceState() will persist this field on rotate, in the bundle.

Now in landscape, you'll read from the bundle in onCreate() and get the value you stored. But note that imageUri will be null since you store this to myUri instead.

When you rotate the second time, onSaveInstanceState() will not persist imageUri since it's null. But now in portrait, it'll try to read it (the bundle is not null), return null (because there was no value for the key "imageuri") and you get your null pointer in Uri.parse.

You can solve by removing the field myUri and assigning the value from the bundle in onCreate() to imageUri. I think - I'm reading this on my phone!

0
Serega Gevelev On

override method onCreate and add setRetainInstance(true) like this:

@Override
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setRetainInstance(true);
}