Загрузка и хранение списка изображений с URL

Я новичок в андроид студии и пытаюсь сделать следующее. В модельном объекте есть список объектов, каждый из которых может содержать внутренние и внешние изображения. Я прочитал, что не могу обработать URL-запрос в основном потоке, поэтому я подумал об использовании AsyncTask . Но мне также нужно знать, когда обрабатывалось одно изображение ... поэтому я подумал об использовании execute().get() , но я также думаю, что это не работает. Я также подумал, что смогу загружать и хранить все изображения последовательно с исходным кодом, который приведен ниже ... Но каким-то образом я в основном задании получаю ответ до того, как все загрузки будут завершены. И чтобы сделать вещи более странными, да, я могу загружать / сохранять изображения, но каким-то образом они все имеют одинаковый размер 48 бит, и когда я пытаюсь открыть изображение, все "черное" .... Я думаю, что как-то, есть общие переменные с этим потоком ....

Я уверен, что мой код полон недостатков, и некоторая часть кода повторяется (я мог бы сделать некоторый рефакторинг кода) ... но ... пока я только ищу, чтобы это заработало.

Есть идеи? Не стесняйтесь бросать мой код и указывать на другие подходы, если вы думаете, что это будет лучше. Спасибо.

public void ProcessImages(MyModel model) {
    if (model == null || model.History == null || model.History .size() == 0) {
        return;
    }
    model.History .forEach((h) -> {
        if (h.InternalImages != null && h.InternalImages.size() > 0) {
            h.InternalImages.forEach((i) -> {
                ExecuteSaveToInternalStorage(i);
                return;
            });
        }
        if (h.ExternalImages != null && h.ExternalImages.size() > 0) {
            h.ExternalImages.forEach((i) -> {
                ExecuteSaveToInternalStorage(i);
                return;
            });
        }
    });
}

,

public void ExecuteSaveToInternalStorage(LKImage lkImage){
    try {
        (new AsyncTask<Void,Void,Void>() {

            @Override
            protected Void doInBackground(Void... voids) {
                SaveToInternalStorage(lkImage);
                return null;
            }

            @Override
            protected void onPostExecute(Void aVoid) {
                //multiTaskHandler.taskComplete();
            }
        }).execute().get();
    } catch (ExecutionException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

,

public boolean SaveToInternalStorage(LKImage lkImage) {
    String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString() + File.separator + ImageDirectory;
    File outputDir = new File(path);
    if (!outputDir.exists()) {
        outputDir.mkdir();
    }
    boolean res = true;
    File imageThumb = new File(path + File.separator + "thumb" + "_" + lkImage.Id + "_" + lkImage.Name);
    if (!imageThumb.exists()) {
        try {
            InputStream inputStream = new java.net.URL(GetAPIServerUrl() + "/Images/GetImage/" + lkImage.Id + "?s=" + lkImage.ImageSource + "&t=True&type=.jpg&tId=" + lkImage.TenantId).openStream();
            Bitmap bitmapImage = BitmapFactory.decodeStream(inputStream);
            FileOutputStream out = new FileOutputStream(imageThumb);
            bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, out);
        } catch (Exception e) {
            e.printStackTrace();
            res = false;
        }
    }
    File imageBig = new File(path + File.separator + lkImage.Id + "_" + lkImage.Name);
    if (!imageBig.exists()) {
        try {
            InputStream inputStream = new java.net.URL(GetAPIServerUrl() + "/Images/GetImage/" + lkImage.Id + "?s=" + lkImage.ImageSource + "&t=False&type=.jpg&tId=" + lkImage.TenantId).openStream();
            Bitmap bitmapImage = BitmapFactory.decodeStream(inputStream);
            FileOutputStream out = new FileOutputStream(imageBig);
            bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, out);
        } catch (Exception e) {
            e.printStackTrace();
            res = false;
        }
    }
    return res;
}

Всего 2 ответа


URL-адрес изображения является строкой, и вы можете легко создать список типов данных строки и сохранить URL-адреса изображения в нем и показать его в своем приложении.

   Glide.with(getContext()).load(imageurl[0]).into(ImageView);

Во-первых , вы должны сделать AsyncTask устаревшим, согласно официальной документации .

Во-вторых , я предлагаю использовать DownloadManager для Android. Это очень простой и удобный API, вы сможете загружать свои изображения.

    internal var dowloadId: Long = 0

    private fun prepareDownloadRequest() {

    val file = File(this@MainActivity.getExternalFilesDir(null), "your path")
    val request =
        DownloadManager.Request(Uri.parse("Your Url"))
            .setTitle("This title would be shown in the notification center")
            .setDescription("This title would be shown in the notification center")
            .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)
            .setDestinationUri(Uri.fromFile(file))
            .setAllowedOverMetered(true)

    val downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
    dowloadId = downloadManager.enqueue(request)
}

Чтобы сделать окончательное решение для этого, я предлагаю создать широковещательный приемник, который уведомляет пользователя о завершении загрузки следующим образом:

    private val onDownloadComplete = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        //Fetching the download id received with the broadcast
        val id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
        //Checking if the received broadcast is for our enqueued download by matching download id
        if (dowloadId == id) {
            Toast.makeText(this@MainActivity, "Download Completed", Toast.LENGTH_SHORT).show()

        }
    }
}

Я надеюсь, что этого достаточно.

Удачного кодирования ?


Есть идеи?

10000