Не хватает памяти, отображается AlertDialog и вносятся изменения в ориентацию

#android #out-of-memory #android-alertdialog #screen-orientation

#Android #не хватает памяти #android-alertdialog #ориентация экрана

Вопрос:

У меня есть действие, содержащее две кнопки imagebuttons. Если пользователь нажимает назад, отображается AlertDialog. Во время отображения предупреждения, если ориентация несколько раз меняется взад и вперед, приложение завершает работу с этим сообщением:

 ERROR/dalvikvm-heap(10988): 3363556-byte external allocation too large for this process.
ERROR/dalvikvm(10988): Out of memory: Heap Size=4935KB, Allocated=2594KB, Bitmap Size=19579KB ERROR/GraphicsJNI(10988): VM won't let us allocate 3363556 bytes
  

Если AlertDialog отсутствует, приложение не завершает работу.

 public class StartPageView extends Activity implements OnClickListener, android.content.DialogInterface.OnClickListener
{
    private static final String TAG = "StartPageView";
    private ImageButton vacButton;
    private ImageButton sickButton;
    private AlertDialog alert;
    private static boolean alertDismissedByLifeCycle = false;


@Override
public void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.startpage);

    vacButton = (ImageButton)findViewById(R.id.gotovac_btn);
    vacButton.setOnClickListener(this);

    sickButton = (ImageButton)findViewById(R.id.gotosick_btn);
    sickButton.setOnClickListener(this); 

    if(alertDismissedByLifeCycle)
    {
        alertDismissedByLifeCycle = false;
        showAlert();
    }
}

@Override
protected void onStop() 
{
    if(alert != null amp;amp; alert.isShowing())
    {
        alertDismissedByLifeCycle = true;
        alert.dismiss();
    }
    super.onStop();
}

//GO TO VACATION VIEW OR SICK VIEW

//user clicked on vacView button or sickView button
@Override
public void onClick(View v) 
{
    if(v.equals(this.vacButton))
    {
         Intent i = new Intent(this, VacationLeaveView.class);
         startActivity(i);
    }
    if(v.equals(this.sickButton))
    {
         Intent i = new Intent(this, SickLeaveView.class);
         startActivity(i);

    }

}


//LOG OUT

//user pressed the back button
@Override
public void onBackPressed() 
{
    showAlert();
}
//OnClickListener for logging out warning
@Override
public void onClick(DialogInterface dialog, int which) 
{
    if(which == DialogInterface.BUTTON_POSITIVE)
    {
        MainController.getInstance().clearAllChildren();
        dialog.cancel();
        this.finish();
    }
    else
        dialog.cancel();
}

//DIALOG

private void showAlert()
{
    if(alert == null)
    {
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);

        alertDialog.setMessage("Vill du logga ut från förskoleportalen?");
        alertDialog.setPositiveButton("Ja", this);
        alertDialog.setNegativeButton("Nej", this);

        alert = alertDialog.create();

        // Title for AlertDialog
        alert.setTitle("Logga ut");
    }

    alert.show();
}
  

Комментарии:

1. Такое поведение указывает на утечку памяти. Вы что-то пропускаете, довольно сильно.

Ответ №1:

Это ясно указывает вам, что вы используете растровое изображение очень большого размера, вам просто нужно преобразовать его, чтобы оно весило меньше.

Комментарии:

1. Если AlertDialog не отображается, приложение не завершает работу. Неправильно ли мне думать, что размер изображений не является проблемой?

2. Размер ваших изображений не будет проблемой, если вы исправите утечку памяти или добавите их в свое приложение по-другому, как описано в документации Android. Смотрите ссылку в моем ответе. В нем конкретно говорится о вашей проблеме.

Ответ №2:

Ваш контекст «этого» почти наверняка является причиной. Вам необходимо явно указать контекст, чтобы избежать этой проблемы. Здесь обсуждается сама ваша проблема: предотвращение утечек памяти

Проблема в этом… когда вы добавляете свои изображения внутри activity к чему-либо с контекстом «это», а затем меняете ориентацию, изображение передается вместе со всем остальным, что является «этим», в метод onCreate() как часть пакета. Делайте это снова и снова, и в итоге вы получите 1 изображение за изменение ориентации в памяти. В документации Android это описано дословно.

Комментарии:

1. Это обсуждается в ссылке документации, приведенной в ответе, и я не могу сказать это лучше, чем они там делают.

2. Спасибо, вы даете очень хорошее объяснение проблемы. Я решил свою проблему, добавив эти две строки кода в свой метод onStop. sickButton.setImageBitmap(null); vacButton.setImageBitmap(null);