Відповідь, надана @Romain Guy, є правильною. Тим не менше, я хотів би додати доповнення до інформації та вказати вказівник на бібліотеку або 2, які можна використовувати для тривалої роботи AsyncTask і навіть більше для мережево орієнтованих асинктаз.
AsyncTasks розроблені для роботи у фоновому режимі. І так, ви можете зупинити це, використовуючи cancel
метод. Завантажуючи матеріали з Інтернету, настійно рекомендую подбати про свою нитку, коли вона перебуває у стані блокування вводу- виводу . Ви повинні організувати завантаження таким чином:
public void download() {
while( inputStream.read(buffer) != -1 && !Thread.interrupted() ) {
}
}
Використання Thread.interrupted
прапора допоможе вашому потоку правильно вийти із блокуючого стану io. Ваш потік буде більш реагувати на виклик cancel
методу.
Недолік дизайну AsyncTask
Але якщо ваш AsyncTask триває занадто довго, тоді ви зіткнетеся з двома різними проблемами:
- Діяльність погано прив’язана до життєвого циклу діяльності, і ви не отримаєте результату своєї AsyncTask, якщо ваша діяльність помре. Справді, так, ви можете, але це буде грубий шлях.
- AsyncTask не дуже добре задокументовані. Наївне, хоч і інтуїтивне, впровадження та використання асинктаску може швидко призвести до витоків пам'яті.
RoboSpice , бібліотека, яку я хотів би представити, використовує фонову службу для виконання такого роду запитів. Він розроблений для мережевих запитів. Він надає додаткові функції, такі як автоматичне кешування результатів запитів.
Ось причина, чому AsyncTasks погані для тривалих завдань. Наступне міркування - це адаптація до мотивацій RoboSpice : додаток, який пояснює, чому використання RoboSpice задовольняє потреби в платформі Android.
Життєвий цикл AsyncTask та Activity
AsyncTasks не відповідають життєвому циклу екземплярів Activity. Якщо ви запустите AsyncTask всередині Activity і обернете пристрій, Activity буде знищено та створено новий екземпляр. Але AsyncTask не помре. Він буде продовжувати жити, поки не завершиться.
І коли він завершиться, AsyncTask не буде оновлювати інтерфейс нової активності. Дійсно, він оновлює попередній екземпляр діяльності, який більше не відображається. Це може призвести до винятку типу java.lang.IllegalArgumentException: подання, не приєднане до диспетчера вікон, якщо ви використовуєте, наприклад, findViewById для отримання подання всередині Activity.
Проблема витоку пам'яті
Дуже зручно створювати AsyncTasks як внутрішні класи вашої діяльності. Оскільки AsyncTask потрібно буде маніпулювати поданнями Activity, коли завдання завершено або виконується, використання внутрішнього класу Activity здається зручним: внутрішні класи можуть отримувати безпосередній доступ до будь-якого поля зовнішнього класу.
Тим не менше, це означає, що внутрішній клас буде мати невидиму посилання на свій екземпляр зовнішнього класу: Activity.
У довгостроковій перспективі це спричиняє витік пам’яті: якщо AsyncTask триває довго, він зберігає активність «живою», тоді як Android хотів би позбутися від неї, оскільки вона більше не може відображатися. Діяльність не може бути зібрана сміття, і це центральний механізм для Android для збереження ресурсів на пристрої.
Прогрес вашого завдання буде втрачено
Ви можете використовувати деякі обхідні шляхи, щоб створити тривалий асинктаск та керувати його життєвим циклом відповідно до життєвого циклу діяльності. Ви можете або скасувати AsyncTask у методі onStop своєї діяльності, або дозволити асинхронному завданню закінчитись, а не втратити його прогрес і зв’язати його з наступним екземпляром вашої діяльності .
Це можливо, і ми показуємо, як у мотиваціях RobopSpice, але це ускладнюється, а код насправді не є загальним. Більше того, ви все одно втратите хід свого завдання, якщо користувач залишить діяльність і повернеться. Ця сама проблема виникає з Loaders, хоча це було б простішим еквівалентом AsyncTask із зазначеним вище обхідним способом обходу.
Використання служби Android
Найкращий варіант - скористатися послугою для виконання ваших тривалих фонових завдань. І це саме рішення, запропоноване RoboSpice. Знову ж таки, він призначений для роботи в мережі, але його можна поширити і на не пов’язані з мережею матеріали. Ця бібліотека має велику кількість функцій .
Ви навіть можете зрозуміти це менш ніж за 30 секунд завдяки інфографіці .
Насправді дуже погана ідея використовувати AsyncTasks для тривалих операцій. Тим не менше, вони чудово підходять для короткоживучих, таких як оновлення подання через 1 або 2 секунди.
Я закликаю вас завантажити додаток RoboSpice Motivations , він справді пояснює це поглиблено, а також надає зразки та демонстрації різних способів робити деякі речі, пов’язані з мережею.
Якщо ви шукаєте альтернативу RoboSpice для не пов'язаних з мережею завдань (наприклад, без кешування), ви також можете поглянути на Tape .