[解決済み】Android "ビュー階層を作成した元のスレッドだけが、そのビューに触れることができる"
2022-02-07 14:48:40
質問
音楽プレーヤー(Android)を作っているのですが、曲のビューにSeekBarが含まれています。
public class Song extends Activity implements OnClickListener,Runnable {
private SeekBar progress;
private MediaPlayer mp;
// ...
private ServiceConnection onService = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder rawBinder) {
appService = ((MPService.LocalBinder)rawBinder).getService(); // service that handles the MediaPlayer
progress.setVisibility(SeekBar.VISIBLE);
progress.setProgress(0);
mp = appService.getMP();
appService.playSong(title);
progress.setMax(mp.getDuration());
new Thread(Song.this).start();
}
public void onServiceDisconnected(ComponentName classname) {
appService = null;
}
};
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.song);
// ...
progress = (SeekBar) findViewById(R.id.progress);
// ...
}
public void run() {
int pos = 0;
int total = mp.getDuration();
while (mp != null && pos<total) {
try {
Thread.sleep(1000);
pos = appService.getSongPosition();
} catch (InterruptedException e) {
return;
} catch (Exception e) {
return;
}
progress.setProgress(pos);
}
}
問題なく動作しています。それから、曲の進行の秒/分をカウントするタイマーが欲しいです。
そこで
TextView
で取得し、レイアウトの
findViewById()
で
onCreate()
で、これを
run()
の後に
progress.setProgress(pos)
:
String time = String.format("%d:%d",
TimeUnit.MILLISECONDS.toMinutes(pos),
TimeUnit.MILLISECONDS.toSeconds(pos),
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(
pos))
);
currentTime.setText(time); // currentTime = (TextView) findViewById(R.id.current_time);
しかし、最後の行でエラーが発生します。
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
しかし、ここでやっていることは、基本的に
SeekBar
- にビューを作成します。
onCreate
でタッチし、それを
run()
- で、この苦情は出ません。
解決方法は?
バックグラウンドタスクのうち、UIを更新する部分をメインスレッドに移動させる必要があります。そのための簡単なコードがあります。
runOnUiThread(new Runnable() {
@Override
public void run() {
// Stuff that updates the UI
}
});
のドキュメント
Activity.runOnUiThread
.
これをバックグラウンドで動作しているメソッド内にネストし、ブロックの途中に更新を実装するコードをコピーペーストするだけです。できるだけ小さなコードだけを含めるようにします。そうしないと、バックグラウンド・スレッドの目的が達成されなくなります。
関連
-
git eclipseプラグインのインストール
-
CE5.2版を使って、武術のベースサイトである第一レベルのメソッドを見つける(グラフィックチュートリアル)。
-
スクリプトとは何かを簡単に説明します。
-
[解決済み】C++使用時、代入の左オペランドにlvalueが必要なエラーについて
-
[解決済み】'const char*' から 'char*' への無効な変換。
-
[解決済み】dyld: ライブラリがロードされない ... 理由: 画像が見つからない
-
[解決済み] MIPSのフェッチアドレスがワード境界にアライメントされていないため、.align 4を使用したが、まだうまくいかない
-
[解決済み】C#コンパイラーエラー。"すべてのコードパスが値を返すわけではない"
-
[解決済み] [Solved] libpthread.so.0: error adding symbols: コマンドラインからDSOが見つからない
-
[解決済み】クロススレッド操作が有効でない。作成されたスレッド以外のスレッドからアクセスされたコントロール
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
batスクリプトからログを出力する方法
-
CSスクリプトの使用方法
-
合理的オブジェクトスクリプトコマンド
-
[解決済み】C++使用時、代入の左オペランドにlvalueが必要なエラーについて
-
[解決済み】 munmap_chunk(): 無効なポインタ
-
[解決済み】C++の<map>に相当するC#は何ですか?[重複しています]
-
[解決済み】コレクションが変更され、列挙操作が実行されないことがある。
-
[解決済み】Nullableオブジェクトは値を持たなければならない?
-
[解決済み】二重の空きや破損(fasttop)
-
[解決済み] [Solved] libpthread.so.0: error adding symbols: コマンドラインからDSOが見つからない