Как стать автором
Обновить

Использование делегата для получения данных из AsyncTask

Время на прочтение2 мин
Количество просмотров1.7K
Всем привет!

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


Понадобилось мне сделать микро-приложение, задача которого проста до безобразия: получить данные с вебсервиса и отобразить их на экране в виде списка. Казалось бы, что может быть проще? Но есть одно «но», точнее, этих «но» даже несколько.

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


Как видите ничего революционного, чисто и просто. Надеюсь, что я кому-нибудь сэкономил время.
Теги:
Хабы:
Всего голосов 16: ↑13 и ↓3+10
Комментарии17

Публикации