Урок 86. AsyncTask. Знакомство, несложный пример

Обсуждение уроков
Аватара пользователя
damager82
Администратор
Сообщения: 1383
Зарегистрирован: 07 янв 2012, 11:32
Контактная информация:

Урок 86. AsyncTask. Знакомство, несложный пример

Сообщение damager82 » 10 июн 2012, 23:00

В этом уроке:
- создаем несложный пример с AsyncTask


Click here to read this article!
Последний раз редактировалось damager82 20 май 2017, 20:09, всего редактировалось 4 раза.
Добро пожаловать на форум сайта StartAndroid
ИзображениеИзображение

Аватара пользователя
rezak90
Сообщения: 3422
Зарегистрирован: 26 июн 2012, 13:22
Откуда: UA
Контактная информация:

Re: Урок 86. AsyncTask. Знакомство, несложный пример

Сообщение rezak90 » 06 сен 2012, 12:31

Что то не было проблем никогда с тасками, а сейчас всплыла проблема такого характера: делаю в AsyncTask'e sleep но экран блокируется (точнее он просто чёрный).

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

public class Example extends Activity {
	private AuthorizationTask task;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_example);
        init();
    }
    
    private void init() {
    	Log.i("MyTag", "name thread: " + Thread.currentThread().getName());
     	boolean isAuthorization = false;
    	task = new AuthorizationTask();
    	task.execute(5);
    	try {
			isAuthorization = task.get();
		} catch (InterruptedException e) {
			Log.i("MyTag", "InterruptedException in Example");
			e.printStackTrace();
		} catch (ExecutionException e) {
			Log.i("MyTag", "ExecutionException in Example");
			e.printStackTrace();
		}
    	if(isAuthorization) {
    		Log.i("MyTag", "authorization is true");
    		Intent intent = new Intent(this, ExampleTwo.class);
    		startActivity(intent);
    	}
    	else {
    		Log.i("MyTag", "authorization is false");
    		Intent intentLogin = new Intent(this, LoginActivity.class);
    		startActivity(intentLogin);
    	}
    }
    
    public class AuthorizationTask extends AsyncTask<Integer, Void, Boolean> {
    	
    	protected void onPreExecute() {
    		super.onPreExecute();
    	}
    	
    	protected void onProgressUpdate(Void... value) {
    		super.onProgressUpdate(value);
    		
    	}
    	
    	@Override
    	protected Boolean doInBackground(Integer... params) {
    		Log.i("MyTag", "name thread: " + Thread.currentThread().getName());
    		for(int i = 0; i < params[0]; i++) {
    			try {
    				TimeUnit.SECONDS.sleep(1);
    			} catch (InterruptedException e) {
    				Log.i("MyTag", "InterruptedException in doInBackground");
    				e.printStackTrace();
    			}
    		}
    		return new Boolean(false);
    	}
    	
    	protected void onPostExecute(Boolean result) {
    		super.onPostExecute(result);
    	}

    }

}
sleep происходит в другом потоке, но почему тогда чёрный экран? почему тогда активити ждёт завершения AsyncTaska а потом уже вываливает экран.
R.id.team
Политика на форуме запрещена

Аватара пользователя
rezak90
Сообщения: 3422
Зарегистрирован: 26 июн 2012, 13:22
Откуда: UA
Контактная информация:

Re: Урок 86. AsyncTask. Знакомство, несложный пример

Сообщение rezak90 » 06 сен 2012, 12:35

а если убрать isAuthorization = task.get(); то sleep'a вообще не происходит, то есть сразу грузится экран.
R.id.team
Политика на форуме запрещена

AndreyI
Сообщения: 372
Зарегистрирован: 14 май 2012, 16:18

Re: Урок 86. AsyncTask. Знакомство, несложный пример

Сообщение AndreyI » 06 сен 2012, 12:54

попробуй init () перенести в onStart() или в onResume().
У меня тоже бывало возникали глюки с onCreate()

Аватара пользователя
rezak90
Сообщения: 3422
Зарегистрирован: 26 июн 2012, 13:22
Откуда: UA
Контактная информация:

Re: Урок 86. AsyncTask. Знакомство, несложный пример

Сообщение rezak90 » 06 сен 2012, 13:22

не помогло.
R.id.team
Политика на форуме запрещена

AndreyI
Сообщения: 372
Зарегистрирован: 14 май 2012, 16:18

Re: Урок 86. AsyncTask. Знакомство, несложный пример

Сообщение AndreyI » 06 сен 2012, 13:54

Ну все правильно, task.get() останавливает UI поток и ждет выполнения задачи.
Эту задачу нужно подругому решать, я бы использовал onPreExecute и onPostExecute они выполняются в UI потоке

Аватара пользователя
rezak90
Сообщения: 3422
Зарегистрирован: 26 июн 2012, 13:22
Откуда: UA
Контактная информация:

Re: Урок 86. AsyncTask. Знакомство, несложный пример

Сообщение rezak90 » 06 сен 2012, 14:05

это понятно, но задержку нужно выполнить допустим на 5 секунд, и это нужно делать в другом потоке что бы не блакировать основной, к тому же в основном будет progressbar работать.
R.id.team
Политика на форуме запрещена

math64
Сообщения: 235
Зарегистрирован: 16 июл 2012, 07:47

Re: Урок 86. AsyncTask. Знакомство, несложный пример

Сообщение math64 » 06 сен 2012, 14:29

Тогда никаких тасков не нужно - вот например, у меня запускается из onCreate():

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

	private void newGame() {
		showDialog(PROGRESS_DIALOG, null);
		Thread t = new Thread() {
			@Override
			public void run() {
				model.newGame();
				dismissDialog(PROGRESS_DIALOG);
			}
		};
		t.start();
	}

3Gern
Сообщения: 25
Зарегистрирован: 30 июл 2012, 13:32

Re: Урок 86. AsyncTask. Знакомство, несложный пример

Сообщение 3Gern » 09 сен 2012, 18:35

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

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

private ArrayList<String> listTitle = new ArrayList<String>();
private ArrayList<String> listLink = new ArrayList<String>();
private String[] arrayTitle = new String[]{"..."};
private String[] arrayLink = new String[]{"..."};

public void onCreate...{
pd = ProgressDialog.show(this, "Working...", "request to server", true, false);
new ParseSite().execute("http://www...");
}
private class ParseSite extends AsyncTask<String, Void, String[]>{
@Override
	protected String[] doInBackground(String... params) {
		try {
			String html = params[0];
			Document doc = Jsoup.connect(html).get();
			listTitle.clear();
			listLink.clear();
			for (Element link : doc.select("div")){
				// Получаю массив из ссылок и содержимых href
				}
				arrayTitle = ConvertToStringArray(listTitle);
				arrayLink = ConvertToStringArray(listLink);
		}
		catch (IOException e) {}
			return null;
	}

	protected void onPostExecute(String[] arrayTitle) {
               pd.dismiss();
	       lvNews = (ListView)findViewById(R.id.lvNews);
	       ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, 
					R.layout.list_news, arrayTitle);
	       lvNews.setAdapter(adapter);
	    }
	}

3Gern
Сообщения: 25
Зарегистрирован: 30 июл 2012, 13:32

Re: Урок 86. AsyncTask. Знакомство, несложный пример

Сообщение 3Gern » 11 сен 2012, 19:10

