2017-02-08 2 views
2

Я пытаюсь использовать класс WeakReference, чтобы предотвратить утечку памяти в Android.WeakReference: ссылка уничтожена в течение «секунд»

Я разработал Bluetooth API, который позволяет двум устройствам Android общаться (клиент и сервер) с помощью Android Bluetooth SDK.

Этот API доступен в общей библиотеке (так что оба приложения имеют доступ к одному и тому же коду).

Проблема в том, что ссылка внутри моих слабых ссылок уничтожается в считанные секунды. Я попытался использовать пользовательский ReferenceQueue, но ни один из его методов не называется!

Глядя на использование ОЗУ обоих устройств Android, я не вижу ничего страшного: очень низко, очень стабильно, потому что у меня есть отдельная активность с несколькими видами.

Я думал, что WeakReference должен хранить ссылки на мои действия, если они не получают сбор мусора (это означает, что ссылки больше нет). Я ошибаюсь ?


[EDIT 1]

Чтобы предоставить дополнительные разъяснения, я буду публиковать некоторые теоретические код, который должен представлять собой то, что я пытаюсь сделать.

Класс BluetoothAPI

private WeakReference<BluetoothStateListener> stateListener; 

public final void setProgressListener(@Nullable BluetoothProgressListener progressListener) { 

     this.progressListener = new WeakReference<>(progressListener, new Ref<>(context)); 
    } 

private synchronized void notifyProgress(final float percent) { 
     if (this.progressListener != null) { 
      final BluetoothProgressListener listener = this.progressListener.get(); 
      if (listener != null) { 
       UIAccess.runOnUiThread(new Runnable() { 
        public final void run() { 
         listener.onProgress(percent); 
        } 
       }); 
      } else { 
       Log.d(TAG, "Progress Listener is null!"); 
      } 
     } 
    } 

класса Activity A, внутри onCreate()

this.btAPI.setProgressListener(new BluetoothProgressListener() { 
      @UiThread 
      public final void onProgress(final float percent) { 
       final int progress = Math.round(percent * 10); 
       progressBar.setProgress(progress); 
       progressLabel.setText(getString(R.string.main_act_progress_status_tv_incoming, progress/10)); 
      } 
     }); 

При получении данных, мой прогрессбар никогда не обновляется, потому что BluetoothProgressListener всегда нулевой. Что оправдывает это?

+0

Пожалуйста, отобразите код. – Fildor

+1

Нет сильной ссылки анонимному слушателю. Так что это будет GC'd. Ожидаемое поведение. – Fildor

+0

Как насчет «SoftReference»? Если активность будет уничтожена, GC собирает мои анонимные ссылки для слушателей в адресных ссылках? – Mackovich

ответ

1

WeakReference в Android не ждёт следующих garbage collection цикл и уничтожить себя в тот момент, когда active and hard reference держится за них.

Поэтому вам необходимо реорганизовать ваш код и не использовать WeakReference как cache.

+2

Какова ссылка на утверждение, что они уничтожают себя без цикла GC? – Lucero

+0

В моем случае мой интерфейс Bluetooth API позволяет получать уведомления об изменении состояния (связанные, отключенные и т. Д.) И о прогрессе (когда данные отправляются или принимаются). Поэтому во всех этих случаях мои действия регистрируются с помощью анонимного класса. Когда вызывающие вызовы запускаются, пользовательский интерфейс обновляется, чтобы отражать события данных. Таким образом, эти реализации сохраняются внутри WeakReferences.Я хотел бы понять, почему эти реализации быстро уничтожаются. Я делаю что-то неправильно ? – Mackovich

+0

«Итак, эти реализации сохраняются внутри WeakReferences». - Как ты это делаешь? – Fildor