как создать saveInstanceState для динамически выбранного изображения в Android?

Я создаю приложение для Android. Выберите изображение из галереи с помощью кнопки и извлеките его в ImageView. Получение изображения прошло успешно. Теперь я хочу сохранить состояние выбранного изображения. Я пытаюсь исправить это. Это приводит к сбою приложения. Когда я меняю горизонтальную ориентацию, приложение аварийно завершает работу. Пожалуйста, помогите мне решить проблему.

Мой код:

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

person reegan29    schedule 23.04.2015    source источник
comment
stackoverflow.com/questions/11346275/   -  person Bojan Kseneman    schedule 23.04.2015
comment
@BojanKseneman, братан, можешь переписать мой код..   -  person reegan29    schedule 23.04.2015
comment
Я сделал, но не знаю, сработает ли, не проверял   -  person Bojan Kseneman    schedule 23.04.2015
comment
Ваш код работает, братан, спасибо...   -  person reegan29    schedule 23.04.2015
comment
Не по теме: не используйте столбец DATA для получения пути к файлу. Подробнее здесь: commonsware.com/blog/2016/03 /15/how-consume-content-uri.html   -  person Eugen Pechanec    schedule 02.04.2016


Ответы (2)


Я не проверял это, поэтому я не знаю, работает ли это. Надеюсь, что это так.

Но вы должны знать об этом

... возможно, вы не сможете полностью восстановить свое состояние активности с помощью Bundle, который система сохраняет для вас с обратным вызовом onSaveInstanceState() — он не предназначен для переноса больших объектов (таких как растровые изображения) и данных внутри него должны быть сериализованы, а затем десериализованы, что может потреблять много памяти и замедлять изменение конфигурации. В такой ситуации вы можете облегчить бремя повторной инициализации своей деятельности, сохранив объект с состоянием, когда ваша деятельность перезапускается из-за изменения конфигурации.

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

}
person Bojan Kseneman    schedule 23.04.2015
comment
Я рад это слышать. Ваше здоровье - person Bojan Kseneman; 23.04.2015

Будьте осторожны при использовании состояния экземпляра с растровыми изображениями. Как процитировал Боян, вы не должны использовать Bundle, управляемый через onSaveInstanceState для изображений.

Это обновленная цитата:

возможно, вы не сможете полностью восстановить свое состояние активности с помощью Bundle, который система сохраняет для вас с помощью обратного вызова onSaveInstanceState() — он не предназначен для переноса больших объектов (например, растровых изображений), и данные в нем должны быть сериализованы. затем десериализуется, что может потреблять много памяти и замедлять изменение конфигурации. В такой ситуации вы можете облегчить бремя повторной инициализации своей активности, сохранив фрагмент, когда ваша активность перезапускается из-за изменения конфигурации. Этот фрагмент может содержать ссылки на объекты с состоянием, которые вы хотите сохранить.

из официальной документации.

Вы можете найти код, который я реализовал, следуя этой подсказке, глядя на мой ответ в этом другом вопрос

person ilmatte    schedule 02.04.2016