Приложение вылетает после изменения ориентации экрана - PullRequest
4 голосов
/ 03 мая 2011

У меня следующая проблема. После запуска приложение работает нормально - даже после изменения ориентации экрана. Приложение еще не подготовлено для обработки изменения ориентации (например, альтернативный макет и т. Д.), Поэтому отображается только повернутый макет по умолчанию, и все в порядке. Однако, когда я покидаю приложение, нажимая клавишу «Назад», меняю ориентацию и сразу после запуска приложения снова происходит сбой. После сбоя, если я снова запускаю приложение, оно работает хорошо, пока не произойдут ранее описанные обстоятельства, - а затем происходит сбой.

Я подключил устройство к компьютеру и запустил приложение в режиме отладки. После перезапуска выдается исключение еще до вызова onCreate. Вызов аварийного вызова:

Thread [<1> main] (Suspended (exception IllegalArgumentException))  
WindowManagerImpl.removeViewImmediate(View) line: 262   
Window$LocalWindowManager.removeViewImmediate(View) line: 436   
ActivityThread.handleDestroyActivity(IBinder, boolean, int, boolean) line: 4022 
ActivityThread.handleRelaunchActivity(ActivityThread$ActivityRecord, int) line: 4127    
ActivityThread.access$2400(ActivityThread, ActivityThread$ActivityRecord, int) line: 136    
ActivityThread$H.handleMessage(Message) line: 2183  
ActivityThread$H(Handler).dispatchMessage(Message) line: 99 
Looper.loop() line: 143 
ActivityThread.main(String[]) line: 5068    
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]  
Method.invoke(Object, Object...) line: 521  
ZygoteInit$MethodAndArgsCaller.run() line: 858  
ZygoteInit.main(String[]) line: 616 
NativeStart.main(String[]) line: not available [native method]  

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

Я переопределил только метод onCreate Activity. У меня также есть пользовательский класс приложения, который создает экземпляр класса используемого движка:

public class ProCalcApplication extends Application
{
    private Engine engine;

    public ProCalcApplication()
    {
        super();

        engine = new Engine();
    }

    public Engine getEngine()
    {
        return engine;
    }
}

Как решить эту проблему?


Я провел еще несколько испытаний. Я закомментировал весь код, оставив только реализацию по умолчанию метода onCreate (super () + setContentLayout ()). Проблема осталась, поэтому я закомментировал весь макет XML, и приложение, наконец, перестало падать. Я нахожусь в процессе зацепления ошибочной записи, пожалуйста, подождите;)


Я нашел причину, но пока не нашел решения. Неисправный XML-код выглядит следующим образом:

<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">

    <android.gesture.GestureOverlayView android:id="@+id/gestureOverlay" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="3">
        <ViewFlipper android:id="@+id/contextArea" android:layout_width="match_parent" android:layout_height="match_parent">

        </ViewFlipper>          
    </android.gesture.GestureOverlayView>

</LinearLayout> 

Может кто-то попытается доказать или опровергнуть, что этот код не работает в описанных обстоятельствах? Или укажите, где я ошибся;)

Моя среда: HTC Desire Z (2.2.1), API 8 используется. Версия Eclipse: Helios Service Release 2 Идентификатор сборки: 20110218-0911.

Редактировать: сделать его немного короче:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">
        <ViewFlipper android:id="@+id/contextArea" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="3">                       
        </ViewFlipper>
</LinearLayout>

И еще немного информации; API 8 в эмуляторе: два изменения ориентации экрана (Ctrl + F12) и сбой приложения. API 10 в эмуляторе: два изменения ориентации экрана, и экран остается в горизонтальном режиме независимо от ориентации (хотя приложение не аварийно завершает работу).

Что я пропустил?

Ответы [ 2 ]

10 голосов
/ 12 мая 2011

Я узнал, что я пропустил :) Поскольку никто не ответил, я оставлю ответ для всех, кто столкнется с той же проблемой.

Оказывается, описанная проблема является общеизвестной ошибкой библиотек Android: ViewFlipper не может правильно обработать изменение ориентации экрана. Он появился в API 2.1 и продолжается до 3.0, где, как считается, он исправлен. К сожалению, большинство современных смартфонов страдают от этой проблемы, так как обычно они имеют 2,2 или 2,3 на борту.

Решением является либо ручная обработка изменения ориентации экрана (см. Перезапуск активности при ротации Android ), либо реализация изменений вида и анимации вручную, используя FrameLayout, видимость просмотра и классы анимации.

Еще один способ - использовать класс SafeViewFlipper Эрика Бёрка:

/**
 * Works around Android Bug 6191 by catching IllegalArgumentException after
 * detached from the window.
 *
 * @author Eric Burke (eric@squareup.com)
 */
public class SafeViewFlipper extends ViewFlipper {
  public SafeViewFlipper(Context context) {
    super(context);
  }

  public SafeViewFlipper(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  /**
   * Workaround for Android Bug 6191:
   * http://code.google.com/p/android/issues/detail?id=6191
   * <p/>
   * ViewFlipper occasionally throws an IllegalArgumentException after
   * screen rotations.
   */
  @Override protected void onDetachedFromWindow() {
    try {
      super.onDetachedFromWindow();
    } catch (IllegalArgumentException e) {
      Log.d(TAG, "SafeViewFlipper ignoring IllegalArgumentException");

      // Call stopFlipping() in order to kick off updateRunning()
      stopFlipping();
    }
  }
}

Вы можете использовать его при создании макета из кода, а также встраивать его в файл XML-макета (вам необходимо полностью его уточнить, например, ).

См. Также http://code.google.com/p/android/issues/detail?id=6191 для получения дополнительной информации.

0 голосов
/ 24 марта 2012

Это работает для вас

package com.palewar;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;

public class ThreadActivity extends Activity {


    static ProgressDialog dialog;
    private Thread downloadThread;
    final static Handler handler = new Handler() {

        @Override
        public void handleMessage(Message msg) {

            super.handleMessage(msg);

            dialog.dismiss();

        }

    };

    protected void onDestroy() {
        if (dialog != null && dialog.isShowing()) {
            dialog.dismiss();
            dialog = null;
        }
        super.onDestroy();
    }

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        downloadThread = (Thread) getLastNonConfigurationInstance();
        if (downloadThread != null && downloadThread.isAlive()) {
            dialog = ProgressDialog.show(ThreadActivity.this, "",
                    "Signing in...", false);
        }

        dialog = ProgressDialog.show(ThreadActivity.this, "",
                "Signing in ...", false);

        downloadThread = new MyThread();
        downloadThread.start();
        // processThread();
    }

    // Save the thread
    @Override
    public Object onRetainNonConfigurationInstance() {
        return downloadThread;
    }


    static public class MyThread extends Thread {
        @Override
        public void run() {

            try {
                // Simulate a slow network
                try {
                    new Thread().sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                handler.sendEmptyMessage(0);

            } finally {

            }
        }
    }

}
...