2012-01-23 3 views
1

내 스플래시 화면에서 나는 긴 초기화를 실행합니다. 그래서 배경 비동기 작업을 만들고 무거운 작업을 수행하기 위해 그것을 실행합니다. 그런 다음 주 Activity (UI) 스레드가 스플래시 화면 이미지를 표시하고 onCreate() 메서드에서 돌아와 화면을 업데이트합니다. 비동기 작업이 완료되면 주 활동을 호출하고 자체 종료하는 스플래시 화면 활동에 대한 메소드를 호출합니다.AsyncTask가 다음 활동 호출시 실행되지 않습니다.

이것은 처음 앱을 실행할 때 훌륭하게 작동합니다. 응용 프로그램을 종료하고 다시 시작하면 완전히 새로운 비동기 작업이 만들어지고 execute 메서드가 호출되면 onPreExecute() 메서드가 호출되지만 doInBackground() 메서드는이 두 번째 실행에서는 호출되지 않습니다.

작업 관리자를 사용하여 응용 프로그램을 강제 종료하면 올바르게 작동합니다. 이 문제는 응용 프로그램이 완료되었지만 (장치 홈 화면에 표시됨) 아직 OS에서 회수하지 않은 경우에 발생합니다.

새로운 비동기 작업 객체를 만들고 execute() 메소드를 호출하기 전에 취소되지 않았는지 확인합니다. 비동기 작업이 이전 인스턴스에 대해 기억하고 마치 이미 실행 된 것으로 생각하기 때문에 새로운 비동기 작업을 시작하지 못하는 것입니다.

새로운 비동기 작업이 execute가 호출 될 때 doInBackground() 메서드를 호출하지 않는 이유는 무엇입니까?

코드 비동기의 작업 :

public class AsynchTaskInitializeApplication extends AsyncTask<Void, Integer, Boolean> { 

    private ActivitySplashScreen theActivity; 

    public AsynchTaskInitializeApplication() { 
      Log.d("App", "AsynchTaskInitializeApplication constructor called\n"); 
    } 

    public void setTheActivity(ActivitySplashScreen theActivity) { 
      Log.d("App", "AsynchTaskInitializeApplication::setTheActivity() called\n"); 
      this.theActivity = theActivity; 
    } 

    @Override 
    protected Boolean doInBackground(Void... arg0) { 
      boolean result = false; 

      Log.d("App", "AsynchTaskInitializeApplication::doInBackground() called\n"); 

      try { 
        // Initialization code goes here 
        result = true; 
      } catch (Exception e) { 
        // Something went wrong - we failed. 
        // Return false result. 
        e.printStackTrace(); 
      } 

      return result; 
    } 

    @Override 
    protected void onPreExecute() { 
      super.onPreExecute(); 
      Log.d("App", "AsynchTaskInitializeApplication::onPreExecute() called\n"); 
    } 

    @Override 
    protected void onPostExecute(Boolean result) { 
      super.onPostExecute(result); 

      if (this.theActivity != null) { 
        this.theActivity.initializationComplete(result); 
      } 
    } 
} 

생성/호출 코드 :

// Start the asynchronous task that starts the data store and does 
    // any other heavy hitting initialization. 
    this.mBackgroundInitialization = null; 
    this.mBackgroundInitialization = new AsynchTaskInitializeApplication(); 
    this.mBackgroundInitialization.setTheActivity(this); 
    Log.d("App", "ActivitySplashScreen::onCreate() start the background initialization\n"); 
    if (this.mBackgroundInitialization.isCancelled()) { 
      Log.d("App", "ActivitySplashScreen::onCreate() background initialization task already cancelled\n"); 
    }  
    this.mBackgroundInitialization.execute(); 
    Log.d("App", "ActivitySplashScreen::onCreate() background initialization should have started\n"); 

배경 작업이 완료 될 때 호출되는 코드 :

