2009-12-16 4 views
19

그래서 AsyncTask 클래스와 함께 Android를 사용하여 첫 번째 멀티 스레드 응용 프로그램을 만들고 있습니다. 두 번째 스레드에서 지오 코더를 실행 한 다음 onPostExecute로 UI를 업데이트하려고하지만이를 올바른 컨텍스트와 관련된 문제로 계속 실행하려고합니다.AsyncTask 및 컨텍스트

메인 스레드에서 컨텍스트를 사용하여 내 방식을 혼란스럽게 만들었지 만 컨텍스트가 무엇인지 또는 백그라운드 스레드에서 사용하는 방법을 정확히 알지 못하고 이에 대한 좋은 예제를 찾지 못했습니다. 어떤 도움이 필요합니까?

public class GeoCode extends AsyncTask<GeoThread, Void, GeoThread> { 
    @Override 
    protected GeoThread doInBackground(GeoThread... i) { 
    List<Address> addresses = null; 
    Geocoder geoCode = null; 
    geoCode = new Geocoder(null); //Expects at minimum Geocoder(Context context); 
    addresses = geoCode.getFromLocation(GoldenHour.lat, GoldenHour.lng, 1); 
    } 
} 

이 때문에 부적절한 문맥으로,이 여섯 번째 줄에서 실패 유지 : 여기에 내가 할 노력하고있어의 일부를 발췌 한 것입니다.

답변

2

나는 더 많은 연구를했고, 누군가 그것을 스레드로 전달할 것을 제안했다. (왜 그런 생각을하지 않았는지 확신 할 수 없다.) 인수를 통해 지오 코더 (Geocoder) 스레드로 전달했고, 그 것처럼 작동했습니다.

+4

당신이 무슨 짓을했는지의 예를 게시하고이 질문에 대한 정확한 답을 업데이트 할 수주십시오? –

+0

@Eugene van der Merwe가 내 대답을 보았습니다. 나는 그것이 그가 결국 무엇을했는지 보여주는 예라고 생각합니다. –

4

컨텍스트는 응용 프로그램 런타임 환경에 이점을 제공하는 개체입니다. 대부분의 경우 리소스,보기, 인프라 클래스 등 Android 환경에서 객체를 가져와야하는 경우 Context가 있어야합니다.

Activity 클래스에있을 때 Context 인스턴스를 얻는 것은 매우 간단합니다. 활동 자체는 Context의 하위 클래스이므로 수행해야하는 모든 작업은 'this'키워드를 사용하여 현재를 가리키는 것입니다 문맥.

Context가 필요할 수있는 코드를 만들 때마다 부모 Activity에서 Context 객체를 전달해야합니다. 귀하의 예제의 경우 입력 인수로 컨텍스트를 받아들이는 명시 적 생성자를 추가 할 수 있습니다.

1

AsyncTask에서 UI를 업데이트 할 때의 문제점은 현재 활동 컨텍스트가 필요하다는 것입니다. 그러나 상황은 모든 방향 변경에 따라 파괴되고 재창조됩니다. 다음 코드 조각은 나를 위해 작동 Android AsyncTask context behavior

18

@Eugene 반 데르 메르 웨

:

여기에 귀하의 질문에 좋은 답변입니다) ->

public class ApplicationLauncher extends Activity { 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.applicationlauncher); 

    LoadApplication loadApplication = new LoadApplication(this); 
    loadApplication.execute(null); 
} 

private class LoadApplication extends AsyncTask { 

    Context context; 
    ProgressDialog waitSpinner; 
    ConfigurationContainer configuration = ConfigurationContainer.getInstance(); 

    public LoadApplication(Context context) { 
     this.context = context; 
     waitSpinner = new ProgressDialog(this.context); 
    } 

    @Override 
    protected Object doInBackground(Object... args) { 
     publishProgress(null); 
     //Parsing some stuff - not relevant 
     configuration.initialize(context); 
     return null; 
    } 

    @Override 
    protected void onProgressUpdate(Object... values) { 
     super.onProgressUpdate(values); 
     // Only purpose of this method is to show our wait spinner, we dont 
     // (and can't) show detailed progress updates 
     waitSpinner = ProgressDialog.show(context, "Please Wait ...", "Initializing the application ...", true); 
    } 

    @Override 
    protected void onPostExecute(Object result) { 
     super.onPostExecute(result); 
     waitSpinner.cancel(); 
    } 
} 
} 

건배,

Ready4Android

+0

감사합니다, 매력처럼 작동합니다! – agentcurry

+27

이 코드는 컨텍스트 누수가 있습니다. Activity를 AsyncTask에 Context로 저장하고 있습니다. 사용자가 Activity를 다시 만드는 장치를 돌릴 때를 제외하고는 괜찮습니다. AsyncTask는 액티비티의 이전 복사본에 대한 참조와 함께 계속 실행되며 이제 액티비티의 두 복사본이 메모리에 저장됩니다. –

+0

@ChristopherPerry : AsyncTask에서 WeakReference로 컨텍스트를 유지하면 누수가 해결됩니까?아니면 위의 솔루션을 안전하게 조정할 수있는 더 나은 방법이 있습니까? – gcl1

0

너처럼 보이지 않는 경우 params를 사용하고 있습니다. Conetxt를 전달하기 위해 그것을 사용할 수 있습니다. 활동 내에서 다음

public class GeoCode extends AsyncTask<Context, Void, GeoThread> { 
    @Override 
    protected GeoThread doInBackground(Context... params) { 
    List<Address> addresses = null; 
    Geocoder geoCode = null; 
    geoCode = new Geocoder(params[0]); //Expects at minimum Geocoder(Context context); 
    addresses = geoCode.getFromLocation(GoldenHour.lat, GoldenHour.lng, 1); 
    } 
} 

:

GeoCode myGeoCode = new GeoCode(); 
myGeoCode.execute(this);