Обработчик `handleMessage` возвращает идентификатор потока основного потока вместо идентификатора рабочего потока - PullRequest
1 голос
/ 21 апреля 2019

Я пытаюсь освоить многопоточность в Android.Моя цель - отправить данные из основного потока в рабочий поток.

У меня есть основное действие со следующим кодом в onCreate -

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

        ThreadOne threadOne = new ThreadOne();
        threadOne.start();
        threadOneLooper = threadOne.getLooper();

        Message msg = new Message();
        msg.obj = "message.";

        Log.i("id--(threadOneLooper)", String.valueOf(threadOneLooper.getThread().getId()));
        Log.i("id--(Main)", String.valueOf(getMainLooper().getThread().getId()));

        TestHandler mHandler = new TestHandler(threadOneLooper);
        mHandler.handleMessage(msg);
    }

Как вы можете заметить,Я сохраняю ссылку на петлитель рабочего потока в threadOneLooper, а затем записываю идентификатор его связанного потока.В то же время я также печатаю идентификатор основного потока.

Ниже приводится код для моего потока -

public class ThreadOne extends Thread{

    @Override
    public void run() {

        if (Looper.myLooper() == null)
            Looper.prepare();

        Log.i("ThreadOne", "run()");

        // Just making sure all approaches give the same result
        Log.i("Id--Thread id 1", String.valueOf(getLooper().getThread().getId()));
        Log.i("Id--Thread id 2", String.valueOf(getId()));

        Looper.loop();
    }

     Looper getLooper() {
        if (Looper.myLooper() != null)
            return Looper.myLooper();
        else
            return null;
    }

И следующий код моего обработчика -

public class TestHandler extends Handler {

    TestHandler(Looper myLooper) {
        super(myLooper);
    }
    public void handleMessage(Message msg) {

        String txt = (String) msg.obj;
        Log.i("Handler", txt);
        Log.i("Id--(Handler)", String.valueOf(getLooper().getThread().getId()));
    }
}

Теперь проблема в том, что я предполагал, что оператор Log.i("Id--(Handler)", String.valueOf(getLooper().getThread().getId())); будет записывать идентификатор потока ThreadOne, так как мы передаем петлитель потока в обработчик.Однако регистрируемый идентификатор относится к основному потоку.Это почему?Правильно ли считать, что handleMessage() выполняется в главном потоке?

1 Ответ

1 голос
/ 21 апреля 2019

Проблема с getLooper() методом ThreadOne.Метод возвращает myLooper () , связанный с потоком, вызвавшим метод.

Для возврата Looper , связанного с ThreadOne, я бы предложил следующую реализациюкласс:

public class ThreadOne extends Thread {
    private Looper mLooper = null;

    @Override
    public void run() {
        Looper.prepare();
        mLooper = Looper.myLooper();

        Looper.loop();
    }

    Looper getLooper() {
        return mLooper;
    }
}

Примечание! ThreadOne Looper равен null до его запуска.Вы не можете получить не null ссылку на него ранее.Вы должны проверить, работает ли поток , прежде чем вызывать метод getLooper().

PS Возможно, вы захотите пересмотреть подход с получением ThreadOne Looper .Возможно, достаточно иметь обработчик , связанный с ThreadOne ( см. Пример потока ).

...