2009-12-16 4 views
19

Итак, я разрабатываю свое первое многопоточное приложение, использующее Android с классом AsyncTask. Я пытаюсь использовать его, чтобы отключить геокодер во втором потоке, а затем обновить пользовательский интерфейс с помощью onPostExecute, но я все время сталкиваюсь с проблемой с соответствующим контекстом.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

@ Юджин ван дер Мерве посмотри мой ответ, я думаю, что это пример того, что он сделал. –

4

Контекст - это объект, который обеспечивает accees среду выполнения приложения. В большинстве случаев, когда вам нужно получать объекты из среды Android, такие как ресурсы, представления, классы инфраструктуры и т. Д., Вам нужно иметь Контекст в ваших руках.

Чтобы получить экземпляр контекста очень просто, когда вы находитесь в классе Activity - сама деятельность является подклассом контекста, поэтому все, что вам нужно сделать, - это использовать это ключевое слово, чтобы указать на текущий контекст.

Создайте код, который может потребовать контекста. Вы должны позаботиться о передаче объекта контекста из своей родительской активности. В случае вашего примера вы можете добавить явный конструктор, который принимает Контекст как входной аргумент.

1

Проблема с обновлением пользовательского интерфейса из AsyncTask заключается в том, что вам нужен текущий контекст активности. Но контекст разрушается и воссоздается для каждого изменения ориентации.

Вот хороший ответ на ваш вопрос: 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(); 
    } 
} 
} 

Cheers,

Ready4Android

+0

спасибо, работает как шарм! – agentcurry

+27

Этот код имеет утечку Контекста. Вы сохраняете Activity как контекст в AsyncTask, что хорошо, за исключением случаев, когда пользователь поворачивает устройство, которое воссоздает Activity. AsyncTask продолжает работать со ссылкой на старую копию вашего Activity, и теперь у вас есть две копии Activity в памяти. –

+0

@ChristopherPerry: сохранял бы контекст как слабый результат в AsyncTask, чтобы устранить утечку?Или есть лучший способ безопасно настроить вышеупомянутое решение? – gcl1

0

Если это не похоже на вас используют параметры. Вы можете использовать это для передачи в 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);