2011-09-29 10 views
4

편집 : 대화 상자를 표시하면 아무런 문제없이 모든 작업이 진행됩니다. 하지만 진행률을 추가하면 대화 상자가 닫히지 않습니다 (메서드 onPostExecute()가 실행되지 않음).Android AsyncTask onPostExecute 메서드


onPostExecute 메서드가 실행되지 않습니다. 나는 어디에서 실수를합니까? (에뮬레이터와 장치에서 같은 결과가 나타납니다.) 이 메서드에 대한 재정의 표기법을 사용해야하는지 잘 모르겠습니다.

이것은 현재로서는 대략적인 해결책입니다. 그것은 매번 작동하지만, 적절하지 않고 좋은 것이 아닙니다. 내가하고있는 일 : * tabgroupactivity를 사용하여 하위 활동을 시작합니다. * 그런 다음 하위 활동의 ​​다른 활동으로 이동하므로 부모의 현재 하위입니다. * 웹보기가 있는데 여기에 대한 정보가 표시됩니다. 덧글 .. 뭐든간에 * webView *에 표시된 콘텐츠에 링크가 있습니다.이 링크를 클릭하면 PDF 파일을 다운로드하기 시작합니다.

파일이 다운로드되는 경우 : 내가 while 루프 후 대화 상자를 호출하려고하면, 난 그냥 그것을 얻을하지 않도록

while ((current = bis.read()) != -1) { 
     read = read + current; 
     baf.append((byte) current); 
     Dialog.setProgress(read); 

     if(Dialog.isShowing() && read+2*current>file_size){ 
      Dialog.dismiss(); 
      Dialog.cancel(); 
     } 
    } 

내 대화 오브젝트는, disapeared된다. 그래서 내가 한 것은 웹 사이트에서 새로운 버퍼를 얻을 때마다 대화 상자가 여전히 보이는지 확인하고 현재 바이트와 함께 읽은 바이트의 양이 파일의 전체 크기보다 큰지를 확인합니다. while 루프에서 대화 상자를 닫으십시오. 나는 이는 파일 크기가 == (바이트의 양)를 읽을 사용하여 시도하지만 파일이

private class DownloadPDFFile extends AsyncTask<String, Integer, Void> { 
    private ProgressDialog Dialog = new ProgressDialog(getParent()); 

    protected void onPreExecute() { 
     Dialog.setMessage("Downloading PDF file.."); 
     Dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 
     Dialog.setCancelable(false); 
     // Dialog.setMax(1000); 
     Dialog.setProgress(0); 
     Dialog.show(); 
    } 

