Работа с UI из AsyncTask вынесенного в отдельный файл

Activity Lifecycle, Saving Activity State, Managing Tasks, Intent, Intent Filter
Ответить
NapalmRain
Сообщения: 34
Зарегистрирован: 04 июн 2014, 10:21

Работа с UI из AsyncTask вынесенного в отдельный файл

Сообщение NapalmRain » 05 июн 2014, 18:29

Доброго всем времени суток!
Есть класс для работы с API сайта.
он наследуется от AsyncTask, что бы отправлять сетевые запросы в отдельном потоке.
Когда этот класс прописан внутри текущей Activity проблем нет, но я захотел вынести его в отдельный файл, что бы не писать один и тот же класс в каждой активити, где нужно использовать API, но тут столкнулся с проблемой, что даже в onPre... и onPostExecute я не могу обращаться к view объектам, что и понятно, их же в этом классе нет и быть не может, но вот как ему передать туда ссылки на эти объекты, понять не могу.

Для примера в тестовом приложении взял код из урока

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

class siteapi extends AsyncTask<String, Void, Void> {
    	protected void onPreExecute() {
    	      super.onPreExecute();
    	      Toast.makeText(MainActivity.this, "Выполняется подключение", Toast.LENGTH_LONG).show();
    	      progBar.setVisibility(0);
    	    }
        @Override
        protected Void doInBackground(String... funcs) {
        	try {
        		TimeUnit.SECONDS.sleep(2);
        	} catch (InterruptedException e) {
        		e.printStackTrace();
        	}
        	return null;
        }

        @Override
        protected void onPostExecute(Void result) {
        	super.onPostExecute(result);
        	progBar.setVisibility(4);
        	Toast.makeText(MainActivity.this, "Выполнено", Toast.LENGTH_LONG).show();
        }
Если создать этот класс в отдельном файле, то в строках

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

Toast.makeText(MainActivity.this, "Выполняется подключение", Toast.LENGTH_LONG).show();
progBar.setVisibility(0);
Буду получать ошибку.
Буду очень признателен, если мне пояснят, как решить данную проблему.

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

Re: Работа с UI из AsyncTask вынесенного в отдельный файл

Сообщение KamiSempai » 05 июн 2014, 23:59

Экземпляр класса siteapi создаётся в активити?
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.

NapalmRain
Сообщения: 34
Зарегистрирован: 04 июн 2014, 10:21

Re: Работа с UI из AsyncTask вынесенного в отдельный файл

Сообщение NapalmRain » 06 июн 2014, 07:16

KamiSempai писал(а):Экземпляр класса siteapi создаётся в активити?
Да.
По нажатию на кнопку создаётся экземпляр и вызывается execute

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

public void onClick(View v) {
		switch (v.getId()) {
		 case R.id.AuthButton:
			 SApi = new siteapi();
			 SApi.execute("funcname");
			 break;
		 }
		
	}

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

Re: Работа с UI из AsyncTask вынесенного в отдельный файл

Сообщение Foenix » 06 июн 2014, 07:51

я класс Thread использую. Там мне как-то даже проще и понятнее.
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

NapalmRain
Сообщения: 34
Зарегистрирован: 04 июн 2014, 10:21

Re: Работа с UI из AsyncTask вынесенного в отдельный файл

Сообщение NapalmRain » 06 июн 2014, 08:00

Foenix писал(а):я класс Thread использую. Там мне как-то даже проще и понятнее.
Ну AsyncTask меня подкупил тем, что мне не нужно создавать собственный поток...
Но тем не менее.
Предположим, что мы работаем через thread, но класс для работы с ним так же выделен в отдельный файл, как оттуда воздействовать на элементы интерфейса?

Аватара пользователя
adarash
Сообщения: 333
Зарегистрирован: 17 июл 2013, 09:59

Re: Работа с UI из AsyncTask вынесенного в отдельный файл

Сообщение adarash » 06 июн 2014, 09:19

А кто нибуть пользуется AndroidAnnotashion?

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

Re: Работа с UI из AsyncTask вынесенного в отдельный файл

Сообщение KamiSempai » 06 июн 2014, 09:36

NapalmRain писал(а):
KamiSempai писал(а):Экземпляр класса siteapi создаётся в активити?
Да.
По нажатию на кнопку создаётся экземпляр и вызывается execute
Как вариант можно сделать вот так:[syntax=java]public void onClick(View v) {
switch (v.getId()) {
case R.id.AuthButton:
SApi = new siteapi() {

@Override
protected void onPreExecute() {
// Ваш код...
}

@Override
protected void onPostExecute(Void result) {
// Ваш код...
}
};
SApi.execute("funcname");
break;
}
}[/syntax]Если же нужен доступ к неким переменным из siteapi то лучше возвращать их как результат.

PS: Замечание по поводу названия класса. Название класса лучше начинать с заглавной буквы, все последующие слова тоже помечаются заглавными в первой букве, в абревиатурах, таких как API, заглавной пишется только первая буква. Если следовать этим правилам, то имя вашего класса стоит писать как "SiteApi". Так читаемость на много выше и сразу понятно, что это класс а не переменная. Переменные лучше начинать с маленькой буквы.
R.id.team
Хватит таскать макулатуру на тренировку! Используй T Note.

NapalmRain
Сообщения: 34
Зарегистрирован: 04 июн 2014, 10:21

Re: Работа с UI из AsyncTask вынесенного в отдельный файл

Сообщение NapalmRain » 06 июн 2014, 09:41

adarash писал(а):А кто нибуть пользуется AndroidAnnotashion?
Я, честно признаться, даже не слышал о нём.

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

Re: Работа с UI из AsyncTask вынесенного в отдельный файл

Сообщение Foenix » 06 июн 2014, 10:03

NapalmRain писал(а):
Foenix писал(а):я класс Thread использую. Там мне как-то даже проще и понятнее.
Ну AsyncTask меня подкупил тем, что мне не нужно создавать собственный поток...
Но тем не менее.
Предположим, что мы работаем через thread, но класс для работы с ним так же выделен в отдельный файл, как оттуда воздействовать на элементы интерфейса?
аналогично асинктаску)) через handler-ы
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

