Скачивание большого файла (> 100 Мб) на Honeycomb в AsyncTask замедляет пользовательский интерфейс, возможно, из-за GC?

У меня есть частный внутренний класс под названием 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 во время загрузки, я вижу много сбора мусора. На самом деле это кажется постоянным. Я знаю, что GC может вызвать задержки в пользовательском интерфейсе, и моя теория такова, что здесь происходит. Кто-нибудь испытал это раньше? Есть ли лучший способ выполнить загрузку файла?

РЕДАКТИРОВАТЬ:

Вызов 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; } 

Во-первых, вы можете получить некоторую скорость, вызвав publishProgress (…) реже. Установите guard в doInBackground(...) поэтому он будет вызываться только каждые 100, 500, X миллисекунд.

Я не смог определить, сколько байтов считывается в буфер данных за раз. Т.е. in.read(data) считывает только до 1024 байтов за раз? Вместо этого вы можете использовать BufferedInputStream .

И примечание: если задача завершена успешно, вы не вызываете mWifiLock.release();

Intereting Posts
Как программно забыть беспроводную сеть в android? Как уменьшить размер изображения камеры при сохранении, используя намерение действия камеры? Каков правильный способ использования метода android.text.format.DateFormat.format Android GridVIew Изменение количества столбцов в зависимости от ориентации Как вы улавливаете URL-адреса, используя фильтр намерений с определенным значением параметра Android: настройка фона окна на запущенной Как использовать соединение с данными вместо WIFI, когда оба включены? AmazonServiceException: Пользователь не имеет права выполнять: dynamodb: DescribeTable Код состояния: 400; Код ошибки: AccessDeniedException Диалоговое окно GUI пользовательского распознавания голоса Android Просмотр сообщения в журналах: «приложение: тема устарела»? Android Аннотации: Аннотированный класс Xyz_ не находит его оригинальным («не может найти символ класса Xyz») Значения с плавающей запятой Android Seekbar от 0.0 до 2.0 Как подключиться к элементу Wifi ScanResult Удалить ошибку из EditText Как прослушивать изменение состояния в виджетах SwitchCompat?