[android] 장기 실행 작업을위한 Android AsyncTask

여기 에있는 AsyncTask에 대한 문서를 인용하면 다음과 같습니다.

AsyncTasks는 짧은 작업 (최대 몇 초)에 이상적으로 사용되어야합니다. 스레드를 장기간 실행해야하는 경우 다음과 같이 java.util.concurrent pacakge에서 제공하는 다양한 API를 사용하는 것이 좋습니다. Executor, ThreadPoolExecutor 및 FutureTask.

이제 내 질문이 생깁니다. 왜? 이 doInBackground()함수는 UI 스레드에서 실행되므로 여기서 장기 실행 작업을 수행하면 어떤 해가 있습니까?



답변

매우 좋은 질문입니다. Android 프로그래머로서 문제를 완전히 이해하려면 시간이 걸립니다. 실제로 AsyncTask에는 관련된 두 가지 주요 문제가 있습니다.

  • 활동 수명주기와 잘 연결되어 있지 않습니다.
  • 그들은 매우 쉽게 메모리 누수를 만듭니다.

내부 RoboSpice (동기 부여 응용 프로그램 Google Play에서 사용할 수 ) 우리는 세부에서 그 질문에 대답. AsyncTasks, 로더, 기능 및 단점에 대한 심층적 인보기를 제공하고 네트워크 요청에 대한 대체 솔루션 인 RoboSpice를 소개합니다. 네트워크 요청은 Android의 일반적인 요구 사항이며 본질적으로 장기 실행 작업입니다. 다음은 앱에서 발췌 한 것입니다.

AsyncTask 및 활동 수명주기

AsyncTask는 활동 인스턴스의 수명주기를 따르지 않습니다. 활동 내에서 AsyncTask를 시작하고 장치를 회전하면 활동이 파괴되고 새 인스턴스가 생성됩니다. 그러나 AsyncTask는 죽지 않을 것입니다. 완료 될 때까지 계속 살아갑니다.

완료되면 AsyncTask는 새 활동의 UI를 업데이트하지 않습니다. 실제로 더 이상 표시되지 않는 활동의 이전 인스턴스를 업데이트합니다. 이로 인해 java.lang.IllegalArgumentException 유형의 예외가 발생할 수 있습니다. 예를 들어, 활동 내에서보기를 검색하기 위해 findViewById를 사용하는 경우 창 관리자에보기가 첨부되지 않습니다.

메모리 누수 문제

AsyncTask를 활동의 내부 클래스로 만드는 것은 매우 편리합니다. AsyncTask는 작업이 완료되거나 진행 중일 때 Activity의 뷰를 조작해야하므로 Activity의 내부 클래스를 사용하는 것이 편리해 보입니다. 내부 클래스는 외부 클래스의 모든 필드에 직접 액세스 할 수 있습니다.

그럼에도 불구하고 내부 클래스는 외부 클래스 인스턴스 인 Activity에 대해 보이지 않는 참조를 보유 할 것임을 의미합니다.

장기적으로 이로 인해 메모리 누수가 발생합니다. AsyncTask가 오래 지속되면 활동이 “살아있는”상태를 유지하는 반면 Android는 더 이상 표시 할 수 없기 때문에이를 제거하려고합니다. 활동은 가비지 수집 될 수 없으며 Android가 기기의 리소스를 보존하는 중심 메커니즘입니다.


장기 실행 작업에 AsyncTasks를 사용하는 것은 정말 매우 나쁜 생각입니다. 그럼에도 불구하고 1 ~ 2 초 후에 View를 업데이트하는 것과 같이 수명이 짧은 경우에는 괜찮습니다.

RoboSpice Motivations 앱 을 다운로드하는 것이 좋습니다.이 은이를 심층적으로 설명하고 일부 백그라운드 작업을 수행하는 다양한 방법에 대한 샘플 및 데모를 제공합니다.


답변

왜 ?

때문에 AsyncTask, 기본적으로 스레드 풀 사용 하면 만들지 않은가 . 풀의 요구 사항이 무엇인지 모르기 때문에 생성하지 않은 풀의 리소스를 묶지 마십시오. 그리고 여기에있는 경우처럼 해당 풀에 대한 문서에서하지 말라고 지시하는 경우 생성하지 않은 풀의 리소스를 묶지 마십시오.

특히, 안드로이드 3.2에서 사용하는 스레드 풀로 시작하는 AsyncTask(와 애플 리케이션을 위해 기본적으로 android:targetSdkVersion단지가 13 이상으로 설정) 무기한이 스레드를 묶어 경우, 다른 작업을 하나도 실행되지 않습니다 – 그것은 스레드를.


답변

Aysnc 작업은 여전히 ​​앱 GUI와 함께 사용되지만 UI 스레드의 리소스가 많은 작업을 유지하는 특수 스레드입니다. 따라서 목록 업데이트, 뷰 변경 등과 같은 작업에서 가져 오기 작업 또는 업데이트 작업을 수행해야하는 경우 이러한 작업을 UI 스레드에서 제외 할 수 있도록 비동기 작업을 사용해야하지만 이러한 작업은 여전히 ​​UI에 연결되어 있습니다. .

UI 업데이트가 필요하지 않은 장기 실행 작업의 경우 UI 없이도 살 수 있기 때문에 서비스를 대신 사용할 수 있습니다.

따라서 짧은 작업의 경우 생성 활동이 종료 된 후 OS에 의해 종료 될 수 있으므로 비동기 작업을 사용하십시오 (보통 작업 중에는 종료되지 않지만 작업을 완료합니다). 길고 반복적 인 작업에는 대신 서비스를 사용하십시오.

자세한 내용은 스레드 참조 :

몇 초 이상 AsyncTask?

AsyncTask는 활동이 파괴 된 경우에도 중지되지 않습니다.


답변

AsyncTask의 문제점은 활동의 비 정적 내부 클래스로 정의 된 경우 활동에 대한 참조가 있다는 것입니다. 비동기 작업의 컨테이너가 작업을 완료하지만 AsyncTask의 백그라운드 작업이 계속되는 시나리오에서 작업 개체는 참조가 있기 때문에 가비지 수집되지 않으므로 메모리 누수가 발생합니다.

이를 해결하는 해결책은 비동기 작업 을 활동의 정적 내부 클래스로 정의 하고 컨텍스트에 대한 약한 참조를 사용하는 것입니다.

그러나 여전히 간단하고 빠른 백그라운드 작업에 사용하는 것이 좋습니다. 깨끗한 코드로 앱을 개발하려면 RxJava 를 사용 하여 복잡한 백그라운드 작업을 실행하고 그 결과로 UI를 업데이트하는 것이 좋습니다.


답변