나는이 문제를 몇 달 동안 조사했으며 다른 해결책을 생각해 냈습니다. 모두 큰 해킹이기 때문에 만족스럽지 않습니다. 디자인에 결함이있는 클래스가 프레임 워크에 만들었고 아무도 그것에 대해 이야기하고 있지 않다는 것을 여전히 믿을 수 없으므로 뭔가 빠진 것 같아요.
문제는입니다 AsyncTask
. 문서에 따르면
"스레드 및 / 또는 핸들러를 조작 할 필요없이 백그라운드 작업을 수행하고 UI 스레드에 결과를 게시 할 수 있습니다."
그런 다음 예제는에서 예제 showDialog()
메소드가 어떻게 호출 되는지 계속 보여줍니다 onPostExecute()
. 그러나 대화 상자를 표시하려면 항상 유효한 참조가 필요하고 AsyncTask 는 컨텍스트 객체에 대한 강력한 참조를 보유해서는 안되기 때문에 이것은 전적으로 나에게 부여 된 것처럼 보입니다 .Context
그 이유는 분명합니다. 활동이 파괴되어 작업을 시작하면 어떻게됩니까? 예를 들어 화면을 뒤집었기 때문에 항상 이런 일이 발생할 수 있습니다. 태스크를 만든 컨텍스트에 대한 참조를 유지한다면, 당신은 단지 쓸모 컨텍스트 개체 (윈도우가 파괴 된 것이며에 들고하지 않는 모든 UI 상호 작용 예외와 함께 실패합니다!), 당신은도를 만드는 위험 메모리 누수.
내 논리가 여기에 결함이 없다면, 이것은 다음과 같이 번역됩니다. onPostExecute()
문맥에 액세스 할 수없는 경우이 메소드가 UI 스레드에서 실행되는 것이 좋기 때문에 전혀 쓸모가 없습니다. 여기서 의미있는 일은 할 수 없습니다.
한 가지 해결 방법은 컨텍스트 인스턴스를 AsyncTask가 아니라 인스턴스로 전달하는 것 Handler
입니다. 작동 : 처리기는 컨텍스트와 작업을 느슨하게 바인딩하므로 누출 위험없이 메시지를 교환 할 수 있습니다 (오른쪽?). 그러나 그것은 AsyncTask의 전제, 즉 처리기를 귀찮게 할 필요가 없다는 것이 잘못되었음을 의미합니다. 동일한 스레드에서 메시지를 보내고 받고 있기 때문에 Handler를 학대하는 것처럼 보입니다 (UI 스레드에서 메시지를 작성하고 UI 스레드에서 실행되는 onPostExecute ()에서 메시지를 전송 함).
그 해결 방법을 사용하더라도 상황이 파괴 될 때 발생하는 작업에 대한 기록 이 없다는 문제가 여전히 있습니다 . 즉, 컨텍스트를 다시 만들 때 (예 : 화면 방향 변경 후) 작업을 다시 시작해야합니다. 이것은 느리고 낭비입니다.
이것에 대한 나의 해결책 ( Droid-Fu 라이브러리에서 구현 됨 )은 WeakReference
고유 한 응용 프로그램 객체의 구성 요소 이름에서 현재 인스턴스 로 의 매핑을 유지하는 것입니다 . AsyncTask가 시작될 때마다 해당 맵에 호출 컨텍스트를 기록하고 모든 콜백에서 해당 맵핑에서 현재 컨텍스트 인스턴스를 가져옵니다. 당신은 오래된 컨텍스트 인스턴스를 참조하지 않을 것을이 보장하지만 그리고 당신이 거기에 의미있는 UI 작업을 할 수 있도록 항상 콜백에 유효한 컨텍스트에 액세스 할 수 있습니다. 참조가 약하고 주어진 구성 요소의 인스턴스가 더 이상 존재하지 않으면 지워지기 때문에 누출되지 않습니다.
여전히 복잡한 해결 방법이며 일부 Droid-Fu 라이브러리 클래스를 서브 클래스 화해야하므로이 방법이 상당히 방해가됩니다.
이제 나는 단순히 알고 싶어합니다. 방금 큰 무언가가 누락되었거나 AsyncTask가 실제로 완전히 결함이 있습니까? 당신의 경험은 어떻게 작동합니까? 이 문제를 어떻게 해결 했습니까?
입력 해 주셔서 감사합니다.