public void initializationComplete(boolean readyToGo) { 
    Log.d("App", "Initialization is complete " + readyToGo + "\n"); 
    // Attempt to forcibly stop the background task. 
    // A second attempt to run the app does not cause it to execute. 
    if (!this.mBackgroundInitialization.isCancelled()) { 
      this.mBackgroundInitialization.cancel(true); 
    } 
    this.mBackgroundInitialization = null; 

    // Display the home screen 
    Intent homeScreenIntent = new Intent(context, ActivityHomeScreen.class); 
    try { 
      startActivity(homeScreenIntent); 

      // And quit this activity so that when the home screen activity 
      // finishes then the application finishes 
      this.finish(); 
    } catch(ActivityNotFoundException e) { 
      errorMessage = "Cannot find activity for intent: " + homeScreenIntent.toString(); 
    } catch(Exception e) { 
      errorMessage = "Unknown exception when launching intent: " + homeScreenIntent.toString(); 
    } 
    Log.e("App", errorMessage); 
    this.finish(); 
    } 

의 로그 캣 출력 성공적인 첫 번째 실행 사례, doInBackground() 메소드가 자체적으로 알림을 받고, 초기화 컴퍼넌트 letes :

01-22 23:59:30.133 10195 10195 D App: AsynchTaskInitializeApplication constructor called 
01-22 23:59:30.133 10195 10195 D App: AsynchTaskInitializeApplication::setTheActivity() called 
01-22 23:59:30.133 10195 10195 D App: ActivitySplashScreen::onCreate() start the background initialization 
01-22 23:59:30.133 10195 10195 D App: AsynchTaskInitializeApplication::onPreExecute() called 
01-22 23:59:30.133 10195 10195 D App: ActivitySplashScreen::onCreate() background initialization should have started 
01-22 23:59:30.157 10195 10207 D App: AsynchTaskInitializeApplication::doInBackground() called 
01-22 23:59:30.477 10195 10195 D App: Initialization is complete true 

doInBackground()가 실행되지 않습니다 두 번째 실행의 로그 캣 출력 :

01-23 00:02:45.868 10195 10195 D App: AsynchTaskInitializeApplication constructor called 
01-23 00:02:45.868 10195 10195 D App: AsynchTaskInitializeApplication::setTheActivity() called 
01-23 00:02:45.868 10195 10195 D App: ActivitySplashScreen::onCreate() start the background initialization 
01-23 00:02:45.868 10195 10195 D App: AsynchTaskInitializeApplication::onPreExecute() called 
01-23 00:02:45.868 10195 10195 D App: ActivitySplashScreen::onCreate() background initialization should have started 
+0

코드를 업로드하십시오 – Lucifer

답변

0

내가 당신의 대답은() 단지에서 onCreate보다 더 많은 방법의 사용에 있다고 생각 . 활동 라이프 사이클에 대해 잘 알고있는 경우 : http://developer.android.com/reference/android/app/Activity.html

앱이 다른 상태로 전환 될 때 새로운 상태를 처리하기 위해 다른 방법을 호출 할 수 있습니다. 이 경우 처음으로 앱을 실행할 때와 마찬가지로 문제를 일으킨 것으로 보이는 AsyncTask가 삭제되었는지 확인하려고합니다. 사용 :

myAsyncTask.cancel(); 

여기서 앱이 작업을 종료하려고 시도하는 것이 적절합니다.

http://developer.android.com/reference/android/os/AsyncTask.html

+0

샘플 코드를 추가하기 전에 Flynn이이 설명을 추가했습니다. 저에게 문제를 일으키는 코드 경로에 명시적인 취소가 있습니다. 초기화가 완료되기 전에 앱이 일시 중지되기 전에 발생하는 경우에도 onPause()에 하나가 있습니다. – Colin

0

본인은 AsyncTask를의 상태를 기록하는 것이 좋습니다.

+0

좋은 아이디어.당신이 그것을 얻을 수 있다는 것을 몰랐는데 (필자는 필독서를 읽어야하며 필자는 필독서를 읽어야한다). 나는 그것이 무엇을 말하는지 보게 될 것이다. – Colin

+1

getStatus()를 사용하면 해당 메서드가 AsyncTask.Status 열거 형을 반환합니다. – lulumeya

관련 문제