2011-03-09 2 views
1

매우 이상한 문제가 있습니다. 전화를 돌릴 때 UI 스레드를 차단하는 것으로 보이는 AsyncTask이 있습니다.Android AsyncTask가 방향 변경 UI를 차단합니다.

먼저, 내 Activity이 파괴되어 회전 할 때 편안하다고 말하게하십시오. AsyncTaskonRetainNonConfigurationInstance()에 저장하고 onDestroy()에서 활동을 분리 한 다음 getLastNonConfigurationInstance()을 사용하여 onCreate()에 다시 첨부합니다.

AsyncTask이 무거운 작업을하지 않는 한 괜찮습니다. 예를 들어, 내 문제를 디버깅하기 위해, 나는이 있고, 그것이 어떤 UI 차단 예상대로 정확하게 작동 : 나는 백그라운드에서 몇 가지 실제 작업을 수행하는 변경하는 경우,

@Override 
protected Boolean doInBackground(Void... params) { 
    boolean success = false; 
    final DbAdapter dbAdapter = dbService.getAdapter(); 

    try { 
     // pretend to do some complicated work 
     Thread.sleep(20000); 
     success = true; 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

    return success; 
} 

그러나, 나는 매우 얻을 회전을 시작하기 위해 onPause() 사이의 긴 지연이 발생하고 나중에 새 방향에서 onResume()이 호출됩니다. 이 지연은 UI가 일관성없는 상태 (이전 레이아웃이 새 방향으로 잘린 상태)에있는 동안 수십 초 내에 나타나며 마치 회전이 AsyncTask에서 차단되는 것처럼 보입니다. 유일한 변화는 try 블록 내부의 두 줄입니다 :

@Override 
protected Boolean doInBackground(Void... params) { 
    boolean success = false; 
    final DbAdapter dbAdapter = dbService.getAdapter(); 

    try { 
     // actually do some complicated work 
     XmlParser parser = new XmlParser(context, dbAdapter); 
     success = parser.parse(source); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

    return success; 
} 

contextAsyncTask의 생성자에 전달 글로벌 애플리케이션 컨텍스트, 그래서 내가 실수에 대한 참조를 유지하고있어 생각하지 않는다 나가는 Activity.

그 밖의 무엇이 잘못 될 수 있습니까?

답변

1

아마도 액티비티도 dbAdapter이고, 두 스레드가 dbAdapter을 동시에 사용하지 못하도록 적절한 동기화가 진행 중입니다.

아마도 당신의 활동이 메인 애플리케이션 스레드의 파일 시스템을로드하려고 시도하고 있으며 데이터베이스 작업이 너무 많은 경쟁을 일으키고 있습니다. 하드웨어에서 YAFFS2는 효과적으로 I/O 작업을위한 단일 스레드입니다.

Traceview를 사용하면 시간이 많이 걸리는 것에 대한 자세한 정보를 얻을 수 있으며 Android 2.2 이상에서는 StrictMode을 사용하여 주 응용 프로그램에서 파일 I/O를 수행하려는 위치를 확인할 수 있습니다 실.

AsyncTask 또한 XML을 데이터베이스 항목으로 변환하는 경우 AsyncTask이 아닌 IntentService을 사용하는 것이 좋습니다.

+0

올바른 방향으로 나를 가리켜 주셔서 감사합니다. 그것은 데이터베이스 경쟁입니다. 장기 실행 데이터베이스 조작은 트랜잭션으로 랩됩니다. 트랜잭션을 사용하지 않도록 설정하면 정상적으로 작동하지만 10 배의 시간이 소요됩니다. 흥미롭게도 그 논쟁은 눈에 보이는 활동이 아닙니다. 내 활동은 Tabhost에서 여러 활동 중 하나이며 데이터베이스가 차단 해제되기를 기다리는 다른 활동 (순환 게재시에는 표시되지 않음) 중 하나입니다. –

+0

IntentService 제안 사항에 대해 ... 결과를 UI에 다시 전달하는 것이 어렵다는 것을 이해합니다. 예를 들어 진행률 대화 상자를 닫을 수 있습니다. IntentService가 AsyncTask보다 나은 이유에 대한 좋은 설명을 가르쳐 주시겠습니까? –

+0

@Graham Borland : 경우에 따라 IntentService보다 좋지 않을 수도 있습니다. 귀하는 귀하의 질문에 UI를 업데이트해야한다고 규정하지 않았습니다. 사용자가 BACK을 누를 때 AsyncTask가 누출되었다고해도, Android가 완료되기 전에 프로세스를 종료 할 수 있기 때문에 배경 작업이 완료되지 않을 수도 있습니다. 주변에서 처리.그것은 'IntentService'가 당신에게주는 것입니다 : 멀리있는 활동에서 살아남을 수 있고, 안드로이드가 무언가가 여전히 주변에 있다는 것을 알려주는 긴 배경 액션들을위한 컨테이너. – CommonsWare