Да, ваша реализация, безусловно, вызовет утечку памяти (я просто столкнулся с этим сам).
Проблема в том, что вы создали круговую ссылку. Вы объявили свой runnable как нестатический внутренний класс, а это означает, что он автоматически сохранит ссылку на активность. Сама runnable является переменной-членом вашей активности, которая закрывает круг. Сборщик мусора никогда не сможет освободить эти объекты, так как всегда будет живая ссылка.
Использование статического внутреннего класса со слабым отношением к действию является самым безопасным способом устранения проблемы. You can see a great code example here. Если mainHandler - еще один нестатический внутренний класс, он создаст вторую круговую ссылку по тем же причинам, поэтому вам придется делать то же самое.
Установка mainHandler.removeCallbacksAndMessages(null);
и thread.randomAlienFire = null;
также может работать, но вы должны быть очень осторожны, когда вы помещаете этот код. Возможно, код идет по другому пути, чем вы ожидаете в некоторых случаях, и пропускаете эти вызовы? This blog post describes someone else's very similar experience with that approach.
В моем случае я использовал исполняемые анимации последовательности для ImageViews. чтобы избавиться от утечек памяти, я создал статический класс runnable, чтобы избежать циклической ссылки. Этого было недостаточно для меня, я также обнаружил, что выталкиваемый по-прежнему сохраняет ссылку на мой фрагмент. вызвав myImageView.removeCallbacksAndMessages(arrowAnimationRunnable);
в onDestroy() в моем фрагменте, наконец, решила утечку. здесь было мое решение:
public class MyFragment extends SherlockFragment {
public static class SafeRunnable implements Runnable {
private final WeakReference<MyFragment> parentReference;
public SafeRunnable(MyFragment parent) {
parentReference = new WeakReference<MyFragment>(parent);
}
@Override
public void run() {
if (parentReference != null) {
final MyFragment parent = parentReference.get();
if (parent != null) {
runWithParent(parent);
}
}
}
public void runWithParent(MyFragment parent) {
}
}
// This anonymous instance of the new runnable class does not retain a
reference to the fragment
private Runnable arrowAnimationRunnable = new SafeRunnable(this) {
@Override
public void runWithParent(MyFragment parent) {
// ... animation code
// repeat the animation in 1 second
parent.myImageView.postDelayed(this, 1000);
}
};
private ImageView myImageView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.my_layout, container, false);
// find the image view and kick off the animation after 1 second
myImageView = (ImageView) view.findViewById(R.id.iv_arrow);
myImageView.postDelayed(arrowAnimationRunnable, 1000);
return view;
}
@Override
public void onDestroyView() {
super.onDestroyView();
// It's necessary to remove the callbacks here, otherwise a message will
// be sitting in the queue and will outlive the fragment. Because a
// reference in that message will still be pointing to the fragment, the
// fragment (and everything else) will not be garbage collected
myImageView.removeCallbacks(arrowAnimationRunnable);
}
}
какие вычисления вы выполняете внутри обработчика. что может вызвать утечку памяти – Raghunandan
вычислений не было бы. Это можно сделать в целом интересным о – MikeT
из того, что я вижу, я не вижу ничего, что вызывает утечку памяти. http://android-developers.blogspot.in/2009/01/avoiding-memory-leaks.html – Raghunandan