Autore Topic: Invio messaggio da activity a thread remoto  (Letto 291 volte)

Offline darioconcilio

  • Nuovo arrivato
  • *
  • Post: 5
  • Respect: 0
    • Mostra profilo
Invio messaggio da activity a thread remoto
« il: 03 Settembre 2016, 16:28:38 CEST »
0
Ciao a tutti,
mi sento molto idiota, ma me ne farò una ragione. Lavoro nel multithreading da molto tempo, ma non nel mondo Android.
Mi trovo un po spaesato nell'architettura, quindi sono qui a chiedere aiuto (spero un giorno di rendere il favore).

Allego qui un piccolo progetto per capire come funziona l'Handler. Ora, banalmente, nell'activity compilo un quesito, che invio al Thread remoto.
Il Thread remoto riceve la domanda e risponde, all'activity.

E' possibile? Nel LogCat chiaramente da un errore nel momento in cui eseguo il metodo sendQuestion, mi sembra di capire che c'é un problema di esecuzione nel thread sbagliato, ho capito bene?

LogCat:
09-03 15:58:05.382 21044-21044/it.test.handlertest E/AndroidRuntime: FATAL EXCEPTION: main
                                                                     Process: it.test.handlertest, PID: 21044
                                                                     java.lang.NullPointerException
                                                                         at it.test.handlertest.MainActivity.sendQuestion(MainActivity.java:56)
                                                                         at it.test.handlertest.MainActivity$2.onClick(MainActivity.java:44)
                                                                         at android.view.View.performClick(View.java:4640)
                                                                         at android.view.View$PerformClick.run(View.java:19431)
                                                                         at android.os.Handler.handleCallback(Handler.java:733)
                                                                         at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                         at android.os.Looper.loop(Looper.java:146)
                                                                         at android.app.ActivityThread.main(ActivityThread.java:5598)
                                                                         at java.lang.reflect.Method.invokeNative(Native Method)
                                                                         at java.lang.reflect.Method.invoke(Method.java:515)
                                                                         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
                                                                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
                                                                         at dalvik.system.NativeStart.main(Native Method)
09-03 16:02:06.947 21538-21538/it.test.handlertest D/AndroidRuntime: Shutting down VM
09-03 16:02:06.947 21538-21538/it.test.handlertest W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x41890c08)
09-03 16:02:06.947 21538-21538/it.test.handlertest E/AndroidRuntime: FATAL EXCEPTION: main
                                                                     Process: it.test.handlertest, PID: 21538
                                                                     java.lang.NullPointerException
                                                                         at it.test.handlertest.MainActivity.sendQuestion(MainActivity.java:56)
                                                                         at it.test.handlertest.MainActivity$2.onClick(MainActivity.java:44)
                                                                         at android.view.View.performClick(View.java:4640)
                                                                         at android.view.View$PerformClick.run(View.java:19431)
                                                                         at android.os.Handler.handleCallback(Handler.java:733)
                                                                         at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                         at android.os.Looper.loop(Looper.java:146)
                                                                         at android.app.ActivityThread.main(ActivityThread.java:5598)
                                                                         at java.lang.reflect.Method.invokeNative(Native Method)
                                                                         at java.lang.reflect.Method.invoke(Method.java:515)
                                                                         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
                                                                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
                                                                         at dalvik.system.NativeStart.main(Native Method)


Cosa non mi è chiaro?

Ho pensato che forse la comunicazione "bidirezionale" non sia possibile in questo modo, dovrei usare un Service?
Con il Service però rimane il problema di mandare il messaggio all'interno del Service ai sotto thread che si dovranno avviare.
Insomma, da thread a thread è possibile la comunicazione bidirezionale?

MainActivity.java

Codice (Java): [Seleziona]
package it.test.handlertest;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import org.w3c.dom.Text;

public class MainActivity extends AppCompatActivity {

    private RemoteRunnableThread mRemoteThread;
    public Handler mHandler;

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

        mRemoteThread = new RemoteRunnableThread(this);
        mRemoteThread.start();

        mHandler = new Handler() {

            @Override
            public void handleMessage(Message pMessage) {
                update(pMessage.obj.toString());
            }

        };

        Button eseguiButton = (Button) findViewById(R.id.esegui);
        eseguiButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                EditText domandaEditText = (EditText) findViewById(R.id.domanda);

                sendQuestion(domandaEditText.getText());

            }
        });
    }

    void update(String pResponse) {
        TextView rispostaTextView = (TextView) findViewById(R.id.risposta);
        rispostaTextView.setText(pResponse);
    }

    void sendQuestion(Editable pQuestion) {
        final Message message = mRemoteThread.consumerHandler.obtainMessage();
        message.obj = pQuestion.toString();
        message.sendToTarget();
    }
}

RemoteRunnableThread.java

Codice (Java): [Seleziona]
package it.test.handlertest;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import java.lang.ref.WeakReference;

/**
 * Created by darioconcilio on 03/09/16.
 */

public class RemoteRunnableThread implements Runnable {

    private boolean mRunning = false;
    private WeakReference<MainActivity> mActivityReference;
    public Handler consumerHandler;
    private Thread mThread;
    private boolean mStarted = false;

    public RemoteRunnableThread(MainActivity pActivity) {
        this.mActivityReference = new WeakReference<MainActivity>(pActivity);
    }

    @Override
    public void run() {
        while(mRunning) {

            if(!mStarted) {
                mStarted = true;

                //Looper.prepare();

                consumerHandler = new Handler() {
                    @Override
                    public void handleMessage(Message pMessage) {
                        String value = pMessage.obj.toString();

                        MainActivity activity = mActivityReference.get();
                        if(activity!=null) {
                            //Risposta al chiamante

                            String risposta = value + " : questa è la risposta....";
                            Message message = activity.mHandler.obtainMessage();
                            message.obj = risposta;
                            activity.mHandler.sendMessage(message);
                        }

                    }
                };

                mRunning = true;

                //Looper.loop();
            }
        }
    }

    public void start() {
        if(!mRunning) {
            mRunning = true;
            mThread = new Thread(this, "RemoteRunnableThread");
        }
    }

    public void stop() {
        if(mRunning) {
            mRunning = false;
            mThread = null;
        }
    }
}

Grazie per la pazienza.

Post unito: 03 Settembre 2016, 17:05:53 CEST
Ok, tutto chiaro, sono ideotonto.

ho spostato l'inizializzazione di consumerHandler fuori dal metodo Run e l'ho messo nel costruttore di RemoteRunnableThread.
Il tutto funziona.
In questo modo l'activity comunica con il thread e viceversa.
L'activity può avviare e stoppare il thread remoto quando vuole.
« Ultima modifica: 03 Settembre 2016, 17:05:53 CEST da darioconcilio, Reason: Merged DoublePost »