Skip to content

Commit

Permalink
load country boundaries asynchronously, only block main thread when t…
Browse files Browse the repository at this point in the history
…he boundaries are needed now but loading is not complete yet (#416)
  • Loading branch information
westnordost committed Jul 26, 2017
1 parent b185135 commit f0e80f9
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 59 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package de.westnordost.streetcomplete.data.meta;

import com.vividsolutions.jts.geom.GeometryCollection;

import junit.framework.TestCase;

import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Collections;

Expand All @@ -25,14 +25,8 @@ public class CountryBoundariesTest extends TestCase

public void setUp()
{
try
{
countryBoundaries = new CountryBoundaries(new ByteArrayInputStream(testGeoJson.getBytes("UTF-8")));
}
catch (UnsupportedEncodingException e)
{
throw new RuntimeException(e);
}
countryBoundaries = new CountryBoundaries(
(GeometryCollection) new GeoJsonReader().read(testGeoJson));
}

public void testIsIn()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@
import com.vividsolutions.jts.index.SpatialIndex;
import com.vividsolutions.jts.index.strtree.STRtree;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
Expand All @@ -34,14 +31,13 @@ public class CountryBoundaries
private final Map<String, Geometry> geometriesByIsoCodes;
private final Map<Geometry, Double> geometrySizeCache;

public CountryBoundaries(InputStream is)
public CountryBoundaries(GeometryCollection countriesBoundaries)
{
long time = System.currentTimeMillis();
index = new STRtree();
geometrySizeCache = new HashMap<>(400);
geometriesByIsoCodes = new HashMap<>(400);

GeometryCollection countriesBoundaries = (GeometryCollection) load(is);
for(int i = 0; i < countriesBoundaries.getNumGeometries(); ++i)
{
Geometry countryBoundary = countriesBoundaries.getGeometryN(i);
Expand Down Expand Up @@ -151,39 +147,4 @@ else if(props.containsKey(ISO3166_2))
}
return result;
}

private String readToString(InputStream is) throws IOException
{
try
{
ByteArrayOutputStream result = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) != -1)
{
result.write(buffer, 0, length);
}
return result.toString("UTF-8");
}
finally
{
if(is != null) try
{
is.close();
}
catch (IOException e) { }
}
}

private Geometry load(InputStream is)
{
try
{
return new GeoJsonReader().read(readToString(is));
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;

import javax.inject.Inject;

Expand All @@ -22,13 +23,13 @@ public class CountryInfos
private static final String BASEPATH = "country_metadata";

private final AssetManager assetManager;
private final CountryBoundaries countryBoundaries;
private final Future<CountryBoundaries> countryBoundaries;

private CountryInfo defaultCountryInfo;

private Map<String, CountryInfo> countryInfoMap;

@Inject public CountryInfos(AssetManager assetManager, CountryBoundaries countryBoundaries)
@Inject public CountryInfos(AssetManager assetManager, Future<CountryBoundaries> countryBoundaries)
{
this.assetManager = assetManager;
this.countryBoundaries = countryBoundaries;
Expand All @@ -38,8 +39,15 @@ public class CountryInfos
/** Get the info by location */
public CountryInfo get(double longitude, double latitude)
{
List<String> countryCodesIso3166 = countryBoundaries.getIsoCodes(longitude, latitude);
return get(countryCodesIso3166);
try
{
List<String> countryCodesIso3166 = countryBoundaries.get().getIsoCodes(longitude, latitude);
return get(countryCodesIso3166);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}

/** Get the info by a list of country codes sorted by size. I.e. DE-NI,DE,EU gets the info
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@

import android.content.res.AssetManager;

import com.vividsolutions.jts.geom.GeometryCollection;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

import javax.inject.Singleton;

Expand All @@ -13,20 +20,53 @@
public class MetadataModule
{
@Provides @Singleton public static CountryInfos countryInfos(
AssetManager assetManager, CountryBoundaries countryBoundaries)
AssetManager assetManager, Future<CountryBoundaries> countryBoundaries)
{
return new CountryInfos(assetManager, countryBoundaries);
}

@Provides @Singleton public static CountryBoundaries countryBoundaries(AssetManager assetManager)
@Provides public static GeoJsonReader geoJsonReader()
{
return new GeoJsonReader();
}

@Provides @Singleton public static Future<CountryBoundaries> countryBoundariesFuture(
final AssetManager assetManager, final GeoJsonReader geoJsonReader)
{
FutureTask<CountryBoundaries> ft = new FutureTask<>(new Callable<CountryBoundaries>()
{
@Override public CountryBoundaries call() throws Exception
{
InputStream is = assetManager.open("countryBoundaries.json");
return new CountryBoundaries(
(GeometryCollection) geoJsonReader.read(readToString(is)));
}
});
// start creating (=loading) CountryBoundaries asynchronously
new Thread(ft).start();
return ft;
}

private static String readToString(InputStream is) throws IOException
{
try
{
return new CountryBoundaries(assetManager.open("countryBoundaries.json"));
ByteArrayOutputStream result = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) != -1)
{
result.write(buffer, 0, length);
}
return result.toString("UTF-8");
}
catch (IOException e)
finally
{
throw new RuntimeException(e);
if(is != null) try
{
is.close();
}
catch (IOException e) { }
}
}
}

0 comments on commit f0e80f9

Please sign in to comment.