Droidcon 2015 London (Part 1)
It was a blast. In these blog post series, I am putting brief of all talks I’ve attended in Droidcon 2015 London (will add links to videos when they are uploaded). It’s a summary and a reference point to things I’ve learned (and actually force myself to look deeper). Also, I am adding awesome #sketchnotes made by @corey_latislaw (my own are not very pretty xD). And some photos from a social feed. Part 2.
Talks covered here:
- Keynote: The Long Road
- RxJava
- Gradle
Keynote: The Long Road
Great talk how to get the job (not a job). I was a bit late (the queue was a bit long too). Got into half-way through talk. Notes:
1. The job should make you happy every morning and be aligned to your personal goals.
2. Apply directly. Don’t use recruiters (they tend to make pressure on you and don’t care much about your goals).
3. Better chance to find the job in a small company (there is more intimacy and you are not just a number).
4. Ask yourself what do you want to learn from a company.
5. The best way to get a picture of a company is to speak with people working in that company and find out, do some research (companies will appreciate the effort).
6. Join communities, get involved, share, code, help developers, give back to a community.
7. Look carefully into job specs. Extract meta-data to get an idea about what company thinks/expects from people they hire. Things to look at specs:
Bad:
1. Misleading technology. ‘Looking for J2SE or J2EE developers’. Is it possible to have J2EE without J2SE??? ‘Looking for people with a passion of technology’. (probably as long as it’s Java).
2. Fixed pay (can mean that they are not looking for talent, just ‘hire for price’)
3. Experience measured in years. Not in knowledge.
4. ‘Software development lifecycle’. Just a fancy name for an old waterfall process.
5. ‘Things like Agile, TDD, JUnit, etc’. When they put every fancy name they hear in one bucket and even make it as optional. Just tells them how much they know about it.
6. ‘Close interaction with system architects and team leaders’. Hierarchy. You will be told what to do by people higher than you. Also means you will have no conversation with business owner/user.
7. ‘Opportunities to work on your career in business domain’. This is where passionate developers are going to die.
8. Promotes ‘we are the best’, ‘we have best people’, ‘we make best stuff x’, but don’t show much…
9. Code tests over the internet. Means they can be inefficient, don’t have a good filter and aims at testing a lot of people like this. If at least they would give feedback then it actually might we worth the time.
10. Brain teasers. Legacy thing started by Google, which is still used widely. Smart people do not always write good code.
11. Coding on white board or paper. Why not use your tools, to show people are efficient with those.
Good:
1. TDD experience is essential in this role. Language is just practice.
2. Wants to attract caring, passionate developers.
3. ‘For you more than just a job’
4. Prefer actions, not stuff you put on your CV
5. ‘Working directly with business’. No middle management.
6. Opinionated specs. ‘Job requires team work and is not right for everyone, but we believe it’s the best way to create software’.
7. TDD, BDD, Coding dojos
8. ‘Technologies we use’. Instead of ‘required’. Means they are open and investigates new ones.
9. Allows to look at their work and people (links, github, app store, blog, twitter, etc). Honesty.
10. Pair programming in interview process. You will get a better picture about people you would work with and they would get it about you.
RxJava
by @passsy and @RittmeyerW
About RxJava and how to Get Reactive. Great overview and tips. Will skip very simple stuff, slides can be found here.
compile ‘io.reactivex:rxjava:1.0.14’
Creating Custom Observable
To obey RxJava conventions all your custom observables should have all 3 events: onNext, onError and onComplete.
Observable.create(new Observable.OnSubscribe<Integer>() {
public void call(Subscriber<? super Integer> s) {
try {
Random r = new Random();
for (int i = 0; i < 10; i++) {
if (!s.isUnsubscribed()) { // precaution
s.onNext(r.nextInt()); // emit item
}
}
s.onCompleted(); // will be emitted after last item
}
catch (Throwable t) {
s.onError(t); // will be emitted if error happens
}
}
});
How not to leak :)
1. Unsubscribe from unused subscriptions (onPause, onStop, onDestroy)
2. Avoid anonymous inner classes.
3. Use RxLifecycle library to handle Android lifecycle.
4. use MVP pattern and preserve presenter and continue request during configuration changes (libraries that help: Mosby or Nucleus).
Error Handling
1. Observable.onErrorResumeNext — allows to switch to another observable after error occurs
2. Observable.onErrorReturn — allows to return one more item after error occurs
Backpressure
For rare situations when you need to manage observables that are emitting items too fast to consume. Advanced use. Mentioned resources to learn:
Testing
1. Special subscriber — TestSubscriber, faster, you don’t need to implement all 3 events: onNext, onCompleted, onError to test
2. To test unhappy scenarios you can use Observable.error(), Observable.empty(), Observable.never().
Debugging
- You can’t simply put a breakpoint in your observable. It will stop only when it’s defined, but not actually executed. You need to put a break point inside your operator (I guess this makes even more sense to separate operators vertically, not in one line).
- Or you can put side effect operators doOnNext, doOnSubscribe, which won’t effect stream (but will clutter your code, so don’t forget to remove after debugging)
- You can also use hooks: RxJavaObservableExecuteionHook, RxJavaSchedulersHook, RxJavaErrorHandler (more info https://github.com/ReactiveX/RxJava/wiki/Plugins)
Resources I would personally recommend to learn more about RxJava:
- Official site for all Rx languages
- Official site for Java
- Blog post series how to start using them
- Podcast on RxJava (episodes 3 and 4)
- More samples
- Advanced usages
- Interactive marble diagrams to let you better understand them
RxAndroid
compile ‘io.reactivex:rxandroid:1.0.1’compile ‘io.reactivex:rxjava:1.0.14’
Contains hooks into various views and make observables out of their events: RxView, RxTextView, RxAdapter, RxAdapterView, RxAutoCompleteTextView, RxCheckedTextView, RxCompoundButton, RxMenuItem, RxSeekBar, RxViewGroup, RxProgressBar, RxRadioGroup, RxRatingBar, RxRecyclerView, RxRecyclerViewAdapter, RxSearchView, RxToolbar, …
Examples:
1. Button onClick:
RxView.clicks(myButton)
.subscribe(v -> triggerAction());
2. Three field forms to validate (one is optional). Fields are checked while a user enters a text, when fields are valid, enable submit button:
// textChanges watches each field and produce an item every time use
// changes that particular field.
Observable<CharSequence> rxUsername = RxTextView.textChanges(username_tv);
Observable<CharSequence> rxPassword = RxTextView.textChanges(password_tv);
Observable<CharSequence> rxFullName = RxTextView.textChanges(fullName_tv) // optional field
// because this field is optional and if user never writes into
// this field, observable will never emit item, that’s why we need
// to merge with empty string, so it will have at least one item
// “” to emit (and more if user decides to write into this field).
.mergeWith(Observable.just(“”)); // Each field observable emits items, combineLatest gets three
// latest values from each of those observables and combines into
// single one
Observable.combineLatest(
// values passed to model
rxUsername, rxPassword, rxFullName, RegistrationModel::new)
// filter checks if form is valid
.filter(RegistrationModel::isValid)
// if it passed filter, submit button will be enabled
.subscribe(result -> enableSubmitButton());
3. As a user enters text into search view, search Github API for repositories with entered name and update list. Also, Github limita requests frequency, so on error case show empty list instead.
// as user enters text into search view
RxSearchView.queryTextChanges(searchView)
// check if it’s not empty (user removed text), if it is
// observable chain will stop here until user enters something.
.filter(charSequence -> !TextUtils.isEmpty(charSequence))
// to prevent making requests too fast (as user may type fast),
// throttleLast will emit last item during 100ms from the time
// first item is emitted
.throttleLast(100, TimeUnit.MILLISECONDS)
// debounce will emit item only 200ms after last item is emitted
// (after user types in last character)
.debounce(200, TimeUnit.MILLISECONDS)
// as network operations can be lengthy, onBackpressureLatest will
// ensure that items won’t be emitted faster than a subscriber can
// consume (will emit last item as soon as subscriber is able to
// consume)
.onBackpressureLatest()
// concatMap ensures ordering of observables (flatMap does not
// care about order). More about it here
.concatMap(charSequence -> {
// retrofit network call
return searchRepositories(charSequence);
})
// results are observed on UI thread
.observeOn(AndroidSchedulers.mainThread())
// this may be pointless as Retrofit handles it itself.
.subscribeOn(Schedulers.io())
// if observable will return an error, whole chain will stop and
// will not emit items afterwards, so with onErrorResumeNext we
// tell that if error happens just return empty observable
// instead. onError will not be called!
.onErrorResumeNext(throwable -> {
return Observable.empty();
})
.subscribe(response -> {
// on success (even if it’s empty) update list
showRepositories(response.getItems());
// there is no on error case here, as it is would not be
// emitted, because it is consumed by onErrorResumeNext
});
// dependency
compile ‘com.jakewharton.rxbinding:rxbinding:0.3.0’Also support for support libraries (no pun intended):
rxbinding-support-v4
rxbinding-appcompat-v7
rxbinding-design
rxbinding-recyclerview-v7
rxbinding-leanback-v17
Retrofit 2 Mock
You can easily mock Retrofit network requests with RxJava, also do operations like delays, etc
// retrofit 2 interface
@GET(“/search/repositories”) Observable<GitHubResponse<Repository>> searchRepositoriesObservable(@Query(“q”) String name);// implementation
@Override
public Observable<GitHubResponse<Repository>> searchRepositoriesObservable(final String name) {
GitHubResponse<Repository> response = new GitHubResponse<>
(testRepo1, testRepo2, testRepoN);
return Observable.just(response)
.delay(1000, TimeUnit.MILLISECONDS);
}// Depenency
compile ‘com.squareup.retrofit:retrofit:2.0.0-beta2’
Gradle
A closer look at Gradle improvements and how they manifest in the context of Android and Android Studio. Gradle is Groovy based domain-specific language (DSL), both expressive and concise compared to Maven and Ant. Compatible with various front end and back end languages.
Components:
Gradle — is a daemon process, independent from Android Studio (if leak happens in one of them, other will still run fine)
Launcher — launches gradle scripts from command-line (build master) and server (cont. integration)
Tooling API — small library for delegating information between Gradle and Android Studio
- supports build cancellation (not just killing process, does it smarter)
- continuous mode
- test execution
- build events
Gradle Phases:
Configuration (builds task graph)
- still very imperative build logic (Gradle does not know much about it, kinda ‘black box’)
- constructs full model (even if you just run just Gradle — help command)
- configure on demand (incubating feature, only in latest releases)
- predexing (Gradle clean will clean them)
- dexing (optimisations on the Android side, collaboration happening between companies)
- many optimisations and tactics done on execution phase are being ported to configuration phase
Execution (executes task graph)
- incremental build feature (old feature, input -> task -> output, if input or output haven’t changed, then a task is skipped)
- continuous build feature
- fast compilation for continuous builds (compiler daemon is kept alive)
Useful Commands
Test Execution./gradlew test
./gradlew -Dtest.single=ClassUnderTest testClean BuildForce to make a clean build without cleaning caches and build folder. Runs tasks even if they are up to date../gradlew build --rerun-tasksContinuous Build FeatureGradle will keep running builds as you change your source code (input watcher). Example with continuous testing as we change source code of either source or test../gradlew test -tRun Y after XRun one task after another (tasks are independent from each other). Different than dependsOn.taskY.mustRunAfter taskXConfigure On DemandIncubating feature that allows to configure only relevant projects. Faster for large multi-projects../gradlew --configure-on-demand
Gradle is also supporting Jigsaw. Service configuration example:
Gradle is working on SaaS service (collecting build configurations, statistics, analytics, sharing, solving problems, etc). Sign up for email updated on http://www.gradle.com/.
Udacity Course on Gradle for Android and Java (free)
Thanks presenters for great talks. More talks summaries incoming in following blog posts.