2012-08-28 2 views
27

2 개의 ASyncTask가 있습니다. 하나는 httpPost에서 값을 검색하고 다른 하나는 UI의 일부 요소 (목록보기 포함)를 업데이트합니다. 문제는 네트워크 동기화가 먼저 시작되고 네트워크 연결 불량으로 인해 두 ASyncTask가 동일한 백그라운드 스레드를 공유하기 때문에 문제입니다. 다른 배경 스레드는 앱을 무책임하게 만드는 데 너무 많은 시간이 걸립니다.다른 사람을 차단하는 ASyncTasks

두 ASyncTasks는 모두 독립적이기 때문에 다른 쪽을 기다리게 만드는 것은 매우 어리 석다. 그것은 더 논리적 인 asynctasks 다른 클래스가 다른 스레드를 사용하는 것입니다, 내가 틀렸어?

ASyncTask 문서를 읽는 중입니다. executeOnExecutor() 사용에 대해 이야기하지만, 11보다 낮은 API 레벨에서 어떻게 해결할 수 있습니까? 여기

는 "문제"로

 new Task1().execute(); 
     new Task2().execute(); 

을 재현 한 작은 예를 간다

public class Task1 extends AsyncTask<Void, Void, Void> { 

    @Override 
    protected Void doInBackground(Void... params) { 
     GLog.e("doInBackground start 1"); 
     SystemClock.sleep(9000); 
     GLog.e("doInBackground end 1"); 
     return null; 
    } 

    @Override 
    protected void onPreExecute() { 
     GLog.e("onPreExecute 1"); 
     super.onPreExecute(); 
    } 

    @Override 
    protected void onPostExecute(Void result) { 
     GLog.e("onPostExecute 1"); 
     super.onPostExecute(result); 
    } 

} 

public class Task2 extends AsyncTask<Void, Void, Void> { 

    @Override 
    protected void onPreExecute() { 
     GLog.e("onPreExecute 2"); 
     super.onPreExecute(); 
    } 

    @Override 
    protected Void doInBackground(Void... params) { 
     GLog.e("doInBackground start 2"); 
     SystemClock.sleep(9000); 
     GLog.e("doInBackground end 2"); 
     return null; 
    } 

    @Override 
    protected void onPostExecute(Void result) { 
     GLog.e("onPostExecute 2"); 
     super.onPostExecute(result); 
    } 

} 
+0

UI를 업데이트하는 AsyncTask가있는 이유는 무엇입니까? 이 스레드에서 동기식으로 수행해야합니다. 귀하의 UI AsyncTask 백그라운드 스레드에서 다른 일을합니까? –

+0

예를 들어 뉴스와 함께 목록보기를 표시하는 데 사용합니다. onPreExecute에서 백그라운드에서 loading() UI를 표시하고 인터넷에서 뉴스를 검색하고 onPostExecute에서 어댑터를 listview에 할당합니다. 그 접근 방식이 잘못 되었습니까? – Addev

+0

@Addev : 첫 번째? onPostExecute (...) 메소드에서 두 번째 AsyncTask를 시작하는 것이 어떨까요? 필요한 경우 하나의 AsyncTask가 다른 AsyncTask의 결과에 의존한다는 것과 동기식 요구 사항을 효과적으로 가지며 두 개의 비동기 작업을 병렬로 실행하지 않아야한다는 것입니다. – Squonk

답변

46

이 내 코드에서이 문제를 처리하는 방법입니다 :

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
    new MyAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
} else { 
    new MyAsyncTask().execute(); 
} 

그리고 MyAsyncTask 교체 너 Task1Task2과 각각 기본적으로 Honeycomb에서 변경된 AsyncTask (Android SDK 문서 here의 "실행 순서"섹션 참조)에 변경 사항이 적용되기 전에 평소와 같이 HC를 실행하고 새로운 동작이 마음에 들지 않으면 executeOnExecutor()을 사용합니다 (아무도하지 않습니다. 나는

7

이 작업을 수행하는 좀 더 일반적인 방법과 같이 유틸리티 클래스에서 두 개의 헬퍼 메소드를 넣어하는 것입니다) 생각 :

class Utils { 

    @SuppressLint("NewApi") 
    public static <P, T extends AsyncTask<P, ?, ?>> void execute(T task, P... params) { 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
      task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params); 
     } else { 
      task.execute(params); 
     } 
    } 
} 

는 그런 다음 Utils.execute(mytask) 또는 Utils.execute(mytask, params)으로 작업을 실행할 수 있으며 처리됩니다 그들을 병렬로 실행합니다.

+0

감사합니다. 후자에 대한 노트,'AsyncTask.execute()'를 오버라이드하려고하지 마라. 그것은 '최종'입니다. – TalkLittle

+0

첫 번째 메소드는 불필요하며 실제로 예상치 못한 동작을 일으킬 수 있습니다 ('params'는 빈 배열 대신에'null'이 될 수 있습니다). 그것을 제거하면 Honeycomb 이전 장치에서 잘 컴파일되고 실행됩니다. – TalkLittle

+0

그것은 불필요한 것이 아니라, 타이핑을 저장합니다 :) –

0

문제는 모든 AsyncTask가 API에 코딩 된 동일한 ThreadPoolExecutor에서 실행된다는 것입니다. 이 ThreadPoolExecutor는 Android 버전에 따라 다른 수의 WorkerThread를 만들 수 있습니다. 나는 번호판을 기억하지 못한다. 그러나 그 생각은 오래된 안드로이드 버전에서는 1 개의 WorkerThread였다. 그런 다음 이후 버전에서는 5로 업데이트되었습니다. 최근에 다시 1로 돌아 왔습니다. 이것이 AsyncTasks가 차단 된 이유입니다. 그들은 모두 같은 WorkerThread에서 실행되므로 순차적으로 실행됩니다. 진정한 병렬 실행을 달성하려면 THREAD_POOL_EXECUTOR와 함께 executeOnExecutor를 사용해보십시오. 그러나 API 11 이후에만 사용할 수 있습니다.

관련 문제