Android Threading: этот класс Handler должен быть статическим, иначе могут возникнуть утечки [дубликаты]

Я использую объект handler для продолжения работы с пользовательским интерфейсом после завершения трудоемкой задачи в отдельном потоке. Была проблема с вышеупомянутым предупреждением Lint, и мой подход был следующим.

[ Образец объекта обработчика, тип 1 ] ->

Handler responseHandler = new Handler()
{
    @Override
    public void handleMessage(Message msg)
    {
        super.handleMessage(msg);
        Toast.makeText(MainActivity.this, "Finished the long running task in seperate thread...", Toast.LENGTH_LONG).show();
    }       
};

[ Образец объекта обработчика, тип 2 ] ->

Handler responseHandler = new Handler(new Handler.Callback() 
{       
    @Override
    public boolean handleMessage(Message msg) 
    {   
        Toast.makeText(MainActivity.this, "Finished long running task in a seperate thread...", Toast.LENGTH_LONG).show();
        return false;      // RETURN VALUE ????
    }
});

В отдельном потоке (кроме пользовательского интерфейса), когда выполняется трудоемкая задача, он выполняет следующую строку, чтобы вернуть управление потоку пользовательского интерфейса (в основном, объекту обработчика).

responseHandler.sendEmptyMessage(0);

Программа отлично работает с обоими типами объектов-обработчиков, но с 1-м типом я получаю предупреждение Lint о том, что Этот класс Handler должен быть статическим, иначе могут возникнуть утечки.

Поэтому я начал использовать второй тип объекта обработчика, чтобы избежать предупреждения Lint, но проблема в том, что я не уверен в значении возвращаемого значения (true/false) вторым способом. а также он работает с любым. Я так много искал это в Google, но не получил точного ответа, объясняющего это возвращаемое значение.

Да, я видел, что этот вопрос задавался во многих местах в stackoverflow, в основном в связи с предупреждением Lint, но мой вопрос в основном касается типа возвращаемого значения вторым способом и получения подтверждения, что все в порядке, как я решаю проблему, используя второй тип обработчика Obj.

Вопросы ->

1). Кто-нибудь знает, что именно означает это значение return (true/false)?

2). Правильно ли я сделал, чтобы избавиться от предупреждения о ворсе?

Спасибо...


person JibW    schedule 13.08.2013    source источник
comment
Да, проверьте связанный пост.   -  person Ivan Bartsov    schedule 13.08.2013
comment
Я видел эти ссылки, и мой вопрос в основном касается возвращаемого значения, где я не нашел объяснения в них.   -  person JibW    schedule 13.08.2013
comment
stackoverflow.com/questions/17899328/. проверьте это и это groups.google.com/forum/#!topic/ android-developers/1aPZXZG6kWk. проверьте обсуждение темы и решение Романа Гая.   -  person Raghunandan    schedule 13.08.2013


Ответы (2)


Каждый обработчик привязан к Looper потока, каждый Message помещается в структуру данных, очередь сообщений.

Message имеет переменную target, указывающую на Handler, и переменную callback, указывающую на Runnable.

Итак, если вы используете анонимный класс для создания объекта Handler (как в первом примере), знайте, что анонимные/нестатические внутренние классы содержат ссылку на внешние объекты (Activity?). Таким образом, сообщение, размещенное в очереди, может содержать ссылки на Handler в качестве цели, а Handler, в свою очередь, содержит ссылку на внешний класс, например Activity.

Теперь сообщение может оставаться в очереди сообщений в течение длительных интервалов времени, пока выполняется поток. Между тем, деятельность, возможно, была прекращена. Но это не будет сборщиком мусора из-за неясной косвенной ссылки на него, которая есть в сообщении. Обратите внимание, что Looper и Message Queue остаются, пока работает поток.

Во втором примере вы не создаете анонимный класс Handler. Вы используете конструктор обработчика и передаете ему анонимный объект Callback. Это может помешать Lint жаловаться, но я сомневаюсь, что это хороший подход. Просто избегайте внутренних классов, избегайте передачи Activity или контекстных ссылок в Handler.

Обновление:

Обработчик dispatchMessage() получает сообщения, которые должны быть обработаны, где он проверяет, был ли предоставлен обратный вызов, затем, если обратный вызов предоставлен, он не вызывает handleMessage(), если обратный вызов handleMessage() возвращает true:

public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg); //--won't be called if you return true.
    }
}
person S.D.    schedule 13.08.2013

Я нашел важную информацию об утечке памяти внутренним классом, например обработчиком, и хочу поделиться с вами:

Как получить утечку контекста: обработчики и внутренние классы И я думаю, что переопределенный метод класса Handler ничего не вернет, как вы можете проверить: handleMessage()

Вы переопределили класс Java Handler, а не Android Handler, вы можете видеть, что handleMessage() класса Java Handler имеет оператор возврата, и вы также можете проверить причину возврата здесь: логическое значение handleMessage (контекст C)

person Harish Godara    schedule 13.08.2013