Last active
November 6, 2017 15:07
-
-
Save mgdiez/51ae180c53b1a62beb059a4b3a6600e3 to your computer and use it in GitHub Desktop.
Rx Geocoder
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface AddressProvider { | |
int MAX_RESULTS = 1; | |
Observable<Map<String, String>> getRealAddressList(TripLocation... locationIds); | |
String getImmediateRealAddress(TripLocation tripLocation); | |
Observable<String> getRealAddress(TripLocation tripLocation); | |
} | |
public class GoogleAddressProvider implements AddressProvider { | |
private final Context context; | |
@Inject public GoogleAddressProvider(Context context) { | |
this.context = context; | |
} | |
@Override | |
public Observable<Map<String, String>> getRealAddressList(TripLocation... tripLocations) { | |
return Observable.just(createMap()) | |
.flatMap(map -> Observable.from(tripLocations) | |
.concatMap(tripLocation -> getAddress(map, tripLocation)) | |
.last()) | |
.retryWhen(this::errorPolicy); | |
} | |
@Override public Observable<String> getRealAddress(TripLocation tripLocation) { | |
return getRealAddressObservable(tripLocation).retryWhen(this::errorPolicy); | |
} | |
private Observable<Long> errorPolicy(Observable<? extends Throwable> errors) { | |
return errors.zipWith(Observable.range(1, 5), (n, i) -> i) | |
.flatMap(retryCount -> Observable.timer(retryCount * 100, TimeUnit.MILLISECONDS)); | |
} | |
@Override public String getImmediateRealAddress(TripLocation tripLocation) { | |
String result = ""; | |
if (tripLocation != null) { | |
try { | |
List<Address> locationAddresses = | |
new Geocoder(context, Locale.getDefault()).getFromLocation(tripLocation.getLatitude(), | |
tripLocation.getLongitude(), MAX_RESULTS); | |
if (locationAddresses != null && !locationAddresses.isEmpty()) { | |
Address address = locationAddresses.get(0); | |
result = address.getAddressLine(0); | |
} | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
return result; | |
} | |
private Observable<String> getRealAddressObservable(TripLocation tripLocation) { | |
String immediateRealAddress = getImmediateRealAddress(tripLocation); | |
if (immediateRealAddress.isEmpty()) { | |
return Observable.error(new IOException()); | |
} else { | |
return Observable.just(immediateRealAddress); | |
} | |
} | |
private Observable<Map<String, String>> getAddress(Map<String, String> map, | |
TripLocation locationId) { | |
Geocoder geocoder = new Geocoder(context, Locale.getDefault()); | |
try { | |
Observable<Address> from = Observable.from( | |
geocoder.getFromLocation(locationId.getLatitude(), locationId.getLongitude(), | |
MAX_RESULTS)); | |
return from.map(toMap(locationId, map)); | |
} catch (IOException e) { | |
return Observable.empty(); | |
} | |
} | |
private Func1<Address, Map<String, String>> toMap(TripLocation locationId, | |
Map<String, String> map) { | |
return location -> { | |
map.put(generateIdForAddress(locationId), location.toString()); | |
return map; | |
}; | |
} | |
@NonNull private static String generateIdForAddress(TripLocation locationId) { | |
return String.valueOf(locationId.getLatitude()) + String.valueOf(locationId.getLongitude()); | |
} | |
@NonNull private static Map<String, String> createMap() { | |
return new HashMap<>(); | |
} | |
} | |
public class TripLocation { | |
private final double latitude; | |
private final double longitude; | |
public TripLocation(double latitude, double longitude) { | |
this.latitude = latitude; | |
this.longitude = longitude; | |
} | |
public double getLatitude() { | |
return latitude; | |
} | |
public double getLongitude() { | |
return longitude; | |
} | |
@Override public String toString() { | |
return "TripLocation{" + "latitude=" + latitude + ", longitude=" + longitude + '}'; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment