У меня есть личный внутренний класс DownloadFileAsyncTask в одном из моих занятий. Я прикрепил это:
private class DownloadFileAsyncTask extends AsyncTask<URL, Integer, Boolean> {
private static final String TAG = "DownloadFileAsyncTask";
@Override
protected void onPreExecute() {
WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
mWifiLock = manager.createWifiLock("wifilock");
mWifiLock.acquire();
}
@Override
protected Boolean doInBackground(URL... params) {
try {
URLConnection urlConnection = params[0].openConnection();
urlConnection.connect();
InputStream in = urlConnection.getInputStream();
FileOutputStream out = openFileOutput("archive.zip", Context.MODE_PRIVATE);
int fileSize = urlConnection.getContentLength();
if (fileSize == 0) {
return false;
}
int downloadedSize = 0;
byte[] data = new byte[1024];
int count = 0;
while ((count = in.read(data)) != -1) {
if (isCancelled()) {
Log.d(TAG, "Download cancelled.");
out.close();
in.close();
return false;
}
out.write(data, 0, count);
downloadedSize += count;
publishProgress(downloadedSize, fileSize);
}
out.close();
in.close();
}
catch (Exception ex) {
Log.e(TAG, "doInBackground()", ex);
return false;
}
return true;
}
@Override
protected void onProgressUpdate(Integer... values) {
int downloadedSize = values[0];
int fileSize = values[1];
int progressPercent = ((int) ((downloadedSize / (float) fileSize) * 100));
mDownloadButton.setText(String.format("%.1f MB", downloadedSize / 1048576f));
mProgressBar.setProgress(progressPercent);
}
@Override
protected void onPostExecute(Boolean result) {
}
@Override
protected void onCancelled() {
mWifiLock.release();
}
}
Этот код работает. Файл загружен, и мой ProgressBar обновлен правильно. У меня также есть кнопка отмены, которую пользователь может нажать, чтобы закрыть загрузку. Это также работает, однако, когда я нажимаю кнопку, регистрация кнопки занимает несколько секунд (я тестирую на оборудовании). Когда я смотрю logcat во время загрузки, я вижу, что происходит много мусора. На самом деле, это кажется постоянным. Я знаю, что сборщик мусора может вызвать задержки в пользовательском интерфейсе, и моя теория заключается в том, что именно здесь происходит. Кто-нибудь испытывал это раньше? Есть ли лучший способ выполнить загрузку файла?
EDIT:
Вызов publishProgress () в конце каждой итерации основного цикла вызывал задержки. Вот обновленный код doInBackground () для решения проблемы:
@Override
protected Boolean doInBackground(URL... params) {
try {
URLConnection urlConnection = params[0].openConnection();
urlConnection.connect();
BufferedInputStream in = new BufferedInputStream(urlConnection.getInputStream());
BufferedOutputStream out = new BufferedOutputStream(openFileOutput("archive.zip", Context.MODE_PRIVATE));
int fileSize = urlConnection.getContentLength();
if (fileSize == 0) {
return false;
}
int downloadedSize = 0;
byte[] data = new byte[1024];
int count = 0;
Calendar lastUpdate = Calendar.getInstance();
while ((count = in.read(data)) != -1) {
if (isCancelled()) {
Log.d(TAG, "Download cancelled.");
out.close();
in.close();
return false;
}
out.write(data, 0, count);
downloadedSize += count;
Calendar now = Calendar.getInstance();
if (now.getTimeInMillis() - lastUpdate.getTimeInMillis() >= 500) {
lastUpdate = now;
publishProgress(downloadedSize, fileSize);
}
}
out.close();
in.close();
}
catch (Exception ex) {
Log.e(TAG, "doInBackground()", ex);
return false;
}
return true;
}