2014-12-12 3 views
0

У меня есть AsyncTask, который мне нужно перезапустить, если пользователь выполняет настройки, такие как Switch Color.MemoryLeak trough onConfigurationChanged()

Когда он сделал так, я начинаю AsyncTask так:

myWorkerClass.clearMemory(); 
    myWorkerClass = new WorkerClass(getApplicationContext(), gv, searchbar, width, scaleButtonText); 
    myWorkerClass.execute(); 

В AsyncTask я добавить onTextChangeListener к моему EditText (который вызывает MemoryLeak позже!).

Для предотвращения MemoryLeaks у меня есть метод в моей AsyncTask который удаляет onTextChangedListener:

public void clearMemory() { 
    searchbar.removeTextChangedListener(myTextWatcher); 
} 

Все хорошо, за исключением, когда я повернуть мое устройство работает. Когда я повернуть мое устройство я сделать это только в onConfigurationChanged:

myWorkerClass.clearMemory(); 
      myWorkerClass = new WorkerClass(getApplicationContext(), gv, searchbar, width, scaleButtonText); 
      myWorkerClass.execute(); 

Как вы можете видеть, я сделать то же самое, как если изменяется пользователь цвет. Но на вращающемся устройстве я течет Память, при переключении Цвет я не!

Это после включения цвета:

enter image description here

Это после поворота экрана несколько раз (помните, я делать точно так же, как и при переключении цвета:

enter image description here

Это мои подозреваемые в утечке из кучи кучи:

enter image description here

enter image description here

Это мое доминатором дерево: enter image description here

Почему я знаю onTextChangeListener это проблема?

Потому что, если я комментирую добавление onTextChangedListener в свой EditText, все работает нормально. Нет утечек памяти.

Мой вопрос:

Почему утечка памяти Rotation Изменение и изменение цвета не когда я начать AsyncTask точно так же, как и делать точные те же вещи в AsyncTask?

Я искал немного: http://developer.android.com/guide/topics/resources/runtime-changes.html

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

Пожалуйста, поймите.Я не хочу публиковать весь свой код. Но я думаю, что это не обязательно в этом случае.

Я ценю любую помощь.

Заранее спасибо

ответ

0

Вращение должно сделать что-то другое, как создать новый вид деятельности из-за того, что создает новую ссылку на мой EditText.

именно он разрушает вашу текущую деятельность и создает новую. Если searchbar переменная член вашей AsyncTask затем рассмотреть вопрос сдачи его в WeakReference:

WeakReference<SearchBar> searchbarPtr; 

затем получить доступ с помощью searchBarPtr.get(), но проверить, если его нуль, если да, то это означает, что он был сборщиком мусора из-за конфигурации изменение.

Также не забудьте не сделать ваш AsyncTask внутренним классом вашей деятельности. Если он вложен, сделайте его статическим. В противном случае ваша asynctask будет ссылаться на вашу активность, и это предотвратит ее уничтожение - пока ее поток не закончится.

Несчастливо, что все это работает в любых ситуациях, может быть довольно сложным и трудоемким.

Надеюсь, никто не предложит предотвратить разрушение вашей деятельности с помощью андроида: configChanges, обеспечивающие правильное поведение вашей активности во время вращения, не позволит ей сбой/утечка в менее распространенных моментах жизненного цикла активности, которые не могут быть предотвращены андроидом: configChanges.

+0

Спасибо за ваш ответ. Да, я помещаю ссылку на мою панель поиска (из моей деятельности) в AsyncTask (что не является внутренним классом моей деятельности). Поэтому я никогда не работал с WeakReference, могу ли вы дать мне быстрое решение, как реализовать это? Я знаю, что это непросто из-за того, что я не предоставлял никакого кода. Но, может быть, мы сможем сделать это? В любом случае, если он GCing мой поиск, то мой 'clearMemory()' должен быть бесполезным право? Потому что, собирая панель поиска, он также собирает 'onTextChangeListener', правильно? – MMike

+0

@MMike Я добавил короткую псевдокодную презентацию использования WeakReference. Также в действии.onCreate вы можете обновить ссылку searchBar внутри вашей AsyncTask, но вам нужно будет каким-то образом ссылаться на вашу асинтезу, используя (устаревший) onRetainNonConfigurationInstance или новый aproach с сохраненными фрагментами. – marcinj

+0

Хм это слишком большой для меня, я попробую с WeakReference и поставлю WeakReference в AsyncTask и проверьте, не является ли оно нулевым. Если это null, мне нужно сделать новую ссылку на строку поиска справа и поместить ее снова в WeakReference, если это необходимо? – MMike

0

В андроиде вращение разрушает вашу текущую деятельность, чтобы начать новую.
Чтобы избежать этого, вы можете добавить android:configChanges="orientation|screenSize" в файл манифеста.

Ниже приведены советы, чтобы избежать утечки памяти об изменении вращения

  1. Не хранить долгоживущие ссылки на контекстно-активности (ссылка на деятельность должна иметь тот же жизненный цикл, как и сама деятельность)
  2. Попробуйте использовать контекстное приложение вместо контекстной активности
  3. Избегайте нестатических внутренних классов в действии, если вы не контролируете свой жизненный цикл, используйте статический внутренний класс и слабо ссылаетесь на активность внутри. Решение этой проблемы заключается в использовании статического внутреннего класса с WeakReference к внешнему классу, как это было сделано в ViewRoot и его W внутренний класс, например
  4. Сборщик мусора не является страхование от утечек памяти

Источник: Avoiding memory leaks

+0

Благодарим вас за отзыв «Ленивый ниндзя». Я передаю только ApplicationContext, мой AsyncTask не является внутренним классом моей активности, и моя единственная утечка памяти - это мой 'addTextChangeListener'' EditText's searchbar. Я не хочу избавляться от Вращения, я хочу избавиться от утечки. Но я не знаю, как это сделать. Нет ли метода, который вызывается до того, как действие будет уничтожено и воссоздано? UpDate: '=" orientation | screenSize "' не помогает. Я снова утешаю память! – MMike

+0

@MMike 'Нет метода, который вызывается до того, как действие будет уничтожено и воссоздано?', OnDestroy -> перед тем, как оно будет уничтожено, onCreate -> будет вызван для нового воссозданного действия. – marcinj