    protected Void doInBackground(String... urls) { 
     File file=null; 
     int file_size = 0; 
     try { 
      URL url = new URL(urls[0]); 
      URLConnection urlConnection = url.openConnection(); 
      urlConnection.connect(); 
      file_size = urlConnection.getContentLength(); 
      Dialog.setMax(file_size); 
     } catch (IOException e) { 

     } 

     try { 
      URL url1 = new URL(urls[0]); // you can // link 

      file = new File("skm_intern_pdf.pdf"); 

      URLConnection ucon = url1.openConnection(); 

      InputStream is = ucon.getInputStream(); 

      BufferedInputStream bis = new BufferedInputStream(is); 

      ByteArrayBuffer baf = new ByteArrayBuffer(5000); 
      int read = 0; 
      int current = 0; 
      while ((current = bis.read()) != -1) { 
       read = read + current; 
       baf.append((byte) current); 
       Dialog.setProgress(read); 

       if(Dialog.isShowing() && read+2*current>file_size){ 
        Dialog.dismiss(); 
        Dialog.cancel(); 
       } 
      } 

      FileOutputStream fos = openFileOutput("skm_pdf.pdf", 
        Context.MODE_WORLD_WRITEABLE); 
      fos.write(baf.toByteArray()); 
      fos.flush(); 
      fos.close(); 

     } catch (IOException e) { 

     } 

     return null; 
     } 
+0

onPostExecute는 절대로 호출되지 않는다고 결론을 내린 이유는 무엇입니까? 일부 logcat을 게시하십시오. – kaspermoerch

+0

sys.out +는 Dialog.dismiss()를하고 있습니다. Logcat을 게시하면 임의의 메시지가 수천 개가됩니다. –

+0

정말 logcat을 게시하십시오. Log.i (디버그 태그, 메시지)를 사용하여 앱을 추적 할 수 있습니다. Eclipse에서는 디버그 태그를 사용하여 필터를 만들 수 있으므로 로그 만 인쇄됩니다. – Huang

답변

2

AsyncTask가 끝나기 전에 AsyncTask의 부모가 취소/일시 정지/삭제 되었습니까?

예인 경우 AsyncTask가 cancel()을 수신하여 onPostExecute()이 실행되지 않을 수 있습니다. 이를 확인하려면 onCancelled() -method를 무시하고 실행 중인지 확인하십시오.

+0

그것은 자식 활동이므로 getParent 컨텍스트를 사용하고 있습니다. 그리고 이전 활동은 아마도 죽었을 것입니다. –

+0

AsyncTask가 선언 된 클래스의 OuterClassName = name 인 경우 'getParent()'를 'OuterClassName.this'로 바꾸어보십시오. 그런 다음'onPostExecute()'에'dialog.dismiss()'를 추가하십시오. – kaspermoerch

+0

onCancelled 메서드에서 아무것도 얻지 못하고 있습니다. 어쩌면 사실이 아닙니다. –

-1

이럴을 다운로드 할 때 아마 그들은 정확하게, 당신은 단지 슈퍼를 제거해야 서로 마하되지 작동하지 않았다 요구.

+0

이 솔루션은 나를 도왔습니다 –

1

사람들이 게시하기 전에 사람들이 검색하지 않기 때문에 3 번 같은 대답을 게시하는 방법 재미 있습 ... UI 스레드가 아닌 UI 스레드에 액세스 할 수는 없습니다 ... 즉, 대화 상자를 의미합니다. Dismiss 및 Dialog.cancel은 스레드로부터 안전하지 않으므로 실행될 수 없습니다.

문제를 해결하려면 여러 가지 방법이 있습니다. 첫 번째 방법은 : AsyncTask을 사용하지 마십시오. 최대 5 개의 작업을 매번 실행합니다 ... AsyncTask의 Android 문서와 추가 정보를 위해 첨부 된 프로세스 및 스레드에 대한 지침을 보내드립니다.

두 번째 방법 :onPostExecute()에있는 모든 UI 스레드 관련 메서드를 이동합니다. 이는 스레드로부터 안전하며 doInBackground()의 결과가 자동으로 전송됩니다.

세 번째 방법 : 다음

Activity.runOnUiThread(Runnable) 
View.post(Runnable) 
View.postDelayed(Runnable, long) 

Runnable 오브젝트의에 사용은 UI 스레드 내에서 실행됩니다. 다시. 스레드로부터 안전합니다.

앱을 철저히 최적화 할 필요가 없다면 두 번째 해결책을 권합니다. 그럴 경우 작업을 수동으로 수동으로 추가 한 ThreadPoolExecutor에 추가하십시오 (다시 ThreadPoolExecutor의 문서 참조).

하면 문서를 검색하는 동안 나는 발견이 :

이 클래스가 제대로 작동하기 위해 반드시 따라야하는 몇 스레딩 규칙이 있습니다

:

The task instance must be created on the UI thread. 
execute(Params...) must be invoked on the UI thread. 
Do not call onPreExecute(), onPostExecute(Result), 
doInBackground(Params...), onProgressUpdate(Progress...) 
manually. 
The task can be executed only once (an exception will be thrown 
if a second execution is attempted.) 

를 UI 스레드에없는 경우 AsyncTask 대신 Task를 사용하고 ThreadPoolExecutor을 사용하여 랩핑하십시오.

이것은 Asynctask : How can I make asynchronous URL connections on Android? 답안에서 내 이름을 찾으려는 이유입니다.

0

이 스레드는 동일한 문제를 찾고 있습니다.)

  1. 내가() (대신 onPostExecute의 화재 때로는 doInBackground에서 내 작업을 취소하는 대신 onCancelled 원인 일반적으로 완전한 방법을시키는되었습니다 많은 시행 착오 후, 나는 두 가지 문제를 발견했다. 팁 (Kasper)에 감사드립니다!

  2. 나는 분명히 onPostExecute에 대해 잘못된 메서드 서명을 사용하고있었습니다. 당신이 반환 유형이없는 경우, 그것은 할 필요가 :

    보호 무효 onPostExecute (무효 V) 매우 직관적되지 않음 및 API에 표시되지하지만 행한 이런 짓을 한 번

속임수.

관련 문제