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

в 14:07, , рубрики: android, android development, asynctask, делегат, Песочница, Разработка под android, метки: , , , ,

Всем привет!

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

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

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


  1. FanFM:

    Спасибо! Отлично работает ))))

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js