私はゲームを書いています。ユーザーがレベルを終了すると、次のことが起こります。
- POSTを送信して、レベルレコードが破られたかどうかを確認します。(1-5秒)
- その場合は、
Dialog
「名前を入力してください」と表示します。(速い) - ユーザーが[OK]をクリックしたら、自分のレコードとともにPOSTを送信します。(1-5秒)
ユーザーがレベルを終了すると、彼はになりGameActivity
ます。checkWorldRecord()
が呼び出され、その中で、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
私が最初にリストしたこれらの3つのことをしています:
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
。
問題は、次の場合です。
- ユーザーがゲームを終了しました。
checkWorldRecord()
と呼ばれます。 - 別のスレッドで、最初のPOSTが開始されます。
- ユーザーが戻るボタンを押して、アクティビティを別のアクティビティに変更し
MainActivity
ます。 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
全体ではなく、Activity
を渡すことも好みshowEnterNameAndSend()
ます。ただし、showDialogOnUiThread()
(によって呼び出されるshowEnterNameAndSend()
)は、 UIスレッドにActivity
を表示するために、を必要とします。Dialog
activity.runOnUiThread()
これを修復する方法は?たぶん、例えば、いくつかの方法があるので、私は、すでに隠されている可能性があるgetCurrentActivity()
を渡す必要はありませんか?Activity
どういうわけかダイアログの表示をキャンセルできれば、ユーザーが閉じた後GameActivity
も問題ありません。