2

잘 알려진 소스 AsyncTasks는 액티비티에 대한 참조를 보유되어, 예를 들면, 내부 클래스로서 태스크를 선언 할 때 :활동 내의 내부 클래스를 수용 할 수 없습니까? 메모리 누수

public class MyActivity extends Activity { 

     ... 

     private class MyTask extends AsyncTask<Void, Void, Void> { 
      ... 
     } 
    } 

때문에 연관된 배경 스레드 (또는 스레드 풀)가, 쓰레드가 실행되고있는 한, 활동에 대한 참조는 활동이 닫히더라도 유지됩니다.

이제 내가 틀렸을 때 나를 고쳐주세요. 작업이 완료되면 활동을 다시 수집 할 수 있습니다.

  • 보다 Runnable는 내부 클래스로 정의하고, 핸들러에 의해 메인 스레드에 게시 :

    나는 거기에 활동을했습니다.

  • TimerTasks는 내부 클래스로 정의됩니다.

나는 메모리 누수 그냥 타이머를 취소하고 핸들러에 removeCallbacks를 호출 방지 수 있을까요?

예 :

public class MyActivity extends Activity { 
     Handler handler; 
     Timer timer; 


     @Override 
     public void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 

      handler = new Handler(); 
      timer = new Timer(); 

      handler.postDelayed(new MyRunnable(), 10000); 
      timer.schedule(new MyTimerTask(), 1000); 
     } 

     @Override 
     protected void onDestroy() { 
      super.onDestroy(); 

      handler.removeCallbacksAndMessages(null); 
      timer.cancel(); 
      handler = timer = null; 
     } 

     private class MyTimerTask extends TimerTask { 
      ... 
     } 

     private class MyRunnable implements Runnable { 
      ... 
     } 
    } 

나는 현재에서 일하고 있어요 프로젝트에서 이러한 활동을 보았다, 나는이 내부 클래스는 정적하고 활동에있는 WeakReferences를 추가 할 리팩토링 고려 중이 야 .
문제는 내부 클래스가 액티비티의 private 변수와 메서드에 대한 액세스 권한을 갖고 있으며 정적 변수로 변경하면 액티비티 클래스에있는 멤버의 액세스 한정자를 private에서 package-default로 변경해야하기 때문에 내부 클래스가 편리하다는 것입니다. 동일한 패키지의 다른 클래스에서 사용할 수 있도록합니다. 이것은 또한 액티비티 내에 package-default 인 메소드가 있고 그 대칭 함수가 여전히 private이기 때문에 대칭을 깨뜨린다. (예를 들어, 지금은 정적 클래스에서 액티비티의 stopFoo 메소드를 사용할 수 있어야한다. startFoo으로 무엇을해야합니까? 그 클래스에서 호출되지 않았습니까?). 그리고 액티비티에서 액세스해야하는 변수는 무엇입니까? 지금 게터를 제공해야합니까?
약한 참조를 액티비티에 추가하면 리팩토링 된 정적 클래스에서 많은 수의 null 검사가 수행되므로 액티비티가 여전히 주변에있는 경우에만 작동합니다. 이 외에도 약한 참조 방법은 회사의 숙련되지 않은 프로그래머가 이해하기 어려울 수 있습니다. (또한 실제로 필요하지 않으면 어디서나 사용하기 시작할 수 있습니다.)

요약하면 리팩터링 된 활동은보기 흉한 반면 이전 사례는 깔끔합니다. 그래서 내부 클래스 기반 설계가 수용 가능한지, 활동이 끝났을 때 runnable 또는 timer 태스크가 잠깐 동안 실행되도록 남겨 두어도 상관하지 않는다는 사실을 알고 있는지 궁금합니다. 이제

+0

정적이 아닌 내부 클래스를 피하십시오. 링크를 스크롤하고 포인트를 살펴보십시오. http://android-developers.blogspot.in/2009/01/avoiding-memory-leaks.html – Raghunandan

답변

2

(내가 틀렸다면 저를 정정), 작업이 완료되면, 활동이 다른 아무것도에 대한 정적 참조가 없다고 가정,

올바른 수집을 위해 다시 사용할 수 있습니다 그것.

타이머를 취소하고 핸들러에서 removeCallbacks를 호출하면 메모리 누수가 방지 될 수 있습니까?

이러한 단계를 수행하면 도움이됩니다. 또한, 어쨌든 그것을해야합니다 - 당신이 그것을 멈추지 않는 한 당신의 Timer이 마술처럼 멈추는 것처럼 아닙니다. 활동이

을 통해 그리고 메모리 관리의 관점에서, 당신의 인수가 소리 때 실행 가능한 또는 타이머 작업이 짧은 시간 동안 실행중인 경우 정말 상관 없어

. "비 정적 내부 클래스를 피하십시오"는 좋은 기본 설계 기준이지만 절대적인 것은 아닙니다.

그러나 IMHO, 실제 문제는 메모리 관리가 아니라 구성이 변경됩니다. 사용자가 화면을 회전하고 언어를 변경하고 장치를 차량 도크에 넣으면 활동이 파괴되고 재생성됩니다. 그러나 아마도 작업의 작업은 여전히 ​​필요하지만 잘못된 활동 인스턴스와 대화 할 것입니다. 보존 된 단편을 사용하여 이러한 작업을 관리하면이 문제를 해결하는 데 도움이됩니다.

+0

응답 해 주셔서 감사합니다. 내 특별한 경우에 내부 Runnables와 TimerTasks가 실제로 수명이 짧으며, 이미 활동 레크리에이션/파괴를 염두에두고 구현되었음을 분명히하고자합니다. 그래서 제 관심은 메모리 누수입니다. –