从不同的线程修改一个Android视图 [英] Modifying an Android view from a different thread
问题描述
在Android上,活动的主UI线程运行和文字转语音引擎在不同的线程中运行。我想在一个活动来更新视图中的文字转语音引擎完成播放话语时。
On Android, activities run in the main UI thread and the TextToSpeech engine runs in a different thread. I want to update a view in an activity when the TextToSpeech engine completes playing back an utterance.
如果我忽略这一点,然后我得到的时候文字转语音引擎调用活动实例的 android.view.ViewRoot $ CalledFromWrongThreadException
错误。
If I ignore this, then I get an android.view.ViewRoot$CalledFromWrongThreadException
error when the TextToSpeech engine calls the Activity instance.
下面是我的code。在MainActivity.java脚本的最后一行出现的错误。
Here's my code. The error occurs on the last line of the MainActivity.java script.
TTSUser.java
TTSUser.java
package com.example.thread;
interface TTSUser {
void ttsUtteranceComplete();
}
MainActivity.java
MainActivity.java
package com.example.thread;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity implements TTSUser {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new TTS(this);
}
public void ttsUtteranceComplete() {
TextView view_to_hide = (TextView) findViewById(R.id.hello_world);
// On next line: android.view.ViewRoot$CalledFromWrongThreadException:
// Only the original thread that created a view hierarchy can touch its
// views.
view_to_hide.setVisibility(TextView.GONE);
}
}
TTS.java
TTS.java
package com.example.thread;
import android.app.Activity;
import android.content.Context;
import android.speech.tts.TextToSpeech;
import java.util.HashMap;
import java.util.Locale;
public class TTS implements TextToSpeech.OnInitListener, TextToSpeech.OnUtteranceCompletedListener {
private final String TAG = "callback";
private static TextToSpeech tts;
private TTSUser activity;
public TTS(TTSUser activity) { // Ensures access to ttsUtteranceComplete()
this.activity = activity;
Context context = ((Activity) activity).getApplicationContext();
tts = new android.speech.tts.TextToSpeech(context, this);
}
@Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
tts.setLanguage(Locale.UK);
tts.setOnUtteranceCompletedListener(this);
speakText("Hello World");
}
}
public void speakText(String toSpeak) {
int mode = android.speech.tts.TextToSpeech.QUEUE_FLUSH;
// Create an id for this utterance, so that we can call back when it's done
HashMap<String, String> hashMap = new HashMap<String, String>();
hashMap.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, TAG);
tts.speak(toSpeak, mode, hashMap);
}
public void onUtteranceCompleted(String utteranceID) {
if (utteranceID.equals(TAG)) {
activity.ttsUtteranceComplete();
}
}
}
我还添加了行activity_main.xml中TextView的定义,以使的Hello World文本可以识别
I also added a line to the TextView definition in activity_main.xml, so that the Hello World text can be identified.
android:id="@+id/hello_world"
要措词类似问题的其他答案假设其他线程在code明确创建。这里,线程为文字转语音引擎隐式地创建。我怎样才能改变我的code,使MainActivity.java的最后一行不会抛出一个错误?
Other answers to similarly-worded questions assume that the other thread is created explicitly in the code. Here, the thread for the TextToSpeech engine is created implicitly. How can I change my code so that the last line of MainActivity.java does not throw an error?
推荐答案
要在UI线程上执行的东西时,它的外面,你可以使用的方法 runOnUiThread(Runnable接口)
属于活动
。
To execute something on the UI thread when outside of it, you can use the method runOnUiThread(Runnable)
that belongs to Activity
.
所以,你可以这样做:
activity.runOnUiThread(new Runnable() { // EDIT: ...Ui... requires a lowercase "i"
@Override
public final void run()
// this runs on UI thread
activity.ttsUtteranceComplete(); // this function will run on the UI thread
}
});
这篇关于从不同的线程修改一个Android视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!