MyTracks 読み (13)

カスタムな Dialog 云々を先んじて掘削しておく事に。
サンプルとしては SendToGoogleDialog なソレをチョイス。エントリポイントは sendToGoogle メソドにします。以下に一部を引用。

  public void sendToGoogle() {
    if (sendToGoogleDialog == null) {
      return;
    }
    setProgressValue(0);
    setProgressMessage("");
    showDialogSafely(DIALOG_PROGRESS);

showDialogSafely って何だったか。てーかこのあたり掘ったようなそうでもないような気がして、今更エントリを確認してみたら、正にココで力尽きていた模様。丁度良い。
で、ええと showDialogSafely メソドの定義が以下。

  /**
   * Just like showDialog, but will catch a BadTokenException that sometimes
   * (very rarely) gets thrown. This might happen if the user hits the "back"
   * button immediately after sending tracks to google.
   *
   * @param id the dialog id
   */
  public void showDialogSafely(final int id) {
    runOnUiThread(new Runnable() {
      public void run() {
        try {
          showDialog(id);
        } catch (BadTokenException e) {
          Log.w(MyTracksConstants.TAG,
              "Could not display dialog with id " + id, e);
        } catch (IllegalStateException e) {
          Log.w(MyTracksConstants.TAG,
              "Could not display dialog with id " + id, e);
        }
      }
    });
  }

showDialog でたまに BadTokenException が投げられる模様。普通はここまでナーバスにならなくても良いのかもしれません。showDialog で grep したソレを以下に貼っておきます。

$ find src |xargs grep showDialog        
src/com/google/android/apps/mytracks/ChartActivity.java:        MyTracks.getInstance().showDialogSafely(MyTracks.DIALOG_CHART_SETTINGS);
src/com/google/android/apps/mytracks/MyTracks.java:        showDialogSafely(DIALOG_SEND_TO_GOOGLE);
src/com/google/android/apps/mytracks/MyTracks.java:            showDialogSafely(DIALOG_SEND_TO_GOOGLE);
src/com/google/android/apps/mytracks/MyTracks.java:    showDialogSafely(DIALOG_IMPORT_PROGRESS);
src/com/google/android/apps/mytracks/MyTracks.java:   * Just like showDialog, but will catch a BadTokenException that sometimes
src/com/google/android/apps/mytracks/MyTracks.java:  public void showDialogSafely(final int id) {
src/com/google/android/apps/mytracks/MyTracks.java:          showDialog(id);
src/com/google/android/apps/mytracks/MyTracks.java:    showDialogSafely(DIALOG_PROGRESS);
src/com/google/android/apps/mytracks/MyTracks.java:    showDialogSafely(DIALOG_WRITE_PROGRESS);
src/com/google/android/apps/mytracks/MyTracks.java:    showDialogSafely(DIALOG_WRITE_PROGRESS);
src/com/google/android/apps/mytracks/MyTracks.java:      showDialogSafely(DIALOG_SEND_TO_GOOGLE_RESULT);
$

ちなみに Dialog な処理について_http://www.techdoctranslator.com/android/guide/ui/dialogs_な記述を以下に引用しておきます。

ダイアログを表示したい場合は、 showDialog(int) を呼び出し、表示するダイアログを識別するユニークな数値を引数に与えます。

初めてダイアログが要求されると、Android がアクティビティから onCreateDialog(int) (ここが Dialog をインスタンス化すべき場所になります)を呼び出し、このコールバックメソッドに showDialog(int) の引数に与えた ID が渡されてきます。ダイアログを作成後、このメソッドの最後でオブジェクトが返されます。

また、Android はダイアログが表示される前に onPrepareDialog(int, Dialog) というオプションのコーバックメソッドを呼び出します。ダイアログがオープンされるたびにダイアログの何らかのプロパティを変更したい場合はこのメソッドを定義してください。このメソッドはダイアログがオープンされるたびに呼び出されますが、 onCreateDialog(int) が呼び出されるのはダイアログがオープンされる最初の1回のみです。 onPrepareDialog() を定義していない場合は、ダイアログは前回オープンしたときと同じ状態のままになります。このメソッドも onCreateDialog() で生成されたダイアログオブジェクトと一緒にダイアログの ID が渡されます。

onCreateDialog(int) と onPrepareDialog(int, Dialog) コールバックメソッドの定義内では、このメソッドに渡される id パラメータを判定する switch 文を使用するのがもっとも良い方法です。各 case 文ではダイアログのユニークな ID を判定し、それぞれに対応するダイアログを生成し定義することになります。例えば、ゲームではふたつの異なるダイアログ(ひとつはゲームが一時停止している、もうひとつはゲームオーバーになったことを知らせる)が使われるであろうことが想像できるでしょう。ではまず以下のように、各ダイアログの数値 ID を定義します。

http://www.techdoctranslator.com/android/guide/ui/dialogs より引用
ちなみに、MyTracks#onCreateDialog な該当部分以下です。

      case DIALOG_SEND_TO_GOOGLE:
        sendToGoogleDialog = new SendToGoogleDialog(this);
        return sendToGoogleDialog;

で、onPrepareDialog は見てませんな。

      case DIALOG_SEND_TO_GOOGLE:
        resetSendToGoogleStatus();
        break;

む、同じ状態ではマズいので reset してるんですね。

  /**
   * Resets status information for sending to MyMaps/Docs.
   */
  private void resetSendToGoogleStatus() {
    sendToMyMapsMessage = "";
    sendToMyMapsSuccess = true;
    sendToDocsMessage = "";
    sendToDocsSuccess = true;
    sendToMyMapsMapId = null;
  }

上記引用記事によれば

  • onCreateDialog は一度だけ
    • Mytracks ではカスタム Dialog なオブジェクトを生成して戻しているのみ
  • onPrepareDialog は表示される直前に呼び出される
    • SendToGoogleDialog にまつわる属性をクリアしているのみ

あら?

SendToGoogleDialog な onCreate にて以下な記述があるな。

    Button send = (Button) findViewById(R.id.sendtogoogle_send_now);
    send.setOnClickListener(new View.OnClickListener() {
      public void onClick(View v) {
        dismiss();
        MyTracks.getInstance().sendToGoogle();
      }
    });

こーゆワザもなんつーか微妙。盥回し方式で次々に進んでいきます。ちょっとへろへろ気味なので、明日日中にがっつり確認する方向でご勘弁下さいませ。