简体   繁体   English

Android动态文本更新-ViewRootImpl $ CalledFromWrongThreadException

[英]Dynamic Text Update for Android - ViewRootImpl$CalledFromWrongThreadException

I'm a beginner with Android, so please be kind if this is a stupid question. 我是Android的初学者,所以如果这是一个愚蠢的问题,请多多关照。

I'm trying to dynamically update four TextViews. 我正在尝试动态更新四个TextView。 Whenever I try to update them, the program crashes. 每当我尝试更新它们时,程序就会崩溃。

I don't understand the explanation "Only the original thread that created a view hierarchy can touch its views." 我不理解“只有创建视图层次结构的原始线程才能触摸其视图”的解释。

Here is my class: 这是我的课:

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();
}

...and this is my LogCat: ...这是我的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

...and the XML code: ...以及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>

Program is getting crashed because you are trying to update the text on TextView from a non UI Thread. 程序崩溃,因为您试图从非UI线程更新TextView上的文本。

replace your run() method with this: 用以下代码替换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);
  }

}); }); } }

You can't change the UI from another thread, you should use a method that deals with the main thread, for example you can try ASYNCtask to do what you want in the background then change the textviews in onPostExecute() 您不能从另一个线程更改UI,您应该使用处理主线程的方法,例如,您可以尝试ASYNCtask在后台执行您想要的操作,然后在onPostExecute()中更改文本视图
here you are a link to it: 这是您的链接:
http://developer.android.com/reference/android/os/AsyncTask.html http://developer.android.com/reference/android/os/AsyncTask.html

Update: example for AsyncTask 更新: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
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Android - ViewRootImpl$CalledFromWrongThreadException - Android - ViewRootImpl$CalledFromWrongThreadException android.view.viewrootimpl $ fromwrongthreadexception android java - android.view.viewrootimpl$calledfromwrongthreadexception android java Android编码:ViewRootImpl $ CalledFromWrongThreadException。 [菜鸟] - Android coding: ViewRootImpl$CalledFromWrongThreadException. [Noob] 计时器导致ViewRootImpl $ CalledFromWrongThreadException吗? - Timer causing ViewRootImpl$CalledFromWrongThreadException? android.view.ViewRootImpl $ CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触摸其视图 - android.view.ViewRootImpl$CalledFromWrongThreadException:Only the original thread that created a view hierarchy can touch its views 为什么我收到异常ViewRootImpl $ CalledFromWrongThreadException? - Why i'm getting exception ViewRootImpl$CalledFromWrongThreadException? 当我按下按钮时,出现错误ViewRootImpl $ CalledFromWrongThreadException - When my button is pressed, I get the error ViewRootImpl$CalledFromWrongThreadException Android Kotlin:异步调用后如何更新recyclerView? 获取CalledFromWrongThreadException - Android Kotlin: How to update recyclerView after async call? getting CalledFromWrongThreadException ViewRootImpl不在Android SDK中 - ViewRootImpl not in Android SDK CalledFromWrongThreadException在Android上执行JUnit测试 - CalledFromWrongThreadException exercising JUnit tests on Android
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM