안 드 로 이 드 쓰레기 회수 메커니즘 메모리 유출 문제 해결

안 드 로 이 드 인 코딩 에서 간단 한 쓰기 와 인 코딩 습관 이 있 을 수 있 습 니 다.저희 코드 에 메모리 유출 문제 가 많 을 수 있 습 니 다.여기 서 잘못된 정 리 를 하 겠 습 니 다.
1.단일 사례 를 작성 할 때 자주 발생 하 는 오류.
오류 모드:

 public class Foo{

   private static Foo foo;

   private Context mContext;

   private Foo(Context mContext){

    this.mContext = mContext;

   }

   //     ,     

   public static Foo getInstance(Context mContext){

    if(foo == null)

     foo = new Foo(mContext);

    return foo;

   }

   public void otherAction(){

    mContext.xxxx();

    ….

   }

  }

오류 원인:
     만약 에 저희 가 Activity A 나 다른 곳 에서 Foo.getInstance()를 사용 할 때 저 희 는 항상'this'나'mContext'(이 변수 도 this 를 가리 키 는 것)를 손 쉽게 씁 니 다.생각해 보 세 요.현재 우리 가 사용 하고 있 는 Foo 는 하나의 예 입 니 다.초기 화 된 후에 메모리 와 계속 존재 하 는 것 을 의미 합 니 다.나중에 호출 할 때 이번 Foo 대상 을 만 들 지 않 습 니 다.그러나 Foo 의'mContext'변 수 는 항상 Activity A 의'Context'를 가지 고 있 기 때문에 Activity A 는 onDestroy 방법 을 실행 하 더 라 도 자신 을 소각 할 수 없습니다.그러나"applicationContext"는 다 릅 니 다.저희 애플 리 케 이 션 과 함께 존재 합 니 다.(중간 에 삭 제 될 수도 있 지만 자동 으로 reCreate 될 수도 있 습 니 다.)따라서 Foo 의"mContext"는 특정한 Activity 의 인용 을 가지 고 있어 서 소각 할 수 없 을 것 이 라 고 걱정 하지 않 아 도 됩 니 다.
올 바른 방식:   

 public class Foo{

   private static Foo foo;

   private Context mContext;

   private Foo(Context mContext){

    this.mContext = mContext;

   }

   //     ,     

   public static Foo getInstance(Context mContext){

    if(foo == null)

     foo = new Foo(mContext.getApplicationContext());

    return foo;

   }

   public void otherAction(){

    mContext.xxxx();

    ….

   }

  }

  

2.익명 내부 클래스 를 사용 할 때 자주 발생 하 는 오류
오류 모드:

 public class FooActivity extends Activity{

   private TextView textView;   



   private Handler handler = new Handler(){

    @override

    public void handlerMessage(Message msg){

     

    }

   };

   @override

   public void onCreate(Bundle bundle){

    super.onCreate(bundle);

    setContextView(R.layout.activity_foo_layout);

    

    textView = (TextView)findViewById(R.id.textView);

    

    handler.postDelayed(new Runnable(){

     @override

     public void run(){

       textView.setText(“ok”);

     };

    },1000 * 60 * 10);

   }

  }



오류 원인:
     FooActivity 의 finish 방법 을 실 행 했 을 때 지 연 된 메 시 지 는 처리 되 기 전에 메 인 스 레 드 메시지 큐 에 10 분 동안 존재 합 니 다.이 메시지 에는 Handler 의 인용 이 포함 되 어 있 습 니 다.Handler 는 익명 의 내부 클래스 의 인 스 턴 스 로 외부 FooActivity 의 인용 을 가지 고 있 기 때문에 FooActivity 를 회수 할 수 없습니다.이 로 인해 FooActivity 가 보유 한 많은 자원 을 회수 하지 못 해 메모리 유출 이 발생 했다.
     위의 new Runnable 을 주의 하 세 요.여기 도 익명 의 내부 클래스 로 이 루어 집 니 다.또한 FooActivity 의 인용 도 가지 고 있 고 FooActivity 가 회수 되 는 것 을 막 을 수 있 습 니 다.
     정적 익명 내부 클래스 인 스 턴 스 는 외부 클래스 의 인용 을 가지 고 있 지 않 습 니 다.
올 바른 방식:    

 public class FooActivity extends Activity{

   private TextView textView;

   

   private static class MyHandler extends Handler {

   private final WeakReference<FooActivity> mActivity;

   public MyHandler(FooActivity activity) {

    mActivity = new WeakReference<FooActivity>(activity);

   }

   @Override

   public void handleMessage(Message msg) {

    FooActivity activity = mActivity.get();

     if (activity != null) {

       // ...

     }

    }

   }

   private final MyHandler handler = new MyHandler(this);



   @override

   public void onCreate(Bundle bundle){

    super.onCreate(bundle);

    setContextView(R.layout.activity_foo_layout);

    

    textView = (TextView)findViewById(R.id.textView);

    

    handler.postDelayed(new MyRunnable(textView),1000 * 60 * 10);

   }



   private static class MyRunnable implements Runnable{

    private WeakReference<TextView> textViewWeakReference;

    

    public MyRunnable(TextView textView){

     textViewWeakReference = new WeakReference<TextView>(textView);

    }

     @override

     public void run(){

       final TextView textView = textViewWeakReference.get();

       if(textView != null){

        textView.setText("OK");

       }

     };

   }

  }

  

