Image on ImageView lost after Activity is destroyed
Asked Answered
T

4

2

I am trying to make an app where I can let a user select a picture to display on their profile. I am able to browse and set their selected image on imageview. But the image is lost once the the activity is destroyed. I tried to implement onSaveInstanceState but still it's the same. I'm wondering if I am using it correctly. I hope you can help a newbie like me. Thanks in advance. Here's the code that I'm using:

public class AccountFragment extends Fragment implements OnClickListener {
private LoginDataBaseAdapter loginDataBaseAdapter;
Bitmap image;
Bitmap bitmap;
String picture_location;
TextView textTargetUri;
ImageView targetImage;

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


        View rootView = inflater.inflate(R.layout.fragment_account, container, false);


            textTargetUri = (TextView) rootView.findViewById(R.id.targeturi);

            targetImage=(ImageView) rootView.findViewById(R.id.profpic);

            targetImage.setOnClickListener(new ImageView.OnClickListener(){
            @Override
            public void onClick(View arg0) {
                Intent   intent = new Intent(Intent.ACTION_PICK,
                android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                startActivityForResult(intent, 0);
            }});

            if (savedInstanceState != null) {
                //if there is a bundle, use the saved image resource (if one is there)
                image = savedInstanceState.getParcelable("BitmapImage");
                targetImage.setImageBitmap(image);
                textTargetUri.setText(savedInstanceState.getString("path_to_picture"));
            } 



        return rootView;



    }

    @Override 
    public void onSaveInstanceState(Bundle savedInstanceState){
        super.onSaveInstanceState(savedInstanceState);
        savedInstanceState.putParcelable("BitmapImage", bitmap);
        savedInstanceState.putString("path_to_picture", picture_location);
    }


    @Override
    public void onActivityResult( int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (resultCode == Activity.RESULT_OK){
            Uri targetUri = data.getData();
            picture_location = targetUri.toString();
            textTargetUri.setText(targetUri.toString());
            Bitmap bitmap;
            try {
                bitmap = BitmapFactory.decodeStream(getActivity().getContentResolver().openInputStream(targetUri));
                targetImage.setImageBitmap(bitmap);
            } 
            catch (FileNotFoundException e){
                e.printStackTrace();
            }
        }   
    }

    @Override
    public void onClick(View arg0) {
        // TODO Auto-generated method stub

    }}

By the way, you may have noticed that instead of using the onRestoreInstanceState after oncreate, I tried to use the different approach. I found an answer from another question that you can also implement it inside the oncreate. I used it since whenever I declare the function onRestoreInstanceState I am being asked to remove the @Override annotation.

@Override 
protected void onRestoreInstanceState(Bundle savedInstanceState){       
            image = savedInstanceState.getParcelable("BitmapImage");
            targetImage.setImageBitmap(image);
            textTargetUri.setText(savedInstanceState.getString("path_to_picture"));
    }
Tabithatablature answered 29/8, 2014 at 14:22 Comment(2)
Do u want to save the image once user goes back?Bohi
If you want to keep the image even once the user leaves the app then you should save the file path in SharedPrefs or DB.Boomer
P
1

Using onSaveInstanceState and onCreate/onRestoreInstanceState is for short term activity state preservation - but not to be used for persistent storage of the application's data.

You can read about onSaveInstanceState here

You can read about persistent storage here

codeMagic suggested using SharedPrefs (see persistent storage link) for your long-term persistent storage. If you wanted to do this, I would suggest saving the image URI (the link has a good example of how to do so) in you onActivityResult method, and then call a method to read the SharedPref and load the image that you can call from onCreate as well as from onActivityResult.

You may also want to store your own copy of the image/bitmap in your application's own internal storage (see persistent storage link).

Paxwax answered 29/8, 2014 at 15:2 Comment(0)
M
1

if you are not finishing the activity, you can use onSavedInstance() to store the picture_location value and bind it back either in onCreate(SavedInst)/onRestore() from the picture_location value.

Maes answered 29/8, 2014 at 14:49 Comment(0)
P
1

Using onSaveInstanceState and onCreate/onRestoreInstanceState is for short term activity state preservation - but not to be used for persistent storage of the application's data.

You can read about onSaveInstanceState here

You can read about persistent storage here

codeMagic suggested using SharedPrefs (see persistent storage link) for your long-term persistent storage. If you wanted to do this, I would suggest saving the image URI (the link has a good example of how to do so) in you onActivityResult method, and then call a method to read the SharedPref and load the image that you can call from onCreate as well as from onActivityResult.

You may also want to store your own copy of the image/bitmap in your application's own internal storage (see persistent storage link).

Paxwax answered 29/8, 2014 at 15:2 Comment(0)
C
0

In case of Bitmaps Instance State is not the suggested way to persist info about the selected image.

You can find the explanation here: Handling configuration Changes

I blogged extensively about it here: Retain selected Image during Screen Rotation

Below I paste my implementation of the illustrated solution:

1 - Create a Fragment and configure it to be retained in memory

import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v4.app.Fragment;

public class ImageRetainingFragment extends Fragment {
    private Bitmap selectedImage;

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

public void setImage(Bitmap selectedImage) {
    this.selectedImage = selectedImage;
}

public Bitmap getImage() {
    return this.selectedImage;
}
}

2 - Use it in your Activity

private static final String FRAGMENT_NAME = "imageFragment";


protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ....

    initializeImageRetainingFragment();
    tryLoadImage();
}


private void initializeImageRetainingFragment() {
    // find the retained fragment on activity restarts    
    FragmentManager fragmentManager = getSupportFragmentManager();
    this.imageRetainingFragment = (ImageRetainingFragment)  fragmentManager.findFragmentByTag(FRAGMENT_NAME);
    // create the fragment and bitmap the first time   
    if (this.imageRetainingFragment == null) {
         this.imageRetainingFragment = new ImageRetainingFragment();
         fragmentManager.beginTransaction()
         // Add a fragment to the activity state. 
         .add(this.imageRetainingFragment, FRAGMENT_NAME)
         .commit();
   }
}
private void tryLoadImage() {
   if (this.imageRetainingFragment == null) {
       return;
   }

   Bitmap selectedImage = this.imageRetainingFragment.getImage();
      if (selectedImage == null) {
        return;
      }

      ImageView selectedImageView = (ImageView)findViewById(R.id.selectedImage);
      selectedImageView.setImageBitmap(selectedImage);
}
Cowhide answered 1/4, 2016 at 16:1 Comment(1)
Hello! Do you know how to save bitmap to storage before retained fragment will be destroyed by operating system?Shenika
E
0

1)// manifest.xml

2)//public class MainActivity extends AppCompatActivity implements LocationListener{...

SharedPreferences.Editor editor;

3)//protected void onCreate(Bundle savedInstanceState){ ...

    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) !=
            PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 3);
    }

4)//SHARED PREFERENCES SharedPreferences pref = getApplicationContext().getSharedPreferences("MyPref", getApplicationContext().MODE_PRIVATE); editor = pref.edit();

5)//SET IMAGE PATH if (pref.getString("mydraw", null) != null) {

        img6.setImageURI(Uri.parse(pref.getString("mydraw", null)));

    } else {
        //set default image
        img6.setImageResource(R.drawable.poseidon);
    }

6)//protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {...

if (requestCode == 100) { if (resultCode == RESULT_OK) {

            img6.setImageURI(data.getData());

            //save URI as string
            editor.putString("mydraw", data.getData().toString());
            editor.commit(); // commit changes

        }
    }
Eterne answered 15/2, 2021 at 14:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.