Android GroupActivity Backpress-триггер Fatal Exception / NullPointerException

У меня есть некоторые проблемы на BackPressed при использовании ActivityGroup под TabHost, Чтобы проиллюстрировать, прежде всего, коды развертываются в слоях следующим образом:

Класс TabGroupActivity

Следующие TabGroupActivity.java ссылка из онлайн-учебника.

public class TabGroupActivity extends ActivityGroup 
{    
    private ArrayList<String> mIdList;

    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);       
        if (mIdList == null) mIdList = new ArrayList<String>();
    }

    /**
     * This is called when a child activity of this one calls its finish method. 
     * This implementation calls {@link LocalActivityManager#destroyActivity} on the child activity
     * and starts the previous activity.
     * If the last child activity just called finish(),this activity (the parent),
     * calls finish to finish the entire group.
     */
  @Override
  public void finishFromChild(Activity child) 
  {
      LocalActivityManager manager = getLocalActivityManager();
      int index = mIdList.size()-1;

      if (index < 1) 
      {
          finish();
          return;
      }

      manager.destroyActivity(mIdList.get(index), true);
      mIdList.remove(index); index--;
      String lastId = mIdList.get(index);
      Activity a = manager.getActivity(lastId); 
      Intent lastIntent = a.getIntent();      // LINE 49
      Window newWindow = manager.startActivity(lastId, lastIntent);
      setContentView(newWindow.getDecorView());
  }

  /**
   * Starts an Activity as a child Activity to this.
   * @param Id Unique identifier of the activity to be started.
   * @param intent The Intent describing the activity to be started.
   * @throws android.content.ActivityNotFoundException.
   */
  public void startChildActivity(String Id, Intent intent) 
  {     
      Window window = getLocalActivityManager().startActivity(Id,intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
      if (window != null) 
      {
          mIdList.add(Id);
          setContentView(window.getDecorView()); 
      }    
  }

  /**
   * The primary purpose is to prevent systems before android.os.Build.VERSION_CODES.ECLAIR
   * from calling their default KeyEvent.KEYCODE_BACK during onKeyDown.
   */
  @Override
  public boolean onKeyDown(int keyCode, KeyEvent event) 
  {
      if (keyCode == KeyEvent.KEYCODE_BACK) 
      {
          //preventing default implementation previous to android.os.Build.VERSION_CODES.ECLAIR
          return true;
      }
      return super.onKeyDown(keyCode, event);
  }

  /**
   * Overrides the default implementation for KeyEvent.KEYCODE_BACK 
   * so that all systems call onBackPressed().
   */
  @Override
  public boolean onKeyUp(int keyCode, KeyEvent event) 
  {
      if (keyCode == KeyEvent.KEYCODE_BACK) 
      {
          onBackPressed(); //LINE 88
          return true;
      }
      return super.onKeyUp(keyCode, event);
  }

  /**
   * If a Child Activity handles KeyEvent.KEYCODE_BACK.
   * Simply override and add this method.
   */
  @Override
  public void  onBackPressed  () 
  {
      int length = mIdList.size();
      if ( length > 1) 
      {
          Activity current = getLocalActivityManager().getActivity(mIdList.get(length-1));
          current.finish(); //LINE 103
      }  
  }
}

Tools_GroupActivity class

public class Tools_GroupActivity extends TabGroupActivity
{
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        startChildActivity("Tools_index", new Intent(this, Tools_index.class));
    }
}

Tools_index.class

Это страница с 9 кнопками, например, при нажатии кнопки 1 она вызовет Tools_1_diamond claass:

public void tools_button1_click (View view) 
{
    Intent edit = new Intent(getParent(), Tools_1_Diamond.class);
    TabGroupActivity parentActivity = (TabGroupActivity)getParent();
    parentActivity.startChildActivity("Tools_1_Diamond", edit);   
} 

внутри Tools_1_diamond учебный класс

Макет имеет кнопку, которая может вернуться к Tools_index страница, следующим образом:

public void button_tools_subpage_back_click (View view)   
{  
    Intent edit = new Intent(getParent(), Tools_index.class);
    TabGroupActivity parentActivity = (TabGroupActivity)getParent();
    parentActivity.startChildActivity("Tools_index", edit); 
}   

