Notice
                              
                            
                          
                        
                          
                          
                            Recent Posts
                            
                        
                          
                          
                            Recent Comments
                            
                        
                          
                          
                        반응형
    
    
    
  오늘도 공부
[펌]Android 개발가이드 - View에 할당한 리소스 완전히 해제하기 본문
반응형
    
    
    
  앞선 포스트 Android 개발가이드 - Bitmap.recycle()은 가급적 호출해 주는 편이 좋다. 에서는 명시적인 오브젝트 해제의 필요성을 알아보았다. VM 을 사용하는 언어에서 코딩함에도, c 스타일의 리소스 해제를 왜 해주어야 하는지에 대한 내용이었다. (안드로이드 프레임웍의 문제 및 특수성, 한정적인 VM Heap size 와 같은 이유 등)
그러나 안드로이드의 내부 동작으로 인해 Bitmap.recycle() 과는 별개로 view 에서의 메모리 누수 위험은 항상 잠재해 있다(자세한 내용은 안드로이드 내부 구현에 대한 이야기로 이어져야 하므로 생략). 결국 가장 안전한 방법은, view 에 할당된 모든 것을 초기화 해 버리는 것이다.
그럼 어떻게 할 것인가? 화면에 보이는 수많은 뷰들에 대해 일일히 null을 할 것인가?
이 점에 착안하여 아래와 같은 지저분한 트릭을 고안해 보았다.
왜 지저분하냐면, 정리 과정에 어느 정도의 성능 저하가 우려되기 때문이다.
주요 성능저하의 원인은 반복되는 재귀 호출 및 Root View 부터의 완전 트리 탐색 로직 때문이다.
게다가 마지막의 System.gc() 콜은 설명이 필요없이 지저분하다. (자세한 내용은 API 문서 참고 http://developer.android.com/reference/java/lang/System.html#gc() - GC호출은 GC를 보장하지 않음)
그러므로 가벼운 앱에서는 이 내용은 고민하지 않아도 무방하다.
View 갯수가 많은 화면을 Tab 혹은 ViewFlipper 등으로 구현한 경우와 같이,
메모리가 절박한 경우라면 이 트릭이 도움이 될 것이다.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | import android.app.Activity; import android.graphics.Bitmap;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;import android.view.View;import android.view.ViewGroup;import android.webkit.WebView;import android.widget.ImageView;/*** Utility class to help unbinding resources consumed by Views in Activity.* * @author Hwan Jo(nimbusob@gmail.com)*/public class ViewUnbindHelper {/*** Removes the reference to the activity from every view in a view hierarchy* (listeners, images etc.). This method should be called in the onDestroy() method immediately which are consumed by Views and this leads to* * @param view View to free from memory*/public static void unbindReferences(View view) {try {if (view != null) {unbindViewReferences(view);if (view instanceof ViewGroup) {unbindViewGroupReferences((ViewGroup)view);} }} catch (Exception ignore) {/* whatever exception is thrown just ignore it because a crash isalways worse than this method not doing what it's supposed to do*/}}/*** Removes the reference to the activity from every view in a view hierarchy* (listeners, images etc.). This method should be called in the onDestroy() method immediately which are consumed by Views and this leads to* * @param view View to free from memory*/publicstaticvoidunbindReferences(Activity activity, intviewID) {try{View view = activity.findViewById(viewID);if(view != null) {unbindViewReferences(view);if(view instanceofViewGroup) {unbindViewGroupReferences((ViewGroup)view);}}} catch(Exception ignore) {/* whatever exception is thrown just ignore it because a crash isalways worse than this method not doing what it's supposed to do.*/}}privatestaticvoidunbindViewGroupReferences(ViewGroup viewGroup) {intnrOfChildren = viewGroup.getChildCount();for(inti = 0; i < nrOfChildren; i++) {View view = viewGroup.getChildAt(i);unbindViewReferences(view);if(view instanceofViewGroup) {unbindViewGroupReferences((ViewGroup)view);}}try{viewGroup.removeAllViews();} catch(Exception ignore) {// AdapterViews, ListViews and potentially other ViewGroups don't support the removeAllViews operation}}privatestaticvoidunbindViewReferences(View view) {// Set everything to null (API Level 8)try{view.setOnClickListener(null);} catch(Exception ignore) {}try{view.setOnCreateContextMenuListener(null);} catch(Exception ignore) {}try{view.setOnFocusChangeListener(null);} catch(Exception ignore) {}try{view.setOnKeyListener(null);} catch(Exception ignore) {}try{view.setOnLongClickListener(null);} catch(Exception ignore) {}try{view.setOnClickListener(null);} catch(Exception ignore) {}try{view.setTouchDelegate(null);} catch(Exception ignore) {}Drawable d = view.getBackground();if(d != null) {try{d.setCallback(null);} catch(Exception ignore) {}}if(view instanceofImageView) {ImageView imageView = (ImageView)view;d = imageView.getDrawable();if(d != null) {d.setCallback(null);}if(d instanceofBitmapDrawable) {Bitmap bm = ((BitmapDrawable)d).getBitmap();bm.recycle();}imageView.setImageDrawable(null);} elseif(view instanceofWebView) {((WebView)view).destroyDrawingCache();((WebView)view).destroy();}try{view.setBackgroundDrawable(null);} catch(Exception ignore) {}try{view.setAnimation(null);} catch(Exception ignore) {}try{view.setContentDescription(null);} catch(Exception ignore) {}try{view.setTag(null);} catch(Exception ignore) {}}} | 
위 코드를 Activity 화면의 onDestroy 에서 호출해 주면 확실히 메모리 절약 효과가 있다. 우리가 미처 신경쓰지 못한 내부 callback 등까지 확실히 제거해 주므로 View 가 올바른 GC의 대상이 되기 때문이다
반응형
    
    
    
  'Android > Tip&Tech' 카테고리의 다른 글
| [펌]Android BitmapFactory.Options 설명 (0) | 2013.06.18 | 
|---|---|
| [펌] 나인패치 자동 생성 (0) | 2013.06.14 | 
| 해상도 지원 (1) | 2013.06.03 | 
| Android Samsung Spen Sdk API (1) | 2013.01.10 | 
| [펌] JSP 에서 엑셀 다운로드 받기 (0) | 2012.11.12 | 
