Image on ImageView lost after Activity is destroye

2019-01-27 03:56发布

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"));
    }

3条回答
叛逆
2楼-- · 2019-01-27 04:21

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);
}
查看更多
仙女界的扛把子
3楼-- · 2019-01-27 04:30

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).

查看更多
手持菜刀,她持情操
4楼-- · 2019-01-27 04:32

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.

查看更多
登录 后发表回答