我是Android的初学者,所以如果这是一个愚蠢的问题,请善待。
我正在尝试动态更新四个TextView。每当我尝试更新它们时,程序都会崩溃。
我不明白解释“只有创建视图层次结构的原始线程才能触及其视图。”
这是我的班级:
Globals g = new Globals();
String l1 = "";
String l2 = "";
String l3 = "";
String l4 = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
}
@Override
public void onStart() {
super.onStart();
//View view = getLayoutInflater().inflate(R.layout.activity_game, null);
run ();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_game, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private void nextLine (String s, int pauseTime, TextView first, TextView second, TextView third, TextView fourth)
{
l4 = l3;
l3 = l2;
l2 = l1;
l1 = s;
first.setText (l1);
second.setText (l2);
third.setText (l3);
fourth.setText(l4);
try
{
Thread.sleep (pauseTime);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
@Override
public void onPause ()
{
super.onPause ();
}
@Override
public void run () {
Thread thread = new Thread() {
@Override
public void run() {
TextView first = (TextView) findViewById(R.id.botLine);
TextView second = (TextView) findViewById(R.id.secondLine);
TextView third = (TextView) findViewById(R.id.thirdLine);
TextView fourth = (TextView) findViewById(R.id.fourthLine);
first.setTypeface(Typeface.MONOSPACE);
second.setTypeface(Typeface.MONOSPACE);
third.setTypeface(Typeface.MONOSPACE);
fourth.setTypeface(Typeface.MONOSPACE);
first.setTextSize((float) g.getTextSizeInt());
second.setTextSize((float) g.getTextSizeInt());
third.setTextSize((float) g.getTextSizeInt());
fourth.setTextSize((float) g.getTextSizeInt());
nextLine("1", 1000, first, second, third, fourth);
nextLine("2", 1000, first, second, third, fourth);
}
};
thread.start();
}
...这是我的LogCat:
08-05 02:33:34.129 14823-14854/com.mycompany.TestApp E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-190
Process: com.mycompany.TestApp, PID: 14823
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6357)
at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:909)
at android.view.ViewGroup.invalidateChild(ViewGroup.java:4690)
at android.view.View.invalidateInternal(View.java:11801)
at android.view.View.invalidate(View.java:11765)
at android.view.View.invalidate(View.java:11749)
at android.widget.TextView.checkForRelayout(TextView.java:6858)
at android.widget.TextView.setText(TextView.java:4057)
at android.widget.TextView.setText(TextView.java:3915)
at android.widget.TextView.setText(TextView.java:3890)
at com.mycompany.TestApp.Game.nextLine(Game.java:64)
at com.mycompany.TestApp.Game.access$000(Game.java:13)
at com.mycompany.TestApp.Game$1.run(Game.java:106)
08-05 02:33:34.266 14823-14839/com.mycompany.TestApp W/EGL_emulation﹕ eglSurfaceAttrib not implemented
08-05 02:33:34.266 14823-14839/com.mycompany.TestApp W/OpenGLRenderer﹕ Failed to set EGL_SWAP_BEHAVIOR on surface 0xb3f1ff20, error=EGL_SUCCESS
...和XML代码:
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="@+id/botLine"
android:layout_marginBottom="70dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="@+id/secondLine"
android:layout_marginBottom="70dp"
android:layout_above="@+id/botLine"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="@+id/thirdLine"
android:layout_marginBottom="70dp"
android:layout_above="@+id/secondLine"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="@+id/fourthLine"
android:layout_marginBottom="70dp"
android:layout_above="@+id/thirdLine"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</RelativeLayout>
答案 0 :(得分:1)
程序正在崩溃,因为您正在尝试从非UI线程更新TextView上的文本。
用这个替换你的run()方法:
public void run () {
Handler handler = new Handler(Looper.getMainLooper);
handler.post(new Runnable(){
@Override
public void run(){
TextView first = (TextView) findViewById(R.id.botLine);
TextView second = (TextView) findViewById(R.id.secondLine);
TextView third = (TextView) findViewById(R.id.thirdLine);
TextView fourth = (TextView) findViewById(R.id.fourthLine);
first.setTypeface(Typeface.MONOSPACE);
second.setTypeface(Typeface.MONOSPACE);
third.setTypeface(Typeface.MONOSPACE);
fourth.setTypeface(Typeface.MONOSPACE);
first.setTextSize((float) g.getTextSizeInt());
second.setTextSize((float) g.getTextSizeInt());
third.setTextSize((float) g.getTextSizeInt());
fourth.setTextSize((float) g.getTextSizeInt());
nextLine("1", 1000, first, second, third, fourth);
nextLine("2", 1000, first, second, third, fourth);
}
}); }
答案 1 :(得分:0)
您无法从其他线程更改UI,您应该使用处理主线程的方法,例如您可以尝试ASYNCtask在后台执行您想要的操作然后更改onPostExecute()中的文本视图
在这里你是它的链接:
http://developer.android.com/reference/android/os/AsyncTask.html
更新: AsyncTask的示例
class Name extends AsyncTask<Void, Void, Boolean>{
//you can add variables here to be public in the class
// also you can add a constructor to the class
@Override
protected void onPreExecute() {
super.onPreExecute();
// here the code that you wanna do before starting the thread
// you can delete this method if you want
}
@Override
protected Boolean doInBackground(Void... parms) {
// this is the method that will do the word away from the main thread
// it must exist in the AsyncTask
// this method will return boolean but you should check if it's null or not
}
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
// in this method you can deal with UI
}
}