Показать большой файл Geojson в Google Maps Google

Я пытаюсь показать слой геойсона на карте Google. Код выглядит следующим образом. Файл geojson хранится локально в моей папке raw. Файл имеет 286 функций (около 15 МБ). Следовательно, чтение этого файла и его отображение занимают больше времени. Первоначально у меня возникала ошибка нехватки памяти, которая устраняется путем установки большой кучи как true в файле манифеста. Как я могу быстро загрузить этот файл (сейчас это занимает минуту или больше)? Мне интересно, есть ли другой эффективный способ сделать это. После этого у меня также будут другие задачи по получению функций и отображению некоторых свойств.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);
}

@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(myanmar, 5.25f));
    new MyAsyncTask().execute();
}

public class MyAsyncTask extends AsyncTask <Void, Void, Void> {

    ProgressDialog pd;
    GeoJsonLayer layer;

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pd = new ProgressDialog(MapsActivity.this);
        pd.setMessage("Loading Data");
        pd.show();
    }

    @Override
    protected Void doInBackground(Void... voids) {
        try {
            layer = new GeoJsonLayer(mMap, R.raw.myanmar, getApplicationContext());
        } catch (Exception e) {
            Log.d("Error is : ", e.toString());
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        pd.cancel();
        layer.addLayerToMap();
     }
}

Очень маленькая часть моего файла geojson выглядит следующим образом:

{
 "type": "FeatureCollection",
 "crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
 "features": [
{ "type": "Feature", "properties": { "ID_3": 193, "NAME_3": "Chaung-U" }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 95.348327636718807, 21.878610610961914 ], [ 95.297210693359432, 21.860000610351676 ], [ 95.286926269531307, 21.853612899780387 ], [ 95.276092529296989, 21.850000381469727 ], [ 95.265823364257926, 21.84832954406744 ], [ 95.257217407226676, 21.846940994262695 ] ] ] ] } },
{ "type": "Feature", "properties": { "ID_3": 199, "NAME_3": "Myaung" }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 95.376281738281193, 21.708541870117301 ], [ 95.375259399414119, 21.703050613403434 ], [ 95.370529174804801, 21.681390762329102 ], [ 95.367752075195313, 21.664720535278434 ], [ 95.366699218750114, 21.658369064331055 ], [ 95.362762451171875, 21.649999618530273 ] ] ] ] } }
]}

Я пытаюсь разделить файл на несколько небольших файловых блоков и параллельно запустить отдельные асинхронные задачи, каждая из которых обрабатывает отдельный файл:

for (int i = 1; i < 3; i++) {
        new MyAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,i);
}

AsyncTask:

public class MyAsyncTask extends AsyncTask <Integer, Void, GeoJsonLayer> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected GeoJsonLayer doInBackground(Integer... integers) {
        int i = integers[0];
        try {
            GeoJsonLayer layer = null;
            switch (i) {
                case 1:
                    layer = new GeoJsonLayer(mMap, R.raw.small_1,
                            getApplicationContext());
                    break;
                case 2:
                    layer = new GeoJsonLayer(mMap, R.raw.small_2,
                            getApplicationContext());
                    break;
                //other cases
            }
            for (GeoJsonFeature feature : layer.getFeatures()) {
                geoJsonFeatures.put(Integer.parseInt(feature.getProperty("ID_3")), feature);
            }
            return layer;
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    protected void onPostExecute(GeoJsonLayer layer) {
        super.onPostExecute(layer);
        layer.addLayerToMap();
    }
}

Это предлагается? При этом время сокращается по сравнению с предыдущим, но все еще не быстро, учитывая фактор пользовательского опыта.

3 ответа

Наконец, решена проблема за счет уменьшения размера файла geojson. Использовал http://mapshaper.org/, онлайн-инструмент, который дает вам возможность уменьшить размер, сохраняя при этом форму. Использовал его для получения упрощенного файла (почти 300 КБ) и взрыва, загрузка завершается в течение нескольких секунд. Надеюсь, что это помогает кому-то сталкиваться с той же проблемой.

Я поставил код для десериализации кода геойсона. Но я никогда не пробовал Google Map раньше. Может быть, вы могли бы задать другой вопрос?

Ниже я покажу вам, как десериализовать ваш огромный файл geojson с помощью GSON Streaming.

GeoJSON.java

public class GeoJSON {

    @SerializedName("type")
    private String type;
    @SerializedName("features")
    private List<Features> features;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }


    public List<Features> getFeatures() {
        return features;
    }

    public void setFeatures(List<Features> features) {
        this.features = features;
    }
}

Features.java

public class Features {

    @SerializedName("type")
    private String type;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}

Конвертировать JSON в класс Pojo

private void readGeoJSON() {
        try {
            InputStream is = getAssets().open("geo.json");

            JsonReader reader = new JsonReader(new InputStreamReader(is, "UTF-8"));
            Gson gson = new GsonBuilder().create();

            GeoJSON geoJSON = new GeoJSON();
            ArrayList<Features> features = new ArrayList<>();

            reader.beginObject();
            while (reader.hasNext()){
                String key = reader.nextName();
                if(key.equals("type")){
                    geoJSON.setType(reader.nextString());
                }else if(key.equals("features")){
                    // read array
                    reader.beginArray();
                    while (reader.hasNext()) {
                        Features o = gson.fromJson(reader, Features.class);
                        features.add(o);
                    }
                    reader.endArray();
                }else{
                    reader.skipValue(); //avoid some unhandle events
                }

                geoJSON.setFeatures(features);
            }

            reader.endObject();
            reader.close();


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

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

Предположим, я храню файл geo.json в папке ресурсов. Вот как вы можете десериализовать свой локальный geo.json, и я проверил код, он работал. Возможно, вам придется добавить для других полей. Надеюсь, что это может решить вашу проблему с памятью.

Вы должны использовать JSON Streaming либо с Gsonили жеJackson.Для получения более подробной информации посмотрите на Джексон Vs. Gson, тест производительности потокового анализа JSON: Джексон против GSON или JSON.simple против GSON против Джексона против JSON P

Другие вопросы по тегам