NapalmRain
Сообщения: 34
Зарегистрирован: 04 июн 2014, 10:21

Re: Работа с UI из AsyncTask вынесенного в отдельный файл

Сообщение NapalmRain » 06 июн 2014, 10:24

KamiSempai писал(а):Если же нужен доступ к неким переменным из siteapi то лучше возвращать их как результат.

PS: Замечание по поводу названия класса. Название класса лучше начинать с заглавной буквы, все последующие слова тоже помечаются заглавными в первой букве, в абревиатурах, таких как API, заглавной пишется только первая буква. Если следовать этим правилам, то имя вашего класса стоит писать как "SiteApi". Так читаемость на много выше и сразу понятно, что это класс а не переменная. Переменные лучше начинать с маленькой буквы.
Благодарю за идею! Честно, не знал, что можно так переопределять методы...
Попробую.
А по имени классов и переменных - я в курсе)) Данный код не более чем пример. В оригинале класс называется SitenameAPI (понятное дело где Sitename - это имя домена).

Viewer
Сообщения: 180
Зарегистрирован: 30 апр 2014, 11:42

Re: Работа с UI из AsyncTask вынесенного в отдельный файл

Сообщение Viewer » 06 июн 2014, 17:34

Еще как вариант, можете передавать ссылку на MainActivity в ваш siteapi, к примеру, через конструктор класса, ну или через сеттер
[syntax=java]
class siteapi extends AsyncTask<String, Void, Void> {
MainActivity mActivity;

siteapi (Activity activity){
mActivity=activity;
}

protected void onPreExecute() {
...[/syntax]

и работать с объектами MainActivity через ссылку на mActivity

Тогда запускать AsyncTask из Activity нужно так
new siteapi(MainActivity.this).execute("funcname");

Но тогда нужно будет еще предусмотреть передачу новой ссылки на объект MainActivity при повороте экрана(при повороте Activity пересоздается, и если поворот произошел за время выполнения AsyncTask, то обращение к необновленному mActivity будет бессмысленным).

Этот способ передачи ссылок на объекты в статические классы через конструктор достаточно стандартен для JAVA, поэтому я и привел его вам скорее на будущее, чем для решения этой конкретной задачи, для неё он будет сильно громоздок и я бы сказал коряв.

А для вашей задачи вариант предложенный KamiSempai более чем изящен и убивает сразу всех зайцев. Тем более что, если вы хотите использовать один и тот же код для разных Activity, то полюбому у них будут разные экранные компоненты и методы onPreExecute() и onPostExecute для них наверняка нужны будут разные, универсальным достаточно сделать только doInBackground().
Насчет синтаксиса он тоже прав, лучше сразу привыкать, даже когда вы пишете код для примера :)

Ответить