web-dev-qa-db-fra.com

Exemple de communication avec HandlerThread

Je veux configurer un HandlerThread à partir du thread GUI. Puis, quelque temps plus tard, lorsqu'un bouton est cliqué sur l'interface graphique, il exécute callHello (), qui envoie ensuite un message à un objet HelloLogger résidant sur le thread non GUI qui enregistre de manière asynchrone "Hello World". J'ai essayé un certain nombre de choses, certaines bloquent indéfiniment, certaines ne reçoivent jamais le message, etc. Le code ci-dessous est plus ou moins aussi proche que je l'ai obtenu, s'il vous plaît quelqu'un pourrait-il le modifier pour fonctionner?

public class HandlerThreadExample {

    private MyHandlerThread mMyHandlerThread;
    private Looper mLooper;
    private Handler mHandler;

    public HandlerThreadExample(){
        mMyHandlerThread = new MyHandlerThread();
        mMyHandlerThread.start();
        mLooper = mMyHandlerThread.getLooper();
    }
    public void callHello() {
        mHandler.sendEmptyMessage(1);
    }
    private class MyHandlerThread extends HandlerThread {
        private HelloLogger mHelloLogger;
        private Handler mHandler;
        public MyHandlerThread() {
            super("The MyHandlerThread thread", HandlerThread.NORM_PRIORITY);
        }
        public void run (){
            mHelloLogger = new HelloLogger();
            mHandler = new Handler(getLooper()){
                public void handleMessage(Message msg){
                    mHelloLogger.logHello();
                }
            };
            super.run();
        }
    }
    private class HelloLogger {
        public HelloLogger (){
        }
        public void logHello(){
            Log.d("HandlerThreadExample", "Hello World");
        }
    }
}

Meilleurs exemples trouvés:

Au moins maintenant je peux fermer les maudits onglets

Solution gracieuseté de l'aide de pskink

public class HandlerThreadExample2 {
    private static int MSG_START_HELLO = 0;
    private static int MSG_HELLO_COMPLETE = 1;
    private HandlerThread ht;
    private Handler mHtHandler;
    private Handler mUiHandler;
    private boolean helloReady = false;
    public HandlerThreadExample2(){
        ht = new HandlerThread("The new thread");
        ht.start();
        Log.d(App.TAG, "UI: handler thread started");
        mUiHandler = new Handler(){
            public void handleMessage(Message msg){
                if (msg.what == MSG_HELLO_COMPLETE){
                    Log.d(App.TAG, "UI Thread: received notification of sleep completed ");
                    helloReady = true;              }
            }
        };
        mHtHandler = new Handler(ht.getLooper()){
            public void handleMessage (Message msg){
                if (msg.what == MSG_START_HELLO){
                    Log.d(App.TAG, "handleMessage " + msg.what + " in " + Thread.currentThread() + " now sleeping");
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.d(App.TAG, "Woke up, notifying UI thread...");
                    mUiHandler.sendEmptyMessage(MSG_HELLO_COMPLETE);
                }
            }
        };
    }
    public void sendLongHello(){
        if (helloReady){
            Log.d(App.TAG, "sending hello " + Thread.currentThread());      
            mHtHandler.sendEmptyMessage(MSG_START_HELLO);
            helloReady = false;
        } else {
            Log.e(App.TAG, "Cannot do hello yet - not ready");
        }
    }
}
29
CL22

Ceci est un exemple de travail:

HandlerThread ht = new HandlerThread("MySuperAwesomeHandlerThread");
ht.start();
Handler h = new Handler(ht.getLooper()) {
    public void handleMessage(Message msg) {
        Log.d(TAG, "handleMessage " + msg.what + " in " + Thread.currentThread());
    };
};
for (int i = 0; i < 5; i++) {
    Log.d(TAG, "sending " + i + " in " + Thread.currentThread());
    h.sendEmptyMessageDelayed(i, 3000 + i * 1000);
}

MISE À JOUR :

Créez deux champs de classe:

Handler mHtHandler;
Handler mUiHandler;

et essayez ceci:

HandlerThread ht = new HandlerThread("MySuperAwsomeHandlerThread");
ht.start();
Callback callback = new Callback() {
    @Override
    public boolean handleMessage(Message msg) {
        if (msg.what == 0) {
            Log.d(TAG, "got a meaasage in " + Thread.currentThread() + ", now sleeping... ");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Log.d(TAG, "woke up, notifying ui thread...");
            mUiHandler.sendEmptyMessage(1);
        } else
        if (msg.what == 1) {
            Log.d(TAG, "got a notification in " + Thread.currentThread());
        }
        return false;
    }
};
mHtHandler = new Handler(ht.getLooper(), callback);
mUiHandler = new Handler(callback);
mHtHandler.sendEmptyMessageDelayed(0, 3000);

Vous pouvez bien sûr vous débarrasser de l'interface Callback et créer deux Handlers avec la méthode handleMessage surchargée ...

53
pskink

Le problème que vous voyez est dû au fait que votre classe externe utilise un champ mHandler privé, tout comme votre HandlerThread. Le champ de la classe externe n'est pas initialisé. Vous n'avez pas besoin du mHandler intérieur. La classe externe peut créer un gestionnaire à partir du looper que vous récupérez juste après avoir appelé start ().

1
Larry Schiefer