Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save scottroemeschke/17dbdeb16649cb9ccccf6d65e1043f54 to your computer and use it in GitHub Desktop.
Save scottroemeschke/17dbdeb16649cb9ccccf6d65e1043f54 to your computer and use it in GitHub Desktop.
//many ways to slice this up, just an example
//syntax may be missing something, been writing Kotlin for a couple years now
//also this sort of thing is general a much better API with RxJava but here's a basic implementation.
public interface CitiesRepo {
//could give an executor here or something to let caller dictate threading/scheduling context
Cancelable getCities(AsyncCallback<List<Cities> callback);
}
//Could just be a class as well.
//Just defining as interface because I'm too lazy to implement, but the gist of it is there
public interface Cancelable {
public boolean isCanceled();
public void cancel();
}
//doesn't need to be an interface if you want it to have functionality could be abstract class, etc.
interface AsyncCallback<T> {
void onSuccess(List<City> cities);
void onFailure(Throwable error);
}
//this can be easily 100% unit tested,
//it doesn't need to be an interface because it's super easy to feed it data and see the output.
//there's no side effects here (purely input -> output).
public class CitiesParser() {
List<Cities> parseCities(InputStream citiesInput) throws JsonMalformedException {
//blah blah parse this json, throw if the json is messed-up
}
}
interface CitiesFetcher {
InputStream getCities() throws IOException;
}
class CitiesFetcherFromAssets extends CitiesFetcher {
private Context appContext;
public CitiesFetcherFromAssets(Context appContext) {
context = appContext;
}
@Override
InputStream getCities() throws IOException {
//blah get assets from context grab the filename for the cities file etc.
//you could also have like an assets class that takes a filename and
//gives back a string or byte[] and use that, then you can test that with robolectric or integration tests.
}
}
//This can also be 100% unit tested. Make sure it cancels appropriately, returns failure or success when it should. etc.
//You can test threading, you can test that it returns an empty list and not a null one if the list from the parser is empty etc.
//You can test that it delievers the error in the callback, and never actually throws the exception. etc.
class CitiesRepository extends CitiesRepo {
private CitiesParser parser;
private CitiesFetcher fetcher;
public CitiesRepository(CitiesParser parser, CitiesFetcher fetcher) {
this.parser = parser;
this.fetcher = fetcher;
}
@Override
Cancelable getCities(AsyncCallback<List<Cities> callback) {
//get from fetcher, feed that to parser
//return back the data in the callback or the error if there is a problem
//you could also have caching here if the data never changes, and return the cached data if you've already fetched it once
//you can check the cancelable at any time during the process to see if they've requested canceling the work etc.
}
}
//then your viewmodel gets a cityrepo in the constructor as a dependency and interacts with it
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment