Проблема при использовании нескольких AsyncTask

Activity Lifecycle, Saving Activity State, Managing Tasks, Intent, Intent Filter
Ответить
Кепыч
Сообщения: 2
Зарегистрирован: 08 окт 2014, 09:10

Проблема при использовании нескольких AsyncTask

Сообщение Кепыч » 10 окт 2014, 13:54

Добрый день.

Помогите разобраться со следующей проблемой: запуск AsyncTask по определенному расписанию.

Т.к. изучением разработки под Android занялся буквально месяц назад, а задача стоит вполне конкретная, буду рад любым комментариям, которые помогут разобраться в вопросе.

Собственно теперь некоторое количество информации, на основе которой будет проще понять, что же хочется реализовать.

Исходные данные.
Есть удаленный ресурс, предоставляющий по запросу информацию о положении на мировой карте устройств, размещенных на транспорте (транспорт курсирует по постоянному маршруту). Данная информация обновляется на стороне ресурса 1 раз в минуту.

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

В каком направлении я двигался.
Дойдя в изучении по урокам до AsyncTask, я понял, что мне это подойдет. И, в принципе, все удалось решить (получение данных из сети при запуске, показ на карте), кроме обновления информации с некоторой периодичностью.

В текущем проекте код для работы выглядит так.

1. MainActivity

Код: Выделить всё

public class MainActivity extends FragmentActivity {
	...
	private AsyncTimer transportTimer;
	...
	@Override
	public void onDestroy(){
		transportTimer.unLink();
		super.onDestroy();
	}
	
	@Override
    public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        ...
	    getShuttle();
	    transportTimer = new AsyncTimer(MainActivity.this);
	    transportTimer.execute(GET_TRANSPORTS,"60000");
	}
	
	// Данный метод запускает AsyncTask, обновляющий положение устройств на карте
	public void getShuttle(){
		Log.d(APP_LOG_TAG,"get shuttle");
		new RequestTask().execute(URL,GET_TRANSPORTS);
	}
}
2. RequestTask - хелпер для работы с удаленным ресурсом, описан внутри класса MainActivity

Код: Выделить всё

class RequestTask extends AsyncTask<String, String, String> {
	...
	String task = "";		
	String jsonResult = "";
 
    @Override
    protected String doInBackground(String... params) {
      	task = params[1];
       	Log.d(APP_LOG_TAG,"Start task "+task);
        try {
            DefaultHttpClient hc = new DefaultHttpClient();
            ResponseHandler<String> res = new BasicResponseHandler();
            HttpPost postMethod = new HttpPost(params[0]);
            postMethod.setHeader("X-Requested-With", "XMLHttpRequest");
            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
            switch(task){
            ...
            case GET_TRANSPORTS:
            	nameValuePairs.add(new BasicNameValuePair("task", "getLastTrackingM"));
              	break;
			...
            }
            postMethod.setEntity(new UrlEncodedFormEntity(nameValuePairs));
            jsonResult = hc.execute(postMethod, res);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return jsonResult;
    }
 
    @Override
    protected void onPostExecute(String strJson) {
      	...
       	switch(task){
       	...
       	case GET_TRANSPORTS:
       		try {
       			... // Изменение положения маркеров на карте в соответствии с новыми координатами 			
       		} catch (JSONException e) {
    			// TODO Auto-generated catch block
    			Log.e("log_tag", "Error parsing data " + e.toString());
    		}
       		Log.d(NET_LOG_TAG, strJson.toString());
       		break;
		...
       	}
        super.onPostExecute(strJson);
    }
}
3. AsyncTimer - хелпер, представляющий собой таймер, запускающий нужную функцию с нужной периодичностью. Описан внутри MainActivity.

Код: Выделить всё

static class AsyncTimer extends AsyncTask<String, Void, Void>{

	private int Tick = 1000;
	private String TaskName;
	private MainActivity parentHandler;
		
	AsyncTimer (MainActivity H){
		parentHandler = H;
	}
		
	void unLink() {
		parentHandler = null;
	}
		
	@Override
	protected Void doInBackground(String... params) {
		TaskName = params[0];
		if(params.length>1){
			Tick = Integer.parseInt(params[1]);
		}
		while (parentHandler!=null)
		{
			publishProgress();
			try{
				Thread.sleep(Tick);
			} catch (Exception xx){
				xx.toString();
			}
                }
		// TODO Auto-generated method stub
		return null;
	}
	
	protected void onProgressUpdate(Void... values) {
		switch(TaskName){
		case GET_TRANSPORTS:
       // Вызов метода, обновляющего положение на карте.
			parentHandler.getShuttle();
			break;
		}
    }		
}
Собственно, проблема заключается в том, что при пошаговом выполнении программы я вижу, как работает таймер в отдельном потоке. Вижу, что он успешно вызывает метод getShuttle() класса MainActivity, но запуска новой асинхронной задачи при этом не происходит и ошибок в логах никаких не видно.

Может быть, выбранный вариант попробовать заменить на связку AsyncTask -> Service ? Т.е. класс RequestTask сделать отдельным сервисом, и запрашивать у него данные из AsyncTimer с нужной периодичностью?

Я думаю, данную задачу можно решить несколькими способами, но пока моих знаний не хватает, что бы сделать это.

Аватара пользователя
Leeroy
Сообщения: 67
Зарегистрирован: 12 дек 2013, 21:25

Re: Проблема при использовании нескольких AsyncTask

Сообщение Leeroy » 10 окт 2014, 17:09

сервис - броадкаст ресивер - активити
В сервисе
while(true или какое вам надо условие){
Thread.sleep(интервал);
Что-то проверить;
Если есть данные отправить интент в броадкаст.
}
В броадкасте что-то сделать
Java Core -> JDBC -> GoF -> Android SDK ->...
Телепрограмма в твоем смарте Телепрограмма

Аватара пользователя
anber
Сообщения: 584
Зарегистрирован: 10 июн 2013, 15:05
Откуда: UA

Re: Проблема при использовании нескольких AsyncTask

Сообщение anber » 10 окт 2014, 17:24

Попробуй запускать AsynkTask методом
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
Личные сообщения с просьбой ответить на форуме или написать программу я просто удаляю, если я в хорошем настроении. Если в плохом добавляю автора в черный список. По любым другим вопросам feel free to write to me.

Аватара пользователя
KamiSempai
Сообщения: 1339
Зарегистрирован: 17 фев 2012, 21:23
Откуда: Мордор

Re: Проблема при использовании нескольких AsyncTask

Сообщение KamiSempai » 10 окт 2014, 18:13

По мне так тут лучше использовать связку AlarmManager - BroadcastRceiver - LocalBroadcastManager.
Всякий раз когда стоит выполнять задачу в определенное время или через длительный промежуток(минута - это уже длительный) лучше использовать AlarmManager.
При срабатывании AlarmManager запускается BroadcastRceiver и в нем выполняется AsyncTask который тянет данные с сервера. После загрузки шлется оповещение через LocalBroadcastManager (он есть в support v4). Активити при запуске регистрируется на получение сообщений от LocalBroadcastManager. Так как данные обновляются когда приложение работает можно хранить результат загрузки в статик переменной и вытаскивать их при получении сообщения об обновлении данных.
То есть:
1) Активити запустилась;
2) регистрируемся в LocalBroadcastManager;
3) назначаем AlarmManager-у сигнал через 1 минуту
4) Тут же запускаем AsyncTask который загружает данные из интернета
5) После загрузки ложим данные в public static переменную и шлем LocalBroadcastManager сигнал об окончании загрузки.
6) Активити получает сообщение берет данные и показывает их.

Когда сработает AlarmManager повторятся шаги 4-6.

После закрытия Активити, не забудте остановить AlarmManager, иначе он будет продолжать запускать загрузки в фоне.
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.

Кепыч
Сообщения: 2
Зарегистрирован: 08 окт 2014, 09:10

Re: Проблема при использовании нескольких AsyncTask

Сообщение Кепыч » 10 окт 2014, 20:47

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

Ответить