прогресс бар бесконечно крутиться (( убрал вот эти строчки

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

lvNews = (ListView)findViewById(R.id.lvNews);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
       R.layout.list_news, arrayTitle);
lvNews.setAdapter(adapter);

math64
Сообщения: 235
Зарегистрирован: 16 июл 2012, 07:47

Re: Урок 86. AsyncTask. Знакомство, несложный пример

Сообщение math64 » 12 сен 2012, 08:27

3Gern, выбросьте массивы - они не нужны. Оставьте только списки. Адаптер принимает список в качестве аргумента.
В doInBackground() после нахождения ссылки вызывайте publishProgress();
В onProgressUpdate() обновляйте списки - и информруйте ListView что список изменился с помощью notifyDataSetChanged().
Пользователь сможет кликать на уже загруженные ссылки даже пока идёт загрузка.
Но прогрессбар крутится, означая что загрузка продолжается.
В onPostExecute() убираете прогрессбар.

Umix
Сообщения: 3
Зарегистрирован: 17 сен 2012, 08:16

Re: Урок 86. AsyncTask. Знакомство, несложный пример

Сообщение Umix » 17 сен 2012, 09:35

Столкнулся со следующей ситуацией:
- при завершении задачи с использованием AsyncTask поток почему-то разрушается и создается новый при выполнении новой задачи;
- при работе с потоками "по-старинке" (пусть и сложновато, да еще и сохраняются корявости при повороте экрана) поток создается и разрушается как ему положено

об этих выводах ярко повествует мониторинг потоков
Вопрос таков, что выгоднее и правильнее???

Umix
Сообщения: 3
Зарегистрирован: 17 сен 2012, 08:16

Re: Урок 86. AsyncTask. Знакомство, несложный пример

Сообщение Umix » 24 сен 2012, 15:05

так что никто не сталкивался с такой ситуацией?

Аватара пользователя
rezak90
Сообщения: 3422
Зарегистрирован: 26 июн 2012, 13:22
Откуда: UA
Контактная информация:

Re: Урок 86. AsyncTask. Знакомство, несложный пример

Сообщение rezak90 » 24 сен 2012, 15:08

при работе с потоками "по-старинке" (пусть и сложновато, да еще и сохраняются корявости при повороте экрана) поток создается и разрушается как ему положено
правильно поток и будет пересоздаваться так как при повороте экрана активити "пересеоздаётся"
- при завершении задачи с использованием AsyncTask поток почему-то разрушается и создается новый при выполнении новой задачи;
а вот здесь не понятно что имеете в виду, скорее всего не правильно построили поток
R.id.team
Политика на форуме запрещена

math64
Сообщения: 235
Зарегистрирован: 16 июл 2012, 07:47

Re: Урок 86. AsyncTask. Знакомство, несложный пример

Сообщение math64 » 24 сен 2012, 17:18

А это уж как запрограммируете. Ни AsyncTask, ни Thread не уничтожаются при повороте экрана. Но если не принять сооветствующих мер - результат будет выводиться в старые View (которые как раз пересоздаются при повороте).
Как это делать, расказано в следующих уроках.

Umix
Сообщения: 3
Зарегистрирован: 17 сен 2012, 08:16

Re: Урок 86. AsyncTask. Знакомство, несложный пример

Сообщение Umix » 28 сен 2012, 13:09

Да нет вопрос не про уничтожение потока при повороте экрана. Интересует то, что СПЕЦИАЛЬНО СДЕЛАННЫЙ ДЛЯ УДОБСТВО МЕХАНИЗМ AsyncTask оставляет исполняемый поток в памяти, после исполнения и закрытия такого, и при вызове снова действия, разделенного на потоки создает новый и т.д.
Thread - после разрушения пропадает.
Все ето можно наблюдать в Debug

math64
Сообщения: 235
Зарегистрирован: 16 июл 2012, 07:47

Re: Урок 86. AsyncTask. Знакомство, несложный пример

Сообщение math64 » 28 сен 2012, 17:11

А почему он должен убиваться при повороте экрана? Он продолжает работать, работать и работать - пока Вы его сами не остановите - впрочем, так же как и Thread - ведь при этом его не обазательно останавливать, достаточно его перенастроить.
А если при повороте экрана Вы не разовравжись запускаете второй экземпляр AsyncTask - тоже Ваши проблемы. Вдруг и в самом деле нужен второй AsyncTask ?

AndreyI
Сообщения: 372
Зарегистрирован: 14 май 2012, 16:18

Re: Урок 86. AsyncTask. Знакомство, несложный пример

Сообщение AndreyI » 28 сен 2012, 18:22

Umix писал(а):Да нет вопрос не про уничтожение потока при повороте экрана. Интересует то, что СПЕЦИАЛЬНО СДЕЛАННЫЙ ДЛЯ УДОБСТВО МЕХАНИЗМ AsyncTask оставляет исполняемый поток в памяти, после исполнения и закрытия такого, и при вызове снова действия, разделенного на потоки создает новый и т.д.
Thread - после разрушения пропадает.
Все ето можно наблюдать в Debug
В Андроид вообще никакие объекты не уничтожаются немедленно после использования, за это отвечает сборщик мусора и мы не можем никак повлиять на его работу. Можно, конечно, вызвать System.gc() но даже в этом случае разработчики Андроид не гарантируют, что он будет немедленно вызван и почистит всю память от всех неиспользуемых объектов, этой командой мы лишь уведомляем систему, что наступил удобный момент для уборки мусора.
Вообще не вижу причин для беспокойства, ну и пусть они висят DDMS, мне так они не мешают.

Что касается AsyncTasks, то его изначально планировалось использовать для разовых, коротких задач:
AsyncTasks в идеале, должны быть использованы для коротких операций (несколько секунд, не больше.) Если вам нужно сохранять потоки в течение длительного периода времени, то настоятельно рекомендуется использовать различные API, предоставляемые пакетом java.util.concurrent , таких как Executor, ThreadPoolExecutor и FutureTask

Tuhlom
Сообщения: 6
Зарегистрирован: 22 ноя 2012, 18:41

Re: Урок 86. AsyncTask. Знакомство, несложный пример

Сообщение Tuhlom » 22 ноя 2012, 19:10

У меня такая проблема: пытаюсь заранее создать содержимое activity с множеством View, чтобы при его вызове оно показывалось мгновенно(иначе примерно 2 секунды загружается). Как я понял, это должно получиться реализовать с помощью создания в AsyncTask, вызываемом в MainActivity, нового View, содержащего в себе все это множество вьюшек, и потом при вызове этого тяжёлого activity просто добавить в него уже созданный в предыдущем activity View.
Но столкнулся с такой проблемой, что в doInBackground не получается создать новый элемент View, так как непонятно что писать в параметры при его создании:

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

LinearLayout linLayout = new LinearLayout(context);
Методы getContext() и getBaseContext() не работают... Что делать в такой ситуации?

P.S.: Я недавно начал программировать под Андройд, и, возможно, это не самый лучший способ реализовать предварительное создание тяжёлого Acivity...

AndreyI
Сообщения: 372
Зарегистрирован: 14 май 2012, 16:18

Re: Урок 86. AsyncTask. Знакомство, несложный пример

Сообщение AndreyI » 22 ноя 2012, 19:31

Обычно, если в классе нужен контекст активити или приложения, то его туда передают в конструкторе и вызывают его методы через него:

public class MyAsyncTask extends AsyncTask {

private Context mContext;

public MyAsyncTask (Context context){

this.mContext=context;

}


...

И вызывают методы контекста или передают его где нужно в конструкторы View

LinearLayout linLayout = new LinearLayout(mContext);



А в Activity передают ссылку на свой контекст (т.е. на себя) при создании объекта

MyAsyncTask myTask = new MyAsyncTask(this);

Ответить