Обработчик `handleMessage` возвращает идентификатор потока основного потока вместо идентификатора рабочего потока

Я пытаюсь освоить многопоточность в 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() выполняется в основном потоке?

Пожалуйста, пройдите через Android Looper, Handler и MessageQueue. Это даст вам ответ blog.mindorks.com/…

noobEinstien 21.04.2019 12:12

Основная причина в том, что вы создали обработчик внутри основного потока, поэтому этот обработчик всегда перехватывает сообщения, поступающие в основной поток.

Jasurbek 21.04.2019 12:12

@Jasurbek Но я передаю петлитель рабочего потока в обработчик. Разве обработчик не должен ассоциировать себя с работником в этом случае?

krtkush 21.04.2019 13:02

У меня пока нет ответа. Но я понял, что мой подход был неправильным - stackoverflow.com/questions/37671500/… Использование вашего подхода дает мне исключение нулевого указателя.

krtkush 21.04.2019 15:56
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
4
158
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Для возврата Лупер, связанного с 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 равен null, пока он не запущен. Вы не можете получить не-null ссылку на него ранее. Вы должны проверить, запущен ли поток перед вызовом метода getLooper().

P.S. Возможно, вы захотите пересмотреть подход к получению ЛуперThreadOne. Наличие Обработчик, связанного с ThreadOne, может быть достаточным (посмотреть пример треда).

Другие вопросы по теме