2015-01-08 2 views
1

У меня есть обработчик, который объявлен в главном потоке:Утечка памяти обработчика?

mainHandler = new Handler() { 

      @Override 
      public void handleMessage(Message msg) { 

       switch (msg.what) { 

        case 1: 

         Bundle bundle = msg.getData(); 
         mTextView.setText(bundle.getString("message")); 
         break; 

        . . . 

        default: 
         super.handleMessage(msg); 
         break; 
       } 
      } 
     }; 

Где mTextView представляет собой определенный TextView OnCreate().

У меня есть задача, которая используется в отдельной теме. В Runnable магазины mainHandler от основного потока и говорит ему отправлять сообщения:

public class SomeRunnable implements Runnable { 

    private Handler mHandler; 

    public SomeRunnable(Handler handler) throws IOException { 
     . . .  
     mHandler = handler; 
    } 

    @Override 
    public void run() { 

     while (!Thread.currentThread().isInterrupted()) { 
      try { 
        . . . 

        Message msg = mHandler.obtainMessage(); 
        . . . 
        mHandler.sendMessage(msg); 
       } 

      } catch (IOException e) { 
       Log.e("Error", e.hashCode() + ": " + e.getLocalizedMessage()); 
      } 
     } 
    } 

Я видел, что вы потенциально можете создать утечку памяти с помощью таких методов, как Handler#postDelayed() если класс Handler не является статичным. Но я использую Handler#sendMessage(), который мгновенно помещает сообщение в очередь сообщений.

Я все еще в опасности иметь утечку памяти? Даже с:

@Override 
    protected void onDestroy() { 
     super.onDestroy(); 

     mThread.interrupt(); 
     mainHandler.removeCallbacksAndMessages(null); 
    } 

Спасибо!

+0

Это не видно из кода, который вы в курсе, но делает ваш 'Handler' или' Runnable' проводить какие-либо ссылки на непреходящий объекты? Кроме того, вопреки тому, что вы, кажется, говорите, я ожидаю, что «статичный» обработчик будет более подвержен утечкам памяти, чем то, что я вижу выше. – 323go

+0

@ 323go мой Runnable «SomeRunnable» имеет тот же адрес, что и мой обработчик «mainHandler» из основного потока. Это то, что вы определяете как не-переходное? Мой обработчик не содержит ссылок, хотя он относится к TextView в основном потоке. – Zack

+0

Тогда вы можете сделать ссылку на 'mainHandler'' WeakReference', чтобы быть в безопасности. В противном случае похоже, что с тобой все будет в порядке. – 323go

ответ

0

Для решения всех случайностей, вы могли бы сделать mHandler в WeakReference, как показано ниже:

public class SomeRunnable implements Runnable { 

    private WeakReference<Handler> mHandlerRef; 

    public SomeRunnable(Handler handler) throws IOException { 
     . . .  
     mHandlerRef = new WeakReference<Handler>(handler); 
    } 

    @Override 
    public void run() { 

     while (!Thread.currentThread().isInterrupted()) { 
      try { 
        . . . 
        Handler mHandler = mHandlerRef.get(); 
        if(mHandler != null) { 
         Message msg = mHandler.obtainMessage(); 
         . . . 
         mHandler.sendMessage(msg); 
        } 
       } 

      } catch (IOException e) { 
       Log.e("Error", e.hashCode() + ": " + e.getLocalizedMessage()); 
      } 
     } 
    } 
} 
+1

Благодарим за предложение! Я посмотрю, как это повлияет на мое приложение, и я дам вам знать мое окончательное решение. – Zack

+0

должен mHandlerRef.получить(); вызывается каждый раз в цикле while или может выполняться за пределами цикла? – Zack

+0

Зависит от того, сколько работы вы выполняете в цикле или используете ли вы другие потоки там. «Запуск» будет выполняться вскоре после его публикации; единственной ситуацией, когда использование 'WeakReference' помогает, является то, что у вас есть длинный« Runnable », который вы хотите, чтобы иметь возможность прерывать/прерывать чистоту. – 323go

Смежные вопросы