@Override  
public void onBackPressed()   
{  
    Intent edit = new Intent(getParent(), Tools_index.class);
    TabGroupActivity parentActivity = (TabGroupActivity)getParent();
    parentActivity.startChildActivity("Tools_index", edit); 
}   

Проблема воспроизведена:

Случай A:1. При нажатии на кнопку Tools_1_Diamond класс (вместо нажатой) приложение может правильно вернуться к Tools_index стр.

  1. Затем внутри Tools_index страницы, если пользователь в это время нажал кнопку BackPressed, приложение вернется к Tools_1_Diamond страница,

  2. а затем нажмите кнопку BackPress, ошибка FATAL EXCEPTION: main java.lang.NullPointerException произойдет.

Случай Б: Когда все время просто с помощью BackPress, не касаясь спроектированной кнопкой назад, все идет гладко.

Вопрос / Намерение:

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

Как это можно решить? Я хотел бы предложить пользователю, что при нажатии либо кнопки собственного дизайна назад, либо метода BackPress вернется к Tools_index страницы, и дальнейшее нажатие BackPress в Tools_index страница не предложит никакой реакции, или даже лучше, всплывающее окно alertDialog спрашивая пользователя, хотите ли вы выйти из приложения.

Logcat:

06-19 22:40:03.570: D/webviewglue(23395): nativeDestroy view: 0x51909960
06-19 22:40:06.585: D/AndroidRuntime(23395): Shutting down VM
06-19 22:40:06.585: W/dalvikvm(23395): threadid=1: thread exiting with uncaught exception (group=0x40fe72a0)
06-19 22:40:06.670: E/AndroidRuntime(23395): FATAL EXCEPTION: main
06-19 22:40:06.670: E/AndroidRuntime(23395): java.lang.NullPointerException
06-19 22:40:06.670: E/AndroidRuntime(23395):    at com.abc.abc_v1.TabGroupActivity.finishFromChild(TabGroupActivity.java:49)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at android.app.Activity.finish(Activity.java:4215)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at com.abc.abc_v1.TabGroupActivity.onBackPressed(TabGroupActivity.java:103)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at com.abc.abc_v1.TabGroupActivity.onKeyUp(TabGroupActivity.java:88)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at android.view.KeyEvent.dispatch(KeyEvent.java:2729)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at android.app.Activity.dispatchKeyEvent(Activity.java:2431)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2033)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1363)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1363)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1363)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at android.widget.TabHost.dispatchKeyEvent(TabHost.java:309)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1363)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1363)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1363)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:2106)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1466)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at android.app.Activity.dispatchKeyEvent(Activity.java:2426)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2033)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at android.view.ViewRootImpl.deliverKeyEventPostIme(ViewRootImpl.java:3852)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at android.view.ViewRootImpl.handleImeFinishedEvent(ViewRootImpl.java:3800)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:2935)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at android.os.Handler.dispatchMessage(Handler.java:99)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at android.os.Looper.loop(Looper.java:137)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at android.app.ActivityThread.main(ActivityThread.java:4921)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at java.lang.reflect.Method.invokeNative(Native Method)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at java.lang.reflect.Method.invoke(Method.java:511)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
06-19 22:40:06.670: E/AndroidRuntime(23395):    at dalvik.system.NativeStart.main(Native Method)

1 ответ

Решение

Первый

Проблема может быть в том, что в TabGroupActivityпосле того, как вы сделали:

mIdList.remove(index);

Вы не проверяете, что индекс все еще действителен, то есть больше или равен единице. Следующий код, вероятно, должен быть:

if (index > 0) {
     index--;
     String lastId = mIdList.get(index);
     Intent lastIntent = manager.getActivity(lastId).getIntent(); //LINE49
     Window newWindow = manager.startActivity(lastId, lastIntent);
     setContentView(newWindow.getDecorView());
}
else {
    // Handle case where there are no children left.
}

второй

Стоит отметить, что LocalActivityManager было объявлено устаревшим на уровне API 13, и поэтому, если вы не ориентируетесь только на устройства до 13, его не следует использовать.

Даже если вы решите продолжить его использование, есть некоторые условия, при которых он на самом деле не начнет новую Activity, Смотрите здесь.

Другие вопросы по тегам