2012-08-24 2 views
9

나는 내 질문과 거의 같은 질문을 거의 보지 못했지만 모든 의문점을 해결할 수있는 완전한 답을 찾을 수 없었다. 그래서 나는 여기있다 ... AsyncTask 클래스를 확장 한 내부 클래스를 가진 활동이 있다고 가정 해보자. 같은 : 실행중인 활동이 아직 실행 중일 때 중지/파괴 될 때 AsyncTask는 어떻게됩니까?

public class MyActivity extends Activity {    
    private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { 
     protected Bitmap doInBackground(String... urls) { 
      return DownloadImage(urls[0]); 
     } 
     protected void onPostExecute(Bitmap result) { 
      ImageView img = (ImageView) findViewById(R.id.img); 
      img.setImageBitmap(result); 
     } 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     new DownloadImageTask().execute("http://mysite.com/image.png") 
    } 
} 

은 활동이 일시 정지 또는 DownloadImageTask 여전히 백그라운드에서 실행되는 동안 (아마도 두 경우가 다른) 파괴한다고 가정하자 .. 다음 활동 UI 스레드에서 실행되는 DownloadImageTask의 방법 가 트리거 될 수 있고 DownloadImageTask은 Activity 클래스의 메서드 (내부 클래스이므로 외부 클래스의 메서드와 인스턴스 변수에 액세스 할 수 있음)에 액세스하려고 시도 할 수 있습니다 (예 :호출). 아래 예제에서.. 그러면 어떻게됩니까? 그것은 조용히 실패합니까? 예외가 발생합니까? 사용자에게 문제가 발생했음을 알리는 메시지가 표시됩니까?

실행중인 UI 메서드가 호출 될 때 시작 스레드 (이 경우 Activity)가 여전히 작동하는지주의해야한다면 AsyncTask에서 어떻게 수행 할 수 있습니까?

중복 된 질문으로 이것을 발견,하지만 어쩌면이 질문은 좀 더 관절과 사람이 R.id.test가를 의미 곳 (이 작업을 고려 자세히

+1

이 코드를 실행했을 때 자동으로 오류가 발생했는지, 예외가 발생했는지, 사용자에게 잘못된 점을 알렸습니까? – CommonsWare

+0

나는 아직 그런 코드를 실행하지 않았다. 나는 며칠 동안 그것을 할 것이다. 나는 앱의 구현을 계속하기 전에 그것에 대해 궁금해하고 있었다. 테스트를 실행할 수있는대로이 포스트를 업데이트하겠습니다.고맙습니다. @ CommonsWare –

+1

요점은 행동이 문서화되어 있지 않다는 것입니다. 특히 우리가 그 활동에서 다른 것을 본적이 없다는 사실을 고려할 때. 'findViewById()'는'R.id.img'에 대해'null '을 반환 할 수도 있고 그렇지 않을 수도 있습니다. 그리고 그 동작은 Android OS 릴리스, 장치 제조업체 변경 및 ROM 개조를 기반으로 장치마다 다를 수 있습니다. – CommonsWare

답변

3

에 대답 할 수 있다면 미안 해요 내가 그렇게 같은 활동의에서 onCreate에서이 작업을 실행하지 않는 경우

public class LongTaskTest extends AsyncTask<Void, Void, Void>{ 
    private WeakReference<Activity> mActivity; 
    public LongTaskTest(Activity a){ 
     mActivity = new WeakReference<Activity>(a); 
    } 
    @Override protected Void doInBackground(Void... params) { 
     LogUtil.d("LongTaskTest.doInBackground()"); 
     SystemClock.sleep(5*60*1000); 
     LogUtil.d("mActivity.get()==null " + (mActivity.get()==null)); 
     LogUtil.d("mActivity.get().findViewById(R.id.frame)==null " + (mActivity.get().findViewById(R.id.test)==null)); 
     return null; 
    } 
} 

: 내 활동의 레이아웃에서 유효보기)에 상관없이

public class Main extends Activity { 
    @Override 
    public void onCreate(Bundle state) { 
     super.onCreate(state); 
     setContentView(R.layout.testlayout); 
     new LongTaskTest(this).execute(); 
     finish(); 
    } 
} 

을 얼마나 나는 배경을 잠 스레드 내 로그는 항상 보여줍니다

LongTaskTest.doInBackground() 
mActivity.get()==null false 
mActivity.get().findViewById(R.id.frame)==null false 

활동과 그 뷰 (I 수동 DDMS를 통해 GC를 발행하는 경우에도) 살아 남기 위해 나타나는 말을하는 것입니다 어느. 좀 더 시간이 있다면 나는 메모리 덤프보고 싶지만, 그렇지 않으면 난 정말이 사건을 왜몰라 ...하지만 질문에 대한 대답이 나타납니다 :

  • 그것을합니까 조용히 실패합니까? 아니요
  • 예외가 발생합니까? 아니요
  • 사용자에게 문제가 발생했음을 알리는 메시지가 표시됩니까? No
+0

내부 클래스에 대한 참조가 있기 때문에 활동이 여전히있을 수 있지만보기 및 인스턴스 변수는 어떻게 사용합니까? – user412759

+0

그래서 Activity에 WeakReference를 사용했습니다 ... 내 내부 클래스가 Activity가 살아 있던 이유가 아니 었는지 확인하기 위해서였습니다. 뷰와 인스턴스 변수에 관해서, 내 내부 클래스는 WeakReference to Activity를 제외하고는 아무 것도 가지고 있지 않습니다. 다른 뜻이 아니라면 요? WeakReference에 대한 자세한 내용 : http://developer.android.com/reference/java/lang/ref/WeakReference.html – newbyca

+3

@newbyca 사실 'LongTaskTest'가 내부 클래스 인 경우에는 Activity에 대한 암시 적 참조가 있습니다. 당신은 잊고 있습니다 - 정적 중첩 클래스 : http://stackoverflow.com/questions/70324/java-inner-class-and-static-nested-class – MattJenko

2

doInBackground() 메소드가 작업자/백그라운드 스레드에서 실행되기 때문에 사용자의 Activity가 파괴되는 경우에도 doInBackground()가 계속 실행됩니다 (즉, 기본 스레드가 파괴됩니다). main/UI 스레드에서 실행될 때 onPostExecute() 메서드를 실행할 때 '문제'가 발생하고 관련없는 데이터로 실행되는 경우가 있지만 예외는 사용자에게 표시되지 않습니다. 따라서 활동이 더 이상 존재하지 않을 때 AsyncTask를 실행할 이유가 없으므로 활동이 파손될 때 항상 AsyncTask를 취소하는 것이 좋습니다. 구성 요소/활동이 파괴 되더라도 네트워크에서 무언가를 지속적으로 다운로드하려면 Android 서비스를 사용하십시오. 감사.