Как загрузить список URL изображений параллельно, используя AsyncTasks android - PullRequest
0 голосов
/ 08 апреля 2020

Согласно моему варианту использования. У меня есть список URL-адресов из API. Я загружаю изображения во внутреннее хранилище, а затем сохраняю URI, чтобы использовать его в приложении в автономном режиме. Теперь я делаю это с помощью циклического перемещения по списку, создавая асинктическую задачу для загрузки, которая вызывает другую асинхронную задачу c, чтобы создать, сохранить ее локально и создать URI. Но проблема в том, что мой код сначала загружает все изображения одно за другим. Затем создает URI один за другим.

Я хочу, чтобы он загружал изображения параллельно, а не последовательно. Кроме того, как только он загружает изображение, он должен сохранить это изображение локально, он не должен ждать завершения загрузки всех изображений. Я имею в виду, что каждая загрузка и сохранение изображений должна выполняться в разных потоках асинхронной задачи. Я читал, что есть что-то под названием ThreadPool. но не могу определить, где это будет соответствовать в моем случае использования. Или, если это вообще подходит.

private void downloadBuildingMaps(JSONArray j_floor) {
    for (int i = 0; i < j_floor.length(); i++) {
        try {
            JSONObject curr_floor = j_floor.getJSONObject(i);
            int floorNumber = curr_floor.optInt("FloorNumber", -1);
            String url = "";
            double swLatitude = 0.0f;
            double swLongitude = 0.0f;
            double neLatitude = 0.0f;
            double neLongitude = 0.0f;

            JSONObject Map = curr_floor.optJSONObject("Map");
            if (Map != null) {
                url = Map.optString("Url");
                String bounding_box = Map.getString("BoundingBox");
                JSONObject b_box = new JSONObject(bounding_box);

                swLatitude = b_box.optDouble("swLatitude", 0.0f);
                swLongitude = b_box.optDouble("swLongitude", 0.0f);
                neLatitude = b_box.optDouble("neLatitude", 0.0f);
                neLongitude = b_box.optDouble("neLongitude", 0.0f);
            }

            LatLng southwest = new LatLng(swLatitude, swLongitude);
            LatLng northeast = new LatLng(neLatitude, neLongitude);

            BuildingMap b_m = new BuildingMap(floorNumber, url, "", northeast, southwest);

            //Calling first asynctask to downlaod image
            new BitmapLoaderURIFromUrl(b_m).execute();

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}

класс BitmapLoaderURIFromUrl

public class BitmapLoaderURIFromUrl extends AsyncTask<Void, Void, Bitmap> {

    BuildingMap buildingMap;

    public BitmapLoaderURIFromUrl(BuildingMap buildingMap) {
        this.buildingMap = buildingMap;
    }

    @Override
    protected Bitmap doInBackground(Void... aVoid) {
        //Bitmap image = null;
        String url_string = buildingMap.image_url;
        try {
            URL url = new URL(url_string);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);
            connection.connect();
            InputStream input = connection.getInputStream();
            Bitmap myBitmap = BitmapFactory.decodeStream(input);
            return myBitmap;
        } catch (IOException e) {
            // Log exception
            return null;
        }
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {
        //String abs_path = saveReceivedImage(bitmap, this.imageName);

        //calling second asynctask to save image to internal storage and create uri
        WriteToInternalStorageURI writeToInternalStorageuri = new WriteToInternalStorageURI(buildingMap);
        writeToInternalStorageuri.execute(bitmap);
    }
}

класс WriteToInternalStorageURI

public class WriteToInternalStorageURI extends AsyncTask<Bitmap, Void, String> {
    BuildingMap buildingMap;

    public WriteToInternalStorageURI(BuildingMap buildingMap) {
        this.buildingMap = buildingMap;
    }

    @Override
    protected String doInBackground(Bitmap... bitmaps) {
        Bitmap bitmap = bitmaps[0];
        String my_image_path = "";
        if (bitmap != null) {
            try {

                File path = new File(SplashActivity.this.getFilesDir(), "GingerGuide" + File.separator + "Images");
                if (!path.exists()) {
                    path.mkdirs();
                }
                String url = buildingMap.image_url;
                String imageName = url.substring(url.lastIndexOf('/') + 1, url.length());
                File outFile = new File(path, "" + imageName + "" + System.currentTimeMillis());
                FileOutputStream outputStream = new FileOutputStream(outFile);
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
                my_image_path = outFile.getAbsolutePath();
                outputStream.close();
            } catch (FileNotFoundException e) {
                Log.e(TAG, "Saving received message failed with", e);
            } catch (IOException e) {
                Log.e(TAG, "Saving received message failed with", e);
            }
        }

        buildingMap.setImage_uri(my_image_path);

        //the created uri is added to list 
        buildingMaps.add(buildingMap);

        return my_image_path;
    }

    @Override
    protected void onPostExecute(String abs_path) {
        //destinationURIRepository.updateUriandStatus(abs_path, true, this.dest_id);
        Gson gson = new Gson();
        String json = gson.toJson(buildingMaps);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putString(getResources().getString(R.string.map_uri_url), json);
        editor.apply();

        Toast.makeText(SplashActivity.this, "Maps downloaded", Toast.LENGTH_SHORT).show();
        navigateHome.setValue(true);
    }
}

Также мне нужно знать, когда завершится загрузка всех изображений. Как сказать это потоку пользовательского интерфейса? Пожалуйста, помогите ..

...