基本的に、私は、呼び出されて必要な情報(カードとアクションについて)を長く渡すいくつかのメソッドを使用するブラックジャックアプリを作成しました。クリック可能(ヒットアンドスタンド)の2つのボタンが画面に表示されています。今、私はプレーヤーターンと呼ばれるメソッドを持っています...そしてこれは私が(静的intを介して)ボタンが選択されている場合に持っているときです、物事は起こります。ただし、ボタンが押されているかどうかを確認し続け、ボタンが押されたときにのみアクションを実行すると考えて、無限のwhileループでこれを実行しました。テキストビューまたはイメージビューが変更されるたびに画面が更新されないため、これは機能しません。したがって、ゲームの開始を押すとすぐにゲームが「フリーズ」しているように見え(メソッドが終了しないため)、ボタンをクリックできません。 。アンドロイドで、Java(アクティビティを一時停止してユーザー入力を待つ)のキーボードリスナーに似たものを呼び出す方法はありますか?そうでない場合、回避策は何を提案しますか?最後に(現在はそれほど重要ではありませんが)、変更のたびにすべてを適切に更新するにはどうすればよいですか(invalidateを使用する必要があると思います。ただし、invalidする前に何が必要かわからないため、全体が更新されます)。よろしくお願いします。
5 に答える
Activity
新しい(によって呼び出されたstartActivityForResult
)のように見え、 (Handler
から呼び出されたonActivityResult
)が問題を解決する可能性があります。
以下のデザインスニペットを見てください。
あなたが「眠る」ことをいとわないメソッドがクラスdoSomething
からのものであるとしましょう。MainActivity
これは、イベントハンドラーの実装から呼び出されると思います。そのメソッドからのすべての呼び出しをBackgroundActivity
アクティビティに移動する必要があります。アクティビティには、ProgressDialogまたはその他何も表示されないはずです。
doSomethingメソッドでは、BackgroundActivityを指すインテントによってアクティビティを開始する必要があります。
this.startActivityForResult(new Intent(this, BackgroundActivity.class),
BG_ACTIVITY_ID);
ここで、BG_ACTIVITY_IDは、開始されたアクティビティの一意の識別子であるため、終了時に処理できます。
内部processBackgroundData
(またはバックグラウンドアクティビティの処理が終了したとき)では、finish()を呼び出す前に結果を設定する必要があります。
final Intent intent = new Intent();
intent.putExtra(KEY_FOR_DATA_YOU_NEED, dataYouNeed);
setResult(Activity.RESULT_OK, intent);
finish();
MainActivityでは、onActivityResult
メソッドをオーバーライドして、終了したBackgroundActivityタスクから必要な情報を取得する必要があります。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
//you might also want to check if the resultCode is `Activity.RESULT_OK`...
switch (requestCode)
{
case BG_ACTIVITY_ID:
//get the data you need
final String dataYouNeed = data.getStringExtra(KEY_FOR_DATA_YOU_NEED);
//process the data...
//if necessary (threads!), call your backgroundHandler's
//sendMessage with the retrieved informations as obj.parameters
[...]
break;
default:
[...]
break;
}
}
また、BackgroundHandler
のhandleMessage
メソッド内で(uiスレッドに戻ったため:メインアプリケーションが実行されているスレッド)、必要なすべてのui変更を実行し、ユーザーイベントをリッスンすることもできます。
このようにして、無限ループを取り除き、ユーザーの操作を常に認識できます。
アクティビティのコールバックルーチンは、最後のイベントリスナーを待ちます...これは簡単な解決策でしょうか??
この「ユーザー入力を待つ」という質問は、定期的に出てくる質問であり、私も困惑しています。実際のクリーンなソリューションのように見えるものはまだ見ていません。
最近アイデアを思いついたのですが、Androidゲームはかなりグリーンで、精査に耐えられるかどうかを確認したいと思います。
この手法は、リッスンし続けるイベントリスナーが存在する限り、アクティビティコールバックルーチンは完了しないという考えに基づいています。その結果、コールバックルーチンは最後のステートメントを実行し、その後何も実行せずに終了します。(IOW、「いつでもチェックアウトできますが、イベントリスナーが許可するまで、離れることはできません。」Yuk。)
これは要件に適合しているようです。UIはフリーズせず、無限ループはありません。UIに対する唯一の要求は、イベントリスターを維持することです。ユーザーが入力を提供すると、イベントコールバックルーチン(onKey)が入力を処理し、次のユーザー入力が必要になる前に必要なすべての手順を実行します。次に、イベントコールバックルーチンが新しいリスナーを設定して戻り、古いリスナーを解放し、UIを1つのタスク(新しいリスナーを維持する)のままにします。これは、アクティビティコールバックルーチンが完了するまで繰り返し続けられます。
これが私がテストしたいくつかのコードです:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public void onStart() {
super.onStart();
final EditText et = (EditText) findViewById(R.id.edittext);
et.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
boolean tf = checKey(keyCode, event);
if(tf==false)return false;
gotPW();
return true;
}
});
}
gotPW(){
...do ALL the stuff you want to do before you need more user input
...set ANOTHER event listener that is connected to another
event callback method
...return, releasing the first event listener, and putting the onStart
routine back in its same state -- nothing to do except to attend to
an event listener.
}
//this checks to see if the enter key has been hit
public boolean checKey(int keyCode, KeyEvent event){
if ((event.getAction() == KeyEvent.ACTION_DOWN) &&
(keyCode == KeyEvent.KEYCODE_ENTER))
{
return true;
}
return false;
}
前述のコードは必要なことを実行しているようです...onStartは私の入力を待っていました。
これは良いテクニックですか?
まだ特定していない問題はありますか?
誰もがずっとこれをやっていて、私のような初心者だけが彼らが何かに取り組んでいると思いますか?
Androidはイベントループを実行します。そのため、自分で入力を待つためにループする必要はありません。
さまざまな方法でループに接続できます。1.6以降、これを行う最も簡単な方法は、XMLでフックを指定することです。例:
<Button android:onClick = "myClickHandler" />
または、setOnClickListenerを呼び出して、コードでこれを行うこともできます。
いくつかの例については、http://android-developers.blogspot.com/2009/10/ui-framework-changes-in-android-16.htmlをご覧ください(「より簡単なクリックリスナー」という見出しのセクションをお読みください)
ビューを無効にできる場合は、Androidイベントループが、レイアウトの変更を含め、画面の再描画を処理します。カスタムビューがある場合、それらのonDraw()が適切に呼び出されます。
お役に立てれば。
うーん、私は間違った解釈をしているかもしれませんが、setOnClickListenerを実行すると、コードの特定の部分に到達したときにボタンがクリック可能になり、ボタンがクリックされたときにアクションが実行されるようになっているようです。ボタンがクリックされてプレイヤーの番になったときにアクションが発生するように、私はすでにそれを持っています。しかし、私が知る必要があるのは、ボタンの1つが押されるまでプログラムを文字通り待機または一時停止させる方法です。
キーボードを起動し、Javaがキーボード入力が行われるのを待つ場合と同様です。
ボタンが押されたかどうかを確認するためにポーリングしないでください。OnClickHandlerでやりたいことを何でもしてください。
コードがどのように見えるかの例を次に示します(間違った方法):
while(1) {
if (buttonHitClicked()) {
doHit();
} else if (buttonStandClicked()) {
doStand();
}
//sleep(); // won't help
}
そして、これが正しい方法です:
OnClickListener hitListener = new OnClickListener() {
public void onClick(View v) { doHit(); }
};
OnClickListener standListener = new OnClickListener() {
public void onClick(View v) { doStand(); }
};
protected void OnCreate(Bundle savedValues) {
...
Button hitButton = (Button)findViewById(R.id.hitButton);
button.setOnClickListener(hitListener);
Button standButton = (Button)findViewById(R.id.standButton);
button.setOnClickListener(standListener);
...
}
はい、正しい方法にはもう少しタイピングが必要です...しかしそれはまた機能します。そして、コリンが投稿したリンクを見ると、AndroidManifestファイルに何かを追加することを含む「タイプy」の方法はあまりありません。クラス内の関数に適切な署名を指定するだけで(public void funcName(View v)
私が覚えているように)、Androidがすべてのリスナーを処理します。
「あなたのプログラムを待たせる」限り、それはすでにです。クラスのエントリポイントの1つが呼び出されるまで、プログラムコードは実行されません。それまでは、実行はプロセス内のAndroidのUIハンドラーコード内で変動し、メッセージをやり取りします。これらのメッセージの1つがアプリに表示されるとすぐに(onCreate、クリックリスナーなど)、コードはそれを実行して戻り、UIスレッドがアプリのプロセスのすべての入力の処理に戻ることができるようにします。
また、アプリがメッセージに応答するのに5秒以上かかる場合は、システムによって強制終了され、「ANR」が表示されます...アプリが応答しません。
「ZippyAndroidアプリの作成」というタイトルのもう1つの便利なGoogleIOビデオ。