Всем привет!
Хочу поделится одним маленьким трюком для начинающих андроидописателей. Этот трюк стар как мир и сам я раньше многократно им пользовался, но поскольку основная моя работа с андроидом никак не связана, то за давностью лет я его подзабыл и вот на днях был вынужден его срочно вспоминать.
Понадобилось мне сделать микро-приложение, задача которого проста до безобразия: получить данные с вебсервиса и отобразить их на экране в виде списка. Казалось бы, что может быть проще? Но есть одно «но», точнее, этих «но» даже несколько.
Во-первых, все операции, выполнение которых, может занять неопределенное количество времени (а сюда относятся все операции с сетью), должны выполнятся в отдельном потоке. Android SDK предоставляет нам как минимум два варианта решения этого вопроса, один из которых (и на мой взгляд самый правильный) — это AsyncTask. Так, с этим понятно. Идем дальше.
Вторая и самая главная проблема — как вернуть результат работы с сетью в наш основной поток, что бы показать его на экране? Ну давайте разбираться… Что мы знаем про AsyncTask из того, что могло бы нам помочь? А знаем мы то, что его метод onPostExecute выполняется в основном потоке! Этот факт дает нам как минимум два варианта решения проблемы. Номер раз — мы попросту можем передать наш графический контроль (в моем случае это ListView) в AsyncTask параметром и заполнить его данными на onPostExecute. Этот вариант чаще всего встречается в интернете в качестве примера решения нашей задачи. И номер два — вариант который дает нам большую гибкость — это использование делегата. Тут конечно тоже есть несколько вариантов, но я рассмотрю только один из них, который мне больше всех нравится.
Пора переходить от слов к делу!
Итак, для начала мы создадим интерфейс в котором будет всего один метод:
public interface GetDataListener {
void onGetDataComplete(JSONArray result);
}
Теперь имплементируем этот интерфейс в нашу activity:
public class MyActivity extends Activity implements GetDataListener {
private ListView list;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
list = (ListView) findViewById(R.id.lvData);
}
public void onGetDataComplete(JSONArray responce) {
...
// заполняем данными наш ListView
...
}
}
Ну а теперь пришла пора AsyncTask:
public class GetData extends AsyncTask<Void, Void, JSONArray> {
private final static String SERVICE_URI = "http://moi.service.com/service.php";
private GetDataListener listener;
GetData(GetDataListener listener)
{
this.listener = listener;
}
protected void onPostExecute(JSONArray result) {
listener.onGetDataComplete(result);
}
protected JSONArray doInBackground(Void... params) {
return CallService();
}
private JSONArray CallService() {
JSONArray records = null;
...
// забираем наши данные с вебсервиса
...
return records;
}
}
Обратите внимание на конструктор! Тут мы получаем нашего делегата и сохраняем его.
Теперь все практически готово, осталось только запустить наш механизм из нашей activity:
new GetData(this).execute();
Как видите ничего революционного, чисто и просто. Надеюсь, что я кому-нибудь сэкономил время.
Автор: seahawk
Спасибо! Отлично работает ))))