2015-06-13 1 views
3
This Handler class should be static or leaks may occur (null) 

Это «класс» это сообщение относится к «MyActivity» здесь, поскольку Handler - это объект, и я объявлял его статическим. Должен ли я игнорировать его или там что-то, что я должен добавить, например «статический» где-нибудь в объявлении «MyActivity» (я пробовал это и получал ошибки). Я замечаю, что «WeakReference» часто предлагается для этого предупреждения.Этот класс обработчика должен быть статическим или может произойти утечка (0)

public class MyActivity extends Activity{ 
... 
static Handler handler; 
... 
handler = new Handler() 
    { 
    public void handleMessage(Message msg) { 
+1

Нет, если вы создаете экземпляр класса внутреннего обработчика, вы должны сделать класс статическим, чтобы избежать утечек. Прямо сейчас вы используете конструктор класса по умолчанию, который не является статичным, вы можете создать свой собственный внутренний класс, который расширяет обработчик и статично, чтобы исправить предупреждение. – zgc7009

+1

существует риск «утечки (может произойти)», только если вы используете какое-либо «замедленное» выполнение, и вы не опорожняете очередь сообщений в конце – pskink

ответ

21

так обработчиком является объектом и я сделал объявить его статическим

Вы заявили членданных, чтобы быть статическим. Тем не менее, вы используете анонимный внутренний класс, и поэтому ваш подкласс Handler не является static.

Вместо:

handler = new Handler() { 
    public void handleMessage(Message msg) { 
     // do cool stuff 
    } 
    }; 

использование:

handler=new MyVeryOwnHandler(); 

где MyVeryOwnHandler либо обычный класс Java или static внутренний класс:

private static class MyVeryOwnHandler extends Handler { 
    public void handleMessage(Message msg) { 
     // do cool stuff 
    } 
}; 

Обратите внимание, что ошибка в том, что класс необходимо be static; он не говорит, что объект должен быть static.

+0

Спасибо за краткое объяснение ошибки в этом случае и пример того, что я должен делать. Я нахожу, что один из элегантных примеров стоит тысячи слов.Я добавил, что «Модификатор статический не разрешен здесь» при попытке добавить «частный» или «статический», но просто используя «класс MyVeryOwnHandler extends Handler» работал и избавился от предупреждения об утечках. – Androidcoder

+1

@michael: Если 'MyVeryOwnHandler' является собственным классом Java верхнего уровня, в файле' MyVeryOwnHandler.java' вам не понадобится (или будет разрешено использовать) 'private' или' static'. Если, однако, 'MyVeryOwnHandler' является внутренним классом' MyActivity', тогда 'private' и' static' становятся актуальными. – CommonsWare

+0

Это не позволяет мне использовать «static» или «private» при объявлении MyHandler в onCreate моего основного действия, хотя просто создание нового класса без «private» или «static» устраняет предупреждение об ошибке. Я нашел интересную статью об этом здесь: http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html, хотя их решение было более сложным. Объявление класса за пределами onCreate неудобно, так как мой обработчик имеет дело с adview, inappPurchasing, межстраничные объявления, таблицы лидеров и т. Д., Которые должны быть обновлены статическими, а некоторые методы не распознаются. – Androidcoder

3

Во избежание утечек я также перенесен в статический вложенный класс. Объяснение из Android Studio говорит, что это, это могло бы помочь:

Поскольку этот обработчик объявлен как внутренний класс, он может предотвратить внешний класс от сборщика мусора. Если обработчик использует Looper или MessageQueue для потока, отличного от основного потока, то нет проблем. Если обработчик использует Looper или MessageQueue основного потока, вам необходимо исправить объявление обработчика, как следует из : Объявить обработчик как статический класс; Во внешнем классе создает экземпляр WeakReference во внешнем классе и передает этот объект в ваш обработчик при создании экземпляра обработчика; Сопоставьте все ссылки на членов внешнего класса с использованием объекта WeakReference.

Перед переносом я использовал реализацию потока Looper, как это было предложено developer.android.com, что в конце приводит к предупреждению. * царапины

class LooperThread extends Thread { 
    public Handler mHandler; 

    public void run() { 
     Looper.prepare(); 

     mHandler = new Handler() { 
      public void handleMessage(Message msg) { 
       // process incoming messages here 
      } 
     }; 

     Looper.loop(); 
    } 
}