3.handler 를 사용 한 후에 onDestroy 에서 handler.removeCallbacks AndMessages(object token)를 기억 하 십시오.

 handler.removeCallbacksAndMessages(null);

  // removeCallbacksAndMessages,    null   ,         handler   Runnable Message,   onDestroy                 。

메모리 누 출 을 막 기 위해 개발 중 주의해 야 할 점:
  •      1.라 이 프 사이클 이 Activity 보다 긴 대상 이 Activity 의 인용 을 가지 게 하지 마 세 요
  •      2.Activity 가 아 닌 애플 리 케 이 션 의 Context 를 사용 하도록 한다
  •      3.Activity 에서 비정 상 내부 클래스 를 사용 하지 마 십시오.비정 상 내부 클래스 는 외부 클래스 인 스 턴 스 의 인용 을 암시 적 으로 가지 고 있 기 때 문 입 니 다.정적 내부 클래스 를 사용 하면 외부 인 스 턴 스 를 약 한 참조 로 사용 합 니 다
  •      4.쓰레기 수 거 는 메모리 유출 을 해결 하지 못 하고 안 드 로 이 드 의 쓰레기 수 거 메커니즘 을 이해한다
  • context 를 가 져 오 는 방법 과 context 와 applicationContext 를 사용 하 는 차이 점:
  •      1.View.getContext,현재 View 대상 의 Context 대상 을 되 돌려 줍 니 다.보통 현재 보 여 주 는 Activity 대상 입 니 다
  •      2.Activity.getapplicationContext,현재 Activity 가 있 는(응용)프로 세 스 의 Context 대상 을 가 져 옵 니 다.보통 Context 대상 을 사용 할 때 이 전역 프로 세 스 Context 를 우선 고려 해 야 합 니 다
  •      3,ContextWrapper.getBaseContext():ContextWrapper 를 가 져 와 장식 하기 전의 Context 를 사용 할 수 있 습 니 다.이 방법 은 실제 개발 에서 많이 사용 되 지 않 고 사용 하 는 것 을 권장 하지 않 습 니 다
  •      4.Activity.this 는 현재 Activity 인 스 턴 스 를 되 돌려 줍 니 다.UI 컨트롤 이 라면 Activity 를 Context 대상 으로 사용 해 야 하지만 기본 Toast 는 실제 applicationContext 를 사용 해도 됩 니 다

  •  여러분,일부 NO 에 숫자 가 추 가 된 것 을 주의 하 세 요.사실은 이런 것들 은 능력 적 으로 YES 인 데 왜 NO 라 고 하 죠?다음 설명:
         숫자 1:Activity 를 시작 하 는 것 은 이 클래스 에서 가능 하지만 새로운 task 를 만들어 야 합 니 다.일반적인 상황 은 추천 하지 않 습 니 다.
         숫자 2:이 클래스 에서 layot inflate 를 제거 하 는 것 은 합 법 적 이지 만 시스템 의 기본 테마 스타일 을 사용 합 니 다.어떤 스타일 을 사용자 정의 하면 사용 되 지 않 을 수도 있 습 니 다.
         숫자 3:receiver 가 null 일 때 4.2 이상 버 전에 서 점성 방송의 현재 값 을 가 져 올 수 있 습 니 다.(무시 해도 된다)
         주:ContentProvider,BroadcastReceiver 가 상기 표 에 있 는 이 유 는 내부 방법 에 context 가 사용 되 기 때 문 입 니 다.
         자,여기 서 표를 보 겠 습 니 다.Activity 와 Application 에 중심 을 두 고 볼 수 있 습 니 다.UI 와 관련 된 방법 은 기본적으로 애플 리 케 이 션 을 권장 하지 않 거나 사용 할 수 없습니다.그리고 앞의 세 가지 조작 은 애플 리 케 이 션 에 나타 날 수 없습니다.실제로 조금 만 파악 하면 UI 와 관련 된 모든 것 은 Activity 를 Context 로 처리 해 야 한다.다른 일부 조작,Service,Activity,Application 등 인 스 턴 스 는 모두 가능 합 니 다.물론 Context 참조 소지 에 주의 하여 메모리 누 출 을 방지 합 니 다.
    이상 은 본문의 전체 내용 이 므 로 여러분 의 학습 에 도움 이 되 기 를 바 랍 니 다.

    좋은 웹페이지 즐겨찾기