web-dev-qa-db-fra.com

Seul le thread d'origine qui a créé une hiérarchie de vues peut toucher ses vues. Sur android

Je ne suis qu'un débutant, alors pardonnez-moi de vous avoir posé une question stupide


Je ne comprends pas la signification de Seul le fil d'origine qui a créé une hiérarchie de vues peut toucher ses vues.

S'il vous plaît quelqu'un peut-il m'apprendre pourquoi cette erreur se produit et comment résoudre ce problème.

Merci

C'est ma classe

public class MainActivity extends Activity {
    TextView title;
    Random   random  = new Random();
    int      counter = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.startup);
        startingUp();
    }

    private void startingUp() {
        Thread timer = new Thread() { //new thread         
            public void run() {
                Boolean b = true;
                try {
                    do {
                        counter++;
                        title();
                        sleep(1000);
                        title.clearComposingText();

                    }
                    while (b == true);
                } catch (IntruptedException e) {
                    e.printStackTrace();
                }
                finally {
                }
            };
        };
        timer.start();
    }

    public void title() {
        title = (TextView) findViewById(R.id.tvTitle);
        switch (random.nextInt(2)) {
            case 0:
                title.setGravity(Gravity.RIGHT);
                break;
            case 1:
                title.setGravity(Gravity.CENTER);
                break;
            case 2:
                title.setGravity(Gravity.LEFT);
                break;
        }
        title.setTextColor(Color.rgb(random.nextInt(250), random.nextInt(250), random.nextInt(250)));
        title.setTextSize(random.nextInt(55) + 10);
    }
}

Et voici mon LogCat

02-20 10:53:19.293: I/Adreno200-EGLSUB(5816): <ConfigWindowMatch:2078>: Format RGBA_8888.
02-20 10:53:19.303: D/memalloc(5816): /dev/pmem: Mapped buffer base:0x5c914000 size:14135296 offset:10366976 fd:64
02-20 10:53:19.303: E/(5816): Can't open file for reading
02-20 10:53:19.303: E/(5816): Can't open file for reading
02-20 10:53:19.303: D/OpenGLRenderer(5816): Enabling debug mode 0
02-20 10:53:19.373: D/memalloc(5816): /dev/pmem: Mapped buffer base:0x5db58000 size:3768320 offset:0 fd:67
02-20 10:53:20.143: W/dalvikvm(5816): threadid=11: thread exiting with uncaught exception (group=0x40abc210)
02-20 10:53:20.143: E/AndroidRuntime(5816): FATAL EXCEPTION: Thread-3102
02-20 10:53:20.143: E/AndroidRuntime(5816): Android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
02-20 10:53:20.143: E/AndroidRuntime(5816):     at Android.view.ViewRootImpl.checkThread(ViewRootImpl.Java:4039)
02-20 10:53:20.143: E/AndroidRuntime(5816):     at Android.view.ViewRootImpl.invalidateChild(ViewRootImpl.Java:722)
02-20 10:53:20.143: E/AndroidRuntime(5816):     at Android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.Java:771)
02-20 10:53:20.143: E/AndroidRuntime(5816):     at Android.view.ViewGroup.invalidateChild(ViewGroup.Java:4112)
02-20 10:53:20.143: E/AndroidRuntime(5816):     at Android.view.View.invalidate(View.Java:8639)
02-20 10:53:20.143: E/AndroidRuntime(5816):     at Android.view.View.invalidate(View.Java:8590)
02-20 10:53:20.143: E/AndroidRuntime(5816):     at Android.widget.TextView.setGravity(TextView.Java:2538)
02-20 10:53:20.143: E/AndroidRuntime(5816):     at com.example.saikoro.MainActivity.title(MainActivity.Java:58)
02-20 10:53:20.143: E/AndroidRuntime(5816):     at com.example.saikoro.MainActivity$1.run(MainActivity.Java:36)

Modifiez votre startingUp() en ceci.

 private void startingUp() {
    Thread timer = new Thread() { //new thread         
        public void run() {
            Boolean b = true;
            try {
                do {
                    counter++;
                    title();
                    sleep(1000);

                    runOnUiThread(new Runnable() {  
                    @Override
                    public void run() {
                        // TODO Auto-generated method stub

                        title.clearComposingText();
                    }
                });


                }
                while (b == true);
            } catch (IntruptedException e) {
                e.printStackTrace();
            }
            finally {
            }
        };
    };
    timer.start();
}

Vous ne pouvez pas modifier les vues à partir d'un thread non-UI.

30
moDev

Cette exception ne vient pas à cause de title.clearComposingText (). même cette ligne n'est pas utile, nous pouvons supprimer cette ligne. Cette exception arrive dans la fonction title () car un thread non UI essaie de modifier la vue. nous devons donc appeler cette fonction dans un ( Thread d'interface utilisateur ou gestionnaire.

private void startingUp() {
        Thread timer = new Thread() { //new thread         
            public void run() {
                boolean b = true;
                try {
                    do {
                        counter++;

                        sleep(1000);
                        runOnUiThread(new Runnable() {

                            @Override
                            public void run() {
                                  title();
                                //title.clearComposingText();//not useful

                            }
                        });


                    }
                    while (b == true);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                finally {
                }
            };
        };
        timer.start();
    }
11
nitwatar

Vous ne pouvez pas modifier le texte avec title.clearComposingText(); à l'intérieur du thread car vous ne pouvez modifier les vues qu'à partir du thread d'interface utilisateur. Utilisez plutôt un gestionnaire et laissez-le modifier le texte.

2
WarrenFaith

Vous ne devez pas mettre à jour textView à partir d'un thread autre que le thread d'interface utilisateur.Vous pouvez utiliser une tâche asynctrogue pour cela.Pouvez vous référer ceci

2
user1969053

Comme d'autres personnes l'ont déjà dit, vous ne pouvez pas modifier l'interface utilisateur à partir d'un thread d'arrière-plan.

Vous pouvez soit utiliser AsyncTask , soit utiliser la méthode Activity.runOnUiThread()

2
nicopico