172 votes

Comment utiliser runOnUiThread dans Android ?

Je suis nouveau sur Android et j'essaie d'utiliser le UI-Thread, j'ai donc écrit une activité de test simple. Mais je pense que j'ai mal compris quelque chose, car après avoir cliqué sur le bouton, l'application ne répond plus.

public class TestActivity extends Activity {

    Button btn;
    int i = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        btn = (Button)findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                runThread();
            }
        });
    }

    private void runThread(){
        runOnUiThread (new Thread(new Runnable() {  
            public void run() {
                while(i++ < 1000){
                    btn.setText("#"+i);
                    try {
                        Thread.sleep(300);
                    } 
                    catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
             }
        }));
    }
}

225voto

Vipul Shah Points 13233

Ci-dessous, un extrait corrigé de runThread Fonction.

private void runThread() {

    new Thread() {
        public void run() {
            while (i++ < 1000) {
                try {
                    runOnUiThread(new Runnable() {

                        @Override
                        public void run() {
                            btn.setText("#" + i);
                        }
                    });
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }.start();
}

0 votes

N'a-t-il pas été collecté presque immédiatement ? Vous avez probablement besoin de garder une référence à la Thread()

18 votes

Nick : le ramasseur d'ordures surveille également la pile, c'est à dire que lorsque le thread est en cours d'exécution, il ne sera pas ramassé.

0 votes

@Vipul, j'avais une question sur la rotation du téléphone : Je veux qu'une fois que je tourne mon téléphone, ce fil fonctionne et qu'aucun nouveau fil ne soit créé. Pouvez-vous me donner quelques conseils sur la façon d'empêcher la création d'un nouveau fil une fois que le téléphone est tourné ?

98voto

Il suffit de l'envelopper dans une fonction, puis d'appeler cette fonction à partir de votre fil d'arrière-plan.

public void debugMsg(String msg) {
    final String str = msg;
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            mInfo.setText(str);
        }
    });
}

28voto

Graham Borland Points 27556

Vous l'avez dos à dos. Votre clic sur le bouton entraîne un appel à runOnUiThread() mais ce n'est pas nécessaire, puisque le gestionnaire de clics est déjà en cours d'exécution sur le thread de l'interface utilisateur. Ensuite, votre code dans runOnUiThread() est le lancement d'un nouveau thread en arrière-plan, où vous essayez d'effectuer des opérations d'interface utilisateur, qui échouent ensuite.

Au lieu de cela, il suffit de lancer le fil d'arrière-plan directement à partir de votre gestionnaire de clics. Ensuite, enveloppez les appels à btn.setText() à l'intérieur d'un appel à runOnUiThread() .

1 votes

S'il est vrai que le gestionnaire de clic se trouve déjà dans le thread de l'interface utilisateur, un appel à runOnUiThread() est inutile mais devrait être inoffensif. La Javadoc de cette méthode dit "Exécute l'action spécifiée sur le thread UI. Si le thread actuel est le thread UI, l'action est exécutée immédiatement. Si le thread actuel n'est pas le thread de l'interface utilisateur, l'action est postée dans la file d'attente des événements du thread de l'interface utilisateur."

16voto

Terranology Points 476
runOnUiThread(new Runnable() {
                public void run() {
                //Do something on UiThread
            }
        });

13voto

Bajrang Hudda Points 719

Il existe plusieurs techniques utilisant des runOnUiThread() Voyons tout

Voici mon thread principal (thread UI) appelé AndroidBasicThreadActivity et je vais le mettre à jour depuis un fil de travail de différentes manières -

public class AndroidBasicThreadActivity extends AppCompatActivity
{
    public static TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_android_basic_thread);

        textView = (TextView) findViewById(R.id.textview);

        MyAndroidThread myTask = new MyAndroidThread(AndroidBasicThreadActivity.this);
        Thread t1 = new Thread(myTask, "Bajrang");
        t1.start();
    }
}

1.) En passant l'instance de l'activité comme argument sur le thread du travailleur

class MyAndroidThread implements Runnable
{
    Activity activity;
    public MyAndroidThread(Activity activity)
    {
        this.activity = activity;
    }
    @Override
    public void run()
    {

        //perform heavy task here and finally update the UI with result this way - 
        activity.runOnUiThread(new Runnable()
        {
            @Override
            public void run()
            {
                AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
            }
        });
    }
}

2.) En utilisant la méthode post(Runnable runnable) de View dans le worker thread

class MyAndroidThread implements Runnable
{
    Activity activity;
    public MyAndroidThread(Activity activity)
    {
        this.activity = activity;
    }
    @Override
    public void run()
    {
     //perform heavy task here and finally update the UI with result this way - 
       AndroidBasicThreadActivity.textView.post(new Runnable()
      { 
        @Override
        public void run()
        {
            AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
        }
    });

    }
}

3.) En utilisant la classe Handler du paquet Android.os Si nous n'avons pas le contexte ( this / getApplicationContext() ) ou l'instance de l'activité ( AndroidBasicThreadActivity.this ) alors nous devons utiliser la classe Handler comme ci-dessous -

class MyAndroidThread implements Runnable
{
    Activity activity;
    public MyAndroidThread(Activity activity)
    {
        this.activity = activity;
    }
    @Override
   public void run()
  {
  //perform heavy task here and finally update the UI with result this way - 
  new Handler(Looper.getMainLooper()).post(new Runnable() {
        public void run() {
            AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
        }
    });
  }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X