Загрузка файла на Android с отображением прогресса в ProgressDialog
Я пытаюсь написать простое приложение, которое будет обновляться. Для этого мне нужна функция, которая может загружать файл и показывать текущий прогресс в ProgressDialog
. Я знаю, как реализовать ProgressDialog
, но не понимаю, как отобразить текущий прогресс и как на самом деле загрузить файл.
5 ответ(ов)
Не забудьте добавить разрешения в файл манифеста, если вы планируете загружать данные из интернета!
Вот пример, как должен выглядеть ваш файл манифеста:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.helloandroid"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="10" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<application
android:icon="@drawable/icon"
android:label="@string/app_name"
android:debuggable="true">
</application>
</manifest>
Обратите внимание, что каждый <uses-permission>
элемент должен быть закрыт, либо с помощью символа /
, что указано в примере, либо с помощью отдельного закрывающего тега. Это необходимо для правильной обработки разрешений в вашем приложении.
Да, приведенный выше код будет работать. Однако, если вы обновляете ваш ProgressBar
в методе onProgressUpdate
вашего AsyncTask
, а затем нажимаете кнопку "Назад" или завершаете вашу активность, AsyncTask
теряет связь с вашим пользовательским интерфейсом. И когда вы вернетесь к вашей активности, даже если загрузка продолжается в фоновом режиме, вы не увидите обновлений на ProgressBar
. Поэтому в методе onResume()
попробуйте запустить поток с использованием runOnUiThread
и таймера, который будет обновлять ваш ProgressBar
с значениями от AsyncTask
, работающего в фоновом режиме.
Вот пример кода, который может вам помочь:
private void updateProgressBar(){
Runnable runnable = new UpdateProgress();
background = new Thread(runnable);
background.start();
}
public class UpdateProgress implements Runnable {
public void run() {
while(Thread.currentThread() == background) {
try {
Thread.sleep(1000);
Message msg = new Message();
progress = getProgressPercentage();
handler.sendMessage(msg);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (Exception e) {
// Обработка других исключений
}
}
}
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
progress.setProgress(msg.what);
}
};
Не забудьте уничтожить поток, когда ваша активность не видима:
private void destroyRunningThreads() {
if (background != null) {
background.interrupt();
background = null;
}
}
Таким образом, вы сможете поддерживать актуальное состояние прогресс-бара даже после изменения состояния активности.
Ваш подход к созданию класса AsyncTask
с обработкой ProgressDialog
кажется разумным и может быть полезным для многократного использования в различных контекстах. Вот что вам следует учесть:
Конструктор: Вы создали конструктор, который принимает контекст, целевой файл и сообщение для диалогового окна, что позволяет легко переиспользовать класс
DownloadTask
в разных активностях.Показ диалога загрузки: Вы вызываете
mPDialog.show()
вonPreExecute()
, чтобы показать диалог перед началом фоновой операции — это хороший подход, который дает пользователю знать, что загрузка началась.Обработка прогресса: Использование
publishProgress()
и обновлениеProgressDialog
вonProgressUpdate()
позволяет пользователю видеть прогресс загрузки, что улучшает пользовательский опыт.Управление ресурсами: Отлично, что вы освобождаете
WakeLock
и закрываете потоки в блокеfinally
— это помогает предотвратить утечки памяти и другие проблемы с ресурсами.Уведомления об ошибках: Вы уведомляете пользователя о статусе загрузки, что важно для информирования о возможных проблемах.
Несмотря на это, стоит быть внимательным к следующим моментам:
Обработка исключений: В вашем коде вы просто возвращаете строку при возникновении исключения. Возможно, имеет смысл обработать эти исключения более детально или использовать собственный механизм логирования. Это может помочь лучше понять, что пошло не так в случае ошибки.
Закрытие диалога: Убедитесь, что
ProgressDialog
корректно закрывается даже в случае возникновения исключений, чтобы избежать зависания диалога.Совместимость: Учтите, что использование
AsyncTask
в некоторых случаях может быть не самым оптимальным способом для выполнения асинхронных задач в современных приложениях Android. Рассмотрите возможность использованияWorkManager
или других подходов для длительных фоновых задач, особенно если они могут продолжаться после закрытия активности.
Если этот класс отвечает вашим требованиям и вы уверены, что обработка ошибок и ресурсоемкость соответствуют вашим стандартам, можете смело использовать его в своих проектах!
Не забудьте заменить "/sdcard..." на new File("/mnt/sdcard/..."), иначе вы получите FileNotFoundException.
Во время изучения разработки под Android я узнал, что ProgressDialog
- это предпочтительный вариант для отображения прогресса загрузки. У ProgressDialog
есть метод setProgress
, который можно использовать для обновления уровня прогресса по мере загрузки файла.
Наилучшие примеры, которые я видел в многих приложениях, заключаются в том, что они настраивают атрибуты диалога прогресса, чтобы придать ему более привлекательный вид по сравнению с стандартной версией. Это хорошо, так как помогает удерживать пользователя в ожидании с помощью различных анимаций, таких как лягушки, слоны или милые котята/щенки. Любая анимация в диалоге прогресса привлекает внимание пользователей, и они не чувствуют, что ждут слишком долго.
Как исправить 'android.os.NetworkOnMainThreadException'?
Ошибка «Необходимо переопределить метод суперкласса» после импорта проекта в Eclipse
Почему в RecyclerView отсутствует onItemClickListener()?
Не удается запустить Eclipse - Java был запущен, но вернул код завершения = 13
Как вызвать метод с задержкой в Android