2017-02-16 84 views
5

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

@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(); 
    } 
} 

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

+1

Вы можете просматривать библиотеку GSON от goole, которая обладает потоковыми возможностями для загрузки большого количества json, не слишком сильно влияя на память. https://github.com/google/gson.быстрый пример можно найти здесь https://www.mkyong.com/java/gson-streaming-to-read-and-write-json/ – Sanny

+0

@ Sanny Я изучил использование Gson (https://sites.google.com/site/gson/gson-user-guide), но мне трудно разобрать мой файл geojson. Я добавил образец моего файла geojson в свой вопрос. Также я не уверен, как я могу показать это на сайтах Google Android после десериализации. – Sujal

ответ

0

Вы должны использовать JSON потоковое либо с Gson или Jackson .Чтобы детали посмотреть на Jackson Vs. Gson, Streaming JSON Parsing Performance Test: Jackson vs. GSON или JSON.simple vs GSON vs Jackson vs JSONP

+0

@harris Не могли бы вы рассказать мне, способ, которым я использую асинхронную задачу (правки в вопросе) - это хороший способ? Что было бы эффективным способом для моего дела? Возможно, для десериализации потребуется дополнительная обработка для отображения на карте. – Sujal

0

Я поставил код, как deserialise код GeoJSON. Но я никогда не пробовал 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, и я проверил код, он сработал. Возможно, вам придется добавить в другие поля. Надеюсь, что это может решить проблему с памятью.

+0

Я использовал другой способ, как упоминалось в изменениях в вопросе. Я также попробую ваш код десериализации. @Sanny – Sujal

2

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