0

我在寫遊戲。當用戶結束等級時,會發生以下情況:在當前活動中顯示對話框

  1. 發送POST以檢查級別記錄是否被毆打。 (1-5秒)
  2. 如果是這樣,請輸入Dialog「輸入你的名字」。 (快)
  3. 當用戶點擊確定時,發送POST與他的記錄。 (1-5秒)

當用戶結束級別時,他在GameActivitycheckWorldRecord()被調用,並在其中,一個AsyncTask啓動:

private void checkWorldRecord(final RecordType recordType, final double time, final int level) 
{ 
    new Handler(Looper.getMainLooper()).post(new Runnable() 
    { 
     @Override 
     public void run() 
     { 
      new DownloadTask(recordType, time, level).execute(); 
     } 
    }); 
} 

DownloadTask正在做這三件事情,這是我在上市之初:

class DownloadTask extends AsyncTask<Void, Void, Void> 
{ 
    RecordType recordType; 
    double time; 
    int level; 

    public DownloadTask(RecordType recordType, double time, int level) 
    { 
     super(); 
     this.recordType = recordType; 
     this.time = time; 
     this.level = level; 
    } 

    @Override 
    protected Void doInBackground(Void... params) 
    { 
     try 
     { 
      if (!Network.isWorldRecord(recordType, time, level)) // 1. 
      { 
       return null; 
      } 
     } 
     catch (Exception e) 
     { 
      return null; 
     } 
     Dialogs.showEnterNameAndSend(GameActivity.this, recordType, time, level, highScores.getGamesPlayed(), 
       highScores.getStars()); // 2. 
     return null; 
    } 
} 

一切都很好,當用戶後,等待這場比賽,如果他留在GameActivity

的問題是,當:

  1. 用戶結束了比賽。調用checkWorldRecord()
  2. 在單獨的線程中,1st POST開始。
  3. 用戶按下後退按鈕並將活動更改爲另一個,至MainActivity
  4. AsyncTask完成檢查,我們有新的記錄。 showEnterNameAndSend()想先建立並稍後顯示AlertDialog。繁榮。因爲我們經過GameActivity,現在MainActivity是在頂部:

public static void showEnterNameAndSend(final Activity activity, final RecordType recordType, final double time, 
     final int level, final long gamesPlayed, final int stars) 
{ 
    AlertDialog.Builder builder = new AlertDialog.Builder(activity); // BOOM!!! 
    final EditText editText = new EditText(activity); 
    editText.setFilters(new InputFilter[] 
    { new InputFilter.LengthFilter(Const.MAX_NAME_LENGTH) }); 
    editText.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); 
    builder.setView(editText); 
    builder.setTitle(recordType + " world record!"); 
    builder.setMessage("Enter your name:"); 
    builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() 
    { 
     @Override 
     public void onClick(DialogInterface dialog, int whichButton) 
     { 
      String username = editText.getText().toString(); 
      if (username.equals("")) 
      { 
       return; 
      } 

      try 
      { 
       Network.sendRecord(recordType, username, time, level, gamesPlayed, stars); // 3. 
      } 
      catch (Exception e) 
      { 
       showInternetError(activity); 
      } 
     } 
    }); 
    showDialogOnUiThread(activity, builder); 
} 

private static void showDialogOnUiThread(Activity activity, final AlertDialog.Builder builder) 
{ 
    activity.runOnUiThread(new Runnable() 
    { 
     @Override 
     public void run() 
     { 
      builder.show(); 
     } 
    }); 
} 

是的,我也喜歡傳球Context,而不是整個ActivityshowEnterNameAndSend()。但是,showDialogOnUiThread()(由showEnterNameAndSend()調用)需要Activity,以在UI線程上顯示Dialog,其中activity.runOnUiThread()

如何修復?也許例如有一些方法getCurrentActivity(),所以我不必通過一個Activity,它可以已經隱藏?如果我可以以某種方式取消顯示對話框,用戶關閉GameActivity後,它也會很好。

回答

1

如果要通過嘗試顯示對話框來防止崩潰,你可能已經解決了通過設置一個標誌:

public static boolean userIsOut = false; 

,然後將其設置爲true,當用戶離開該活動的:

@Override 
protected void onDestroy() { 
    userIsOut = true; 
    super.onDestroy(); 
} 

在你ShowEnterNameAndSend()方法,你可以做如:

if(!userIsOut) 
    showDialogOnUiThread(activity, builder); 

因此,如果用戶不在該活動中,將永遠不會構建對話框。

但是,如果你堅持要顯示對話框,那麼我想你應該寫你自己的getCurrentActivity()方法。要做到這一點,你可以有一個類來保存該變量

public static class ActivityHolder { 
    public static Activity current; 

    public static void setCurrentActivity(Activity act) { 
      current = act; 
    } 

    public static Activity getCurrentActivity() { 
      return current; 
    } 
} 

你應該設置在每一個活動的這個的onResume當前活動,並且的onCreate方法......所以,你永遠知道你在哪個活動,並且您可以使用該活動來顯示對話框。

@Override 
protected void onResume() { 
    ActivityHolder.setCurrentActivity(this); 
    super.onResume(); 
} 
0

兩個解決方案,我在我的腦海了:

第一個是創建一個activty(可以稱之爲SpecialActivity)。

此活動將保存將在onResume中註冊的廣播接收器,並將在onPause中註銷。

您的每項活動都將繼承SpecialActivity並將從doInBackground方法中獲得廣播,然後將調用顯示對話框的方法。

第二個,就是要創造一種無形的活動(可以稱之爲DialogActivity)是 它的唯一責任是調用的onCreate對話框,並殺死自己一旦 對話框已dissmissed。 該活動也將從doInBackground(startActivity ...)觸發。

也許還有更簡單,智能的解決方案,但是這就是我在我的腦海裏了:d

0

嘗試只改變對話框,將應用程序上下文,而不是活動場景上下文。您可以通過使用自定義應用程序類(我的首選項)來獲取它,該類包含對應用程序上下文的靜態引用或使用GameActivity.this.getAppContext()

+0

但我需要在UI線程上運行builder.show()。爲此,我必須使用runOnUiThread(),這是Activity的一種方法,而不是Context。 –

+0

我認爲在大多數情況下,情境並不重要。您應該能夠使用UI線程上的應用程序上下文和調用show來創建構建器。你嘗試過嗎? – toadzky

+0

如果我刪除runOnUiThread()應用程序崩潰。那麼,我如何運行builder.show()而沒有引用Activity? –

相關問題