问题
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"));
}
回答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).
回答2:
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.
回答3:
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);
}
来源:https://stackoverflow.com/questions/25570293/image-on-imageview-lost-after-activity-is-destroyed