简体   繁体   English

如何在Android中为动态选择的图像创建savedInstanceState?

[英]how to create savedInstanceState for dynamically selected image in Android?

I create a android application.Select image from gallery using a button and retrieve in the ImageView. 我创建了一个Android应用程序。使用按钮从库中选择图像并在ImageView中检索。 The image fetching is successful. 图像提取成功。 Now I want to saved the state of the selected Image.I try to fix.It makes crash application.When I change the Horizontal orientation the app is crashed.Please help me to solve the issue. 现在我想保存所选Image.It尝试修复的状态。它使崩溃应用程序。当我更改水平方向时,应用程序崩溃。请帮我解决问题。

My Code : 我的代码:

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

I have not tested this, so I don't know if it is working. 我没有测试过这个,所以我不知道它是否正常工作。 Hope it is. 希望是的。

But you should be aware of this 但你应该意识到这一点

...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. ...您可能无法通过onSaveInstanceState()回调系统为您保存的Bundle完全恢复您的活动状态 - 它不是为了携带大型对象(如位图)及其中的数据而设计的必须序列化然后反序列化,这会占用大量内存并使配置变化缓慢。 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);
        }
    }

}

Be careful in using Instance State with Bitmaps. 使用带有位图的实例状态时要小心。 As Bojan quoted you should not use the Bundle managed via 'onSaveInstanceState' for images. 正如Bojan所引用的那样,你不应该使用通过'onSaveInstanceState'管理的Bundle来处理图像。

This is the updated quote: 这是更新的报价:

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. 您可能无法使用系统为onSaveInstanceState()回调为您保存的Bundle完全恢复活动状态 - 它不是为承载大型对象(如位图)而设计的,并且其中的数据必须序列化然后反序列化,这会占用大量内存并使配置变化缓慢。 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. 在这种情况下,您可以通过在配置更改时重新启动活动时保留Fragment来减轻重新初始化活动的负担。 This fragment can contain references to stateful objects that you want to retain. 此片段可以包含对要保留的有状态对象的引用。

from the official documentation 来自官方文件

You can find the code I implemented following this hint looking at my answer at this other question 您可以在此提示下找到我实现的代码,在另一个问题上查看我的答案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM