Android: ваша активность запущена? Диалоговое окно не может отображаться после завершения

У меня есть представление под названием SpotOnView, и оно распространяется на Game_shooting_AB. Кодирование следующим образом.

Фон:

В SpotOnView есть таймер обратного отсчета. Когда время истекло, игра окончена, и появится диалоговое окно с вопросом, хочет ли пользователь выйти или сыграть снова.

Код SpotOnView:

public class SpotOnView extends View 
{
   ......
  // constructs a new SpotOnView
   public SpotOnView(Context context, RelativeLayout parentLayout)
   {
      super(context);          
      resources = context.getResources();            
      layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
      ....    

   } 


   public void start_timer() 
   {
        if (!timerHasStarted) 
        {
            countDownTimer.start();
            timerHasStarted = true;
        } 
        else 
        {
            countDownTimer.cancel();
            timerHasStarted = false;
        }
   }

    public class MyCountDownTimer extends CountDownTimer 
    {
        public MyCountDownTimer(long startTime, long interval) 
        {
            super(startTime, interval);
        }

        @Override
        public void onFinish() 
        {
            text.setText("Time's up!");
               ((Game_shooting_AB)getContext()).replay_dialog();  //LINE 181
        }

        @Override
        public void onTick(long millisUntilFinished) 
        {
            ....
        }
    }

Game_shooting_AB Код:

   public void onCreate(Bundle savedInstanceState) 
   {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.game_shooting);

      // create a new SpotOnView and add it to the RelativeLayout
      RelativeLayout layout = (RelativeLayout) findViewById(R.id.relativeLayout);
      view = new SpotOnView(this, layout);                                          //EXTENDING HERE
      layout.addView(view, 0); // add view to the layout
    ....
}



public void replay_dialog()    
{
    final Dialog dialog1 = new Dialog(Game_shooting_AB.this, android.R.style.Theme_Translucent_NoTitleBar);
    WindowManager.LayoutParams lp = dialog1.getWindow().getAttributes();
    lp.dimAmount = 0.7f;
    dialog1.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);

    Window window = dialog1.getWindow();
    window.setGravity(Gravity.CENTER);

    dialog1.setContentView(R.layout.alert_dialog_replay_shooting);
    dialog1.setCancelable(false);
    dialog1.show();     //LINE 431
    ....

Логкат:

Необходимые номера строк добавлены в качестве комментариев в приведенных выше кодах.

11-22 00:16:34.365: W/dalvikvm(1105): threadid=1: thread exiting with uncaught exception (group=0x41f342a0)
11-22 00:16:34.370: E/AndroidRuntime(1105): FATAL EXCEPTION: main
11-22 00:16:34.370: E/AndroidRuntime(1105): android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@43304558 is not valid; is your activity running?
11-22 00:16:34.370: E/AndroidRuntime(1105):     at android.view.ViewRootImpl.setView(ViewRootImpl.java:708)
11-22 00:16:34.370: E/AndroidRuntime(1105):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:346)
11-22 00:16:34.370: E/AndroidRuntime(1105):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:224)
11-22 00:16:34.370: E/AndroidRuntime(1105):     at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:149)
11-22 00:16:34.370: E/AndroidRuntime(1105):     at android.view.Window$LocalWindowManager.addView(Window.java:554)
11-22 00:16:34.370: E/AndroidRuntime(1105):     at android.app.Dialog.show(Dialog.java:277)
11-22 00:16:34.370: E/AndroidRuntime(1105):     at com.app.abc.Game_shooting_AB.replay_dialog(Game_shooting_AB.java:431)
11-22 00:16:34.370: E/AndroidRuntime(1105):     at com.app.abc.SpotOnView$MyCountDownTimer.onFinish(SpotOnView.java:181)
11-22 00:16:34.370: E/AndroidRuntime(1105):     at android.os.CountDownTimer$1.handleMessage(CountDownTimer.java:118)
11-22 00:16:34.370: E/AndroidRuntime(1105):     at android.os.Handler.dispatchMessage(Handler.java:99)
11-22 00:16:34.370: E/AndroidRuntime(1105):     at android.os.Looper.loop(Looper.java:137)
11-22 00:16:34.370: E/AndroidRuntime(1105):     at android.app.ActivityThread.main(ActivityThread.java:4898)
11-22 00:16:34.370: E/AndroidRuntime(1105):     at java.lang.reflect.Method.invokeNative(Native Method)
11-22 00:16:34.370: E/AndroidRuntime(1105):     at java.lang.reflect.Method.invoke(Method.java:511)
11-22 00:16:34.370: E/AndroidRuntime(1105):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1008)
11-22 00:16:34.370: E/AndroidRuntime(1105):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:775)
11-22 00:16:34.370: E/AndroidRuntime(1105):     at dalvik.system.NativeStart.main(Native Method)

Вопрос:

Logcat показывает, работает ли ваша активность?

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

  2. Можно ли закодировать и показать диалог в SpotOnView вместо того, чтобы писать в коде Game_shooting_AB?

  3. Я попытался изменить код, переместив класс MyCountDownTimer и метод replay_dialog обратно в Game_shooting_AB, но все равно появляется та же ошибка. Я хотел бы спросить, приведет ли OnFinish MyCountDownTimer к завершению действия, так что диалоговое окно не сможет найти базу для отображения?

Спасибо большое!!


person pearmak    schedule 21.11.2013    source источник


Ответы (2)


Проблема началась с "((Game_shooting_AB)getContext()).replay_dialog();" эта строка кода.

Как вы найдете в документации по Android, когда вы вызываете getContext() изнутри представления, вы получаете «Контекст представления». Теперь то, что вы делаете, — это приведение этого контекста к Game_shooting_AB, что не очень хорошо, поскольку это может быть или не быть контекстом действия. Ознакомьтесь с ответом Romain Guy по этому поводу. Таким образом, Android говорит вам: «Ваша активность запущена?».

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

Настройте свой код следующим образом:

public class SpotOnView extends View 
{
  Game_shooting_AB mGame_shooting_AB;
  public void setGame_shooting_AB(Game_shooting_AB mGame_shooting_AB){
   this.mGame_shooting_AB = mGame_shooting_AB;
  }
   ......
   // constructs a new SpotOnView
  public SpotOnView(Context context, RelativeLayout parentLayout)
  {
   super(context);          
   resources = context.getResources();            
    layoutInflater = (LayoutInflater)          context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  ....    

  } 


  public void start_timer() 
  {
    if (!timerHasStarted) 
    {
        countDownTimer.start();
        timerHasStarted = true;
    } 
    else 
    {
        countDownTimer.cancel();
        timerHasStarted = false;
    }
  }

public class MyCountDownTimer extends CountDownTimer 
{
    public MyCountDownTimer(long startTime, long interval) 
    {
        super(startTime, interval);
    }

    @Override
    public void onFinish() 
    {
        text.setText("Time's up!");
           mGame_shooting_AB.replay_dialog();  //LINE 181
    }

    @Override
    public void onTick(long millisUntilFinished) 
    {
        ....
    }
}

После того, как вы получите экземпляр SpotOnView, установите действие:

      view = new SpotOnView(this, layout);                                          //EXTENDING HERE
  layout.addView(view, 0); // add view to the layout
  view.setGame_shooting_AB(Game_shooting_AB.this);

Надеюсь это поможет.

person saiful103a    schedule 21.11.2013
comment
Спасибо за ваш быстрый ответ! Я хотел бы спросить, куда звонить для setGame_shooting_AB? Теперь он показывает java.lang.NullPointerException - person pearmak; 21.11.2013
comment
Вы должны добавить метод setGame_shooting_AB в свой класс SpotOnView. После получения экземпляра SpotOnView вызовите этот метод, передав действие в качестве параметра. - person saiful103a; 21.11.2013
comment
ужасно жаль, что я все еще застрял ... не могли бы вы более подробно расшифровать приведенную выше кодировку? =( Я продолжаю получать NPE везде... - person pearmak; 21.11.2013
comment
Как вы добавили свой SpotOnView в пользовательский интерфейс? Используя макет, или вы добавили View после выполнения new SpotView( .... ? - person saiful103a; 21.11.2013
comment
действительно спасибо за вашу активную поддержку! Я добавил коды в приведенную выше область кода Game_shooting_AB.. создав новый SpotOnView и добавив его в RelativeLayout. - person pearmak; 21.11.2013
comment
сделал правку для вашего удобства, проверьте, работает ли она. хотя должен :) - person saiful103a; 21.11.2013
comment
мой исходный код ранее с вероятностью 50% может работать, а 50% - с ошибкой. теперь реализую ваш, я пробовал около 10 раз без ошибок! большое спасибо! я продолжу тестирование и могу ли я связаться с вами, когда у него возникнут проблемы =) =) - person pearmak; 21.11.2013
comment
Возможно, я ошибался в том, что это определенно не контекстная часть Activity. Отредактировал мой ответ и сослался на одну полезную ссылку для лучшего понимания, чтобы позже другие не поняли неправильно. Спасибо - person saiful103a; 21.11.2013
comment
Привет, я обнаружил, что проблема все еще возникает после тестирования около 20 раз ...! точно с такой же ошибкой... - person pearmak; 22.11.2013
comment
какое исключение вы получаете? - person saiful103a; 22.11.2013
comment
Я собирался предложить другое решение, но это немного длинное объяснение. я думаю, будет лучше, если мы перенесем нашу дискуссию в чат? - person saiful103a; 22.11.2013
comment
давайте продолжим это обсуждение в чате - person saiful103a; 22.11.2013
comment
спасибо за последнее предложение добавить countDownTimer.cancel();countDownTimer = null; при вызове намерения закончить действие. Теперь он работает идеально! - person pearmak; 22.11.2013

Вам нужно использовать setResult в Intent при завершении активность. Затем этот результат необходимо обработать в родительском действии в onActivityResult, а затем отобразится диалоговое окно.

person PravinCG    schedule 21.11.2013
comment
Я изменил код сейчас и переместил класс MyCountDownTimer и метод replay_dialog обратно в Game_shooting_AB, но та же ошибка все равно появляется. Я хотел бы спросить, приведет ли OnFinish MyCountDownTimer к завершению действия, чтобы диалоговое окно не смогло найти базу для отображения? - person pearmak; 21.11.2013