如何为 Android 中动态选择的图像创建 savedInstanceState?
how to create savedInstanceState for dynamically selected image in Android?
我使用按钮从画廊创建了一个 android application.Select 图像并在 ImageView 中检索。图片获取成功。
现在我想保存所选的状态 Image.I 尝试 fix.It 导致崩溃 application.When 我更改应用程序的水平方向 crashed.Please 帮助我解决问题。
我的代码:
public class MainActivity extends ActionBarActivity {
ImageView imgBackground;
Button loadImgBtn;
String imgDecodableString;
Drawable drawable;
private static int RESULT_LOAD_IMG = 1;
private static final String IMAGE_DATA = "image_resource";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadImgBtn = (Button)findViewById(R.id.btnSelectImage);
imgBackground = (ImageView)findViewById(R.id.myImg);
loadImgBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/* Create intent to open Image Application like Gallery */
Intent galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
/* start the Intent */
startActivityForResult(galleryIntent,RESULT_LOAD_IMG);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
try {
if (requestCode == RESULT_LOAD_IMG && resultCode == RESULT_OK && null != data) {
/* Get the Image from Data */
Uri selectedImage = data.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };
/* Get the Cursor */
Cursor cursor = getContentResolver().query(selectedImage,filePathColumn,null,null,null);
/* Move the first row */
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
imgDecodableString = cursor.getString(columnIndex);
cursor.close();
/* Rendering the Image */
drawable = new BitmapDrawable(imgDecodableString);
imgBackground.setBackgroundDrawable(drawable);
}
} catch (Exception e) {
message(getBaseContext()," Error : " + e.getMessage(),Toast.LENGTH_SHORT);
}
}
public void message(Context ctx,String msg,int duration) {
Toast.makeText(ctx,msg,duration).show();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(IMAGE_DATA, (android.os.Parcelable) drawable);
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
drawable = (Drawable) savedInstanceState.getParcelable(IMAGE_DATA);
}
}
我没有测试过这个,所以我不知道它是否有效。希望是。
但是你应该知道这一点
...it might not be possible for you to completely restore your
activity state with the Bundle that the system saves for you with the
onSaveInstanceState() callback—it is not designed to carry large
objects (such as bitmaps) and the data within it must be serialized
then deserialized, which can consume a lot of memory and make the
configuration change slow. In such a situation, you can alleviate the
burden of reinitializing your activity by retaining a stateful Object
when your activity is restarted due to a configuration change.
public class MainActivity extends ActionBarActivity {
ImageView imgBackground;
Button loadImgBtn;
String imgDecodableString;
BitmapDrawable drawable;
private static int RESULT_LOAD_IMG = 1;
private static final String IMAGE_DATA = "image_resource";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadImgBtn = (Button)findViewById(R.id.btnSelectImage);
imgBackground = (ImageView)findViewById(R.id.myImg);
loadImgBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/* Create intent to open Image Application like Gallery */
Intent galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
/* start the Intent */
startActivityForResult(galleryIntent,RESULT_LOAD_IMG);
}
});
if(savedInstanceState != null) {
Bitmap tmp = savedInstanceState.getParcelable(IMAGE_DATA);
if(tmp != null) {
drawable = new BitmapDrawable(getResources(), tmp);
imgBackground.setImageDrawable(drawable);
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
try {
if (requestCode == RESULT_LOAD_IMG && resultCode == RESULT_OK && null != data) {
/* Get the Image from Data */
Uri selectedImage = data.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };
/* Get the Cursor */
Cursor cursor = getContentResolver().query(selectedImage,filePathColumn,null,null,null);
/* Move the first row */
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
imgDecodableString = cursor.getString(columnIndex);
cursor.close();
/* Rendering the Image */
drawable = new BitmapDrawable(imgDecodableString);
imgBackground.setBackgroundDrawable(drawable);
}
} catch (Exception e) {
message(getBaseContext()," Error : " + e.getMessage(), Toast.LENGTH_SHORT);
}
}
public void message(Context ctx,String msg,int duration) {
Toast.makeText(ctx,msg,duration).show();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if(drawable != null && drawable.getBitmap() != null) {
outState.putParcelable(IMAGE_DATA, drawable.getBitmap());
}
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
}
}
对位图使用实例状态时要小心。正如 Bojan 所引用的那样,您不应该使用通过 'onSaveInstanceState' 管理的 Bundle 来处理图像。
这是更新后的报价:
it might not be possible for you to completely restore your activity state with the Bundle that the system saves for you with the onSaveInstanceState() callback—it is not designed to carry large objects (such as bitmaps) and the data within it must be serialized then deserialized, which can consume a lot of memory and make the configuration change slow. In such a situation, you can alleviate the burden of reinitializing your activity by retaining a Fragment when your activity is restarted due to a configuration change. This fragment can contain references to stateful objects that you want to retain.
你可以找到我按照这个提示实现的代码,看看我在另一个 question
上的回答
我使用按钮从画廊创建了一个 android application.Select 图像并在 ImageView 中检索。图片获取成功。 现在我想保存所选的状态 Image.I 尝试 fix.It 导致崩溃 application.When 我更改应用程序的水平方向 crashed.Please 帮助我解决问题。
我的代码:
public class MainActivity extends ActionBarActivity {
ImageView imgBackground;
Button loadImgBtn;
String imgDecodableString;
Drawable drawable;
private static int RESULT_LOAD_IMG = 1;
private static final String IMAGE_DATA = "image_resource";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadImgBtn = (Button)findViewById(R.id.btnSelectImage);
imgBackground = (ImageView)findViewById(R.id.myImg);
loadImgBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/* Create intent to open Image Application like Gallery */
Intent galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
/* start the Intent */
startActivityForResult(galleryIntent,RESULT_LOAD_IMG);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
try {
if (requestCode == RESULT_LOAD_IMG && resultCode == RESULT_OK && null != data) {
/* Get the Image from Data */
Uri selectedImage = data.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };
/* Get the Cursor */
Cursor cursor = getContentResolver().query(selectedImage,filePathColumn,null,null,null);
/* Move the first row */
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
imgDecodableString = cursor.getString(columnIndex);
cursor.close();
/* Rendering the Image */
drawable = new BitmapDrawable(imgDecodableString);
imgBackground.setBackgroundDrawable(drawable);
}
} catch (Exception e) {
message(getBaseContext()," Error : " + e.getMessage(),Toast.LENGTH_SHORT);
}
}
public void message(Context ctx,String msg,int duration) {
Toast.makeText(ctx,msg,duration).show();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(IMAGE_DATA, (android.os.Parcelable) drawable);
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
drawable = (Drawable) savedInstanceState.getParcelable(IMAGE_DATA);
}
}
我没有测试过这个,所以我不知道它是否有效。希望是。
但是你应该知道这一点
...it might not be possible for you to completely restore your activity state with the Bundle that the system saves for you with the onSaveInstanceState() callback—it is not designed to carry large objects (such as bitmaps) and the data within it must be serialized then deserialized, which can consume a lot of memory and make the configuration change slow. In such a situation, you can alleviate the burden of reinitializing your activity by retaining a stateful Object when your activity is restarted due to a configuration change.
public class MainActivity extends ActionBarActivity {
ImageView imgBackground;
Button loadImgBtn;
String imgDecodableString;
BitmapDrawable drawable;
private static int RESULT_LOAD_IMG = 1;
private static final String IMAGE_DATA = "image_resource";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadImgBtn = (Button)findViewById(R.id.btnSelectImage);
imgBackground = (ImageView)findViewById(R.id.myImg);
loadImgBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/* Create intent to open Image Application like Gallery */
Intent galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
/* start the Intent */
startActivityForResult(galleryIntent,RESULT_LOAD_IMG);
}
});
if(savedInstanceState != null) {
Bitmap tmp = savedInstanceState.getParcelable(IMAGE_DATA);
if(tmp != null) {
drawable = new BitmapDrawable(getResources(), tmp);
imgBackground.setImageDrawable(drawable);
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
try {
if (requestCode == RESULT_LOAD_IMG && resultCode == RESULT_OK && null != data) {
/* Get the Image from Data */
Uri selectedImage = data.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };
/* Get the Cursor */
Cursor cursor = getContentResolver().query(selectedImage,filePathColumn,null,null,null);
/* Move the first row */
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
imgDecodableString = cursor.getString(columnIndex);
cursor.close();
/* Rendering the Image */
drawable = new BitmapDrawable(imgDecodableString);
imgBackground.setBackgroundDrawable(drawable);
}
} catch (Exception e) {
message(getBaseContext()," Error : " + e.getMessage(), Toast.LENGTH_SHORT);
}
}
public void message(Context ctx,String msg,int duration) {
Toast.makeText(ctx,msg,duration).show();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if(drawable != null && drawable.getBitmap() != null) {
outState.putParcelable(IMAGE_DATA, drawable.getBitmap());
}
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
}
}
对位图使用实例状态时要小心。正如 Bojan 所引用的那样,您不应该使用通过 'onSaveInstanceState' 管理的 Bundle 来处理图像。
这是更新后的报价:
it might not be possible for you to completely restore your activity state with the Bundle that the system saves for you with the onSaveInstanceState() callback—it is not designed to carry large objects (such as bitmaps) and the data within it must be serialized then deserialized, which can consume a lot of memory and make the configuration change slow. In such a situation, you can alleviate the burden of reinitializing your activity by retaining a Fragment when your activity is restarted due to a configuration change. This fragment can contain references to stateful objects that you want to retain.
你可以找到我按照这个提示实现的代码,看看我在另一个 question
上的回答