Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Android Dependencies You Can Depend On
Search
Daniel Lew
March 21, 2015
Programming
830
14
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Android Dependencies You Can Depend On
Daniel Lew
March 21, 2015
More Decks by Daniel Lew
See All by Daniel Lew
What the fuck are passkeys and why are they everywhere now?
dlew
1
56
How to Use Computers (Privately!)
dlew
0
110
Finding Meaningful, Mission-Driven Work
dlew
0
210
Things Maybe You Don't Know as a Newer Developer
dlew
1
160
Maintaining Software Correctness
dlew
4
1.1k
Grokking Coroutines (MinneBar)
dlew
5
700
ClimateChangeTech.pdf
dlew
0
170
What Tech Can Do About Climate Change
dlew
0
690
Grokking Coroutines
dlew
5
1.4k
Other Decks in Programming
See All in Programming
Welcome to the "Parametricity" 🏙️ − Generic だけど Specific な世界 −
guvalif
PRO
1
180
act1-costs.pdf
sumedhbala
0
240
琵琶湖の水は止められてもNet--HTTPのリトライは止められない / You might be able to stop the water flow of Lake Biwa but you can't stop Net::HTTP retries
luccafort
PRO
0
430
関数型プログラミングのメリットって何だろう?
wanko_it
0
190
PHP初心者セッション2026 〜生成AIでは見えない裏側を知る:今だからLAMPを通して仕組みを学ぶ〜
kashioka
0
650
アルゴリズムは何を圧縮しているのか ─ Haskell から育った「圧縮代数」というメンタルモデル
naoya
16
3.6k
php-fpmのプロセスが枯渇した日-調査・対処・そして本当にやるべきだったこと-
shibuchaaaan
0
130
人間の目はかわらない、だからJPEGは30年もつ
yuzneri
1
590
The Bowling Game- From Imperative to Functional Programming - Part 1
philipschwarz
PRO
0
340
AIエージェントで 変わるAndroid開発環境
takahirom
2
710
使用 Meilisearch 建立新聞搜尋工具
johnroyer
0
170
SLOをサービス品質の共通言語にするために 取り組んできたこと
wakana0222
0
540
Featured
See All Featured
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.1k
Faster Mobile Websites
deanohume
310
32k
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
280
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
AI Search: Where Are We & What Can We Do About It?
aleyda
0
7.7k
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
280
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.4k
Ten Tips & Tricks for a 🌱 transition
stuffmc
0
150
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
210
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
201
75k
Discover your Explorer Soul
emna__ayadi
2
1.2k
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
640
Transcript
Android Dependencies You Can Depend On Dan Lew 3/21/2015
Why Libraries? • Stand on the shoulders of giants •
Hit the ground running • Easier than ever to use
Adding Libraries repositories { jcenter() } dependencies { compile
'com.squareup.retrofit:retrofit:1.9.0' }
Which Libraries?
My Basic Stack • Retrofit • GSON • Picasso •
OkHttp • Dagger • RxJava
Retrofit • …Because a lot of people use REST •
…Because REST is easy to understand
Example API http://company.com/api/public/cards?id=someId
Define an Interface http://company.com/api/public/cards?id=someId public interface MyService { @GET("/api/{visibility}/cards")
List<Card> getCards(@Path("visibility") String visibility, @Query("id") String id); }
Create a RestAdapter RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint("http://company.com") .build();
MyService service = restAdapter.create(MyService.class);
Use the service List<Card> cards = service.getCards("public", "someId");
GSON • …Because many REST APIs use JSON
JSON vs. Object • JSON { "id": "someId", "data": "Some
data" } • Class public class Card { private String id; private String data; }
Without GSON String jsonStr = /* …what we had from
before… */; try { JSONObject jsonObject = new JSONObject(jsonStr); String id = jsonObject.getString("id"); String data = jsonObject.getString("data"); Card card = new Card(id, data); } catch (JSONException e) { e.printStackTrace(); }
With GSON String jsonStr = /* ...whatever you get from
Retrofit... */; Gson gson = new Gson(); Card card = gson.fromJson(jsonStr, Card.class);
Customizable • Can handle differently named fields: public class Card
{ @SerializedName("theId") private String id; @SerializedName("theData") private String data; } • Custom deserializers (type adapters)
Retrofit with GSON RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint("http://company.com") .setConverter(new
GsonConverter(new Gson())) .build(); MyService service = restAdapter.create(MyService.class);
Picasso • Easy image loading Picasso.with(this) .load("http://path.to/image.png") .into(someImageView);
Picasso Options Picasso.with(this) .load("http://path.to/image.png") .placeholder(R.drawable.placeholder) .centerCrop() .into(someImageView);
OkHttp • Consistent HTTP implementation • Better HTTP implementation •
Easier HTTP implementation • Drives other libraries
OkHttp + Retrofit • Add client to RestAdapter RestAdapter restAdapter
= new RestAdapter.Builder() .setEndpoint("http://company.com") .setConverter(new GsonConverter(new Gson())) .setClient(new OkClient()) .build();
OkHttp + Picasso Picasso picasso = new Picasso.Builder() .downloader(new OkHttpDownloader())
.build(); picasso.load("http://path.to/image.png") .into(someImageView);
Dagger • Dependency injection! • …What does that really mean?
• …Why do you want it?
Components • RestAdapter • Gson • Picasso • OkHttp •
…All intertwined
BAD • DO NOT create new instances each time! RestAdapter
restAdapter = new RestAdapter.Builder() .setEndpoint("http://company.com") .setConverter(new GsonConverter(new Gson())) .setClient(new OkClient()) .build(); MyService service = restAdapter.create(MyService.class); Picasso picasso = new Picasso.Builder() .downloader(new OkHttpDownloader()).build();
Solving the Bad • Problem: Need to cache components •
Solution: static singletons!
It is now impossible to test most of your code
Solution Dependency injection!
It’s Not Complex • Without dependency injection public class SomeClass
{ private SomeService service; public SomeClass() { this.service = new SomeService(); } } • With dependency injection public class SomeClass { private SomeService service; public SomeClass(SomeService service) { this.service = service; } }
Unfortunately… • Passing around dependencies is a PITA! • Dagger:
Handles busywork for you
Dagger Modules @Module public class AppModule { @Provides @Singleton
Gson provideGson() { return new Gson(); } @Provides @Singleton Client provideClient() { return new OkClient(); } @Provides @Singleton RestAdapter provideRestAdapter(Gson gson, Client client) { return new RestAdapter.Builder() .setConverter(new GsonConverter(gson)) .setClient(client) .build(); } @Provides @Singleton MyService provideMyService(RestAdapter restAdapter) { return restAdapter.create(MyService.class); } }
Injecting Modules public class SomeClass { @Inject MyService myService;
public SomeClass() { // In real life, ObjectGraph should be reused ObjectGraph objectGraph = ObjectGraph.create(new AppModule()); objectGraph.inject(this); } }
RxJava • Reactive framework • Less coding • Easy error
handling • Easy concurrency • Just plain fun • …But not easy to understand at first
Observer Pattern Observable.just("1", "2", "3") .subscribe(new Action1<String>() { @Override public
void call(String s) { System.out.println(s); } });
Operators Observable.just("1", "2", "3") .map(new Func1<String, String>() { @Override public
String call(String s) { return "item: " + s; } }) .subscribe(new Action1<String>() { @Override public void call(String s) { System.out.println(s); } });
Schedulers Observable.just("1", "2", "3") .map(new Func1<String, String>() { @Override public
String call(String s) { return "item: " + s; } }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<String>() { @Override public void call(String s) { System.out.println(s); } });
Error Handling Observable.just("1", "2", "3") .map(new Func1<String, String>() { @Override
public String call(String s) { return "item: " + s; } }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( new Action1<String>() { @Override public void call(String s) { System.out.println(s); } }, new Action1<Throwable>() { @Override public void call(Throwable throwable) { System.out.println("Something went wrong!"); } });
u2020 • Great sample for (most) of basic stack •
https://github.com/JakeWharton/u2020/
Alternatives • Everything has alternatives • Impact, not implementation •
Weigh pros/cons
Development Libraries
Stetho • Debug bridge on Chrome
Stetho • Debug bridge on Chrome
Hugo • Before: public void doSomething(String input) { Log.i("SomeTagYouMadeUp", "doSomething("
+ input + ")"); // Shockingly, this does something Log.i("SomeTagYouMadeUp", "doSomething finished"); } • After: @DebugLog public void doSomething(String input) { // Shockingly, this does something }
Timber • Smarter alternative to Log Timber.i("Something bad happened", exception);
gradle-versions-plugin • Keep your dependencies up-to-date • https://github.com/ben-manes/gradle-versions- plugin
Fun Libraries • Calligraphy - Automatic fonts! • Gradle retrolambda
- Lambdas in Android! • Butterknife - Annotated views! • RoundedImageView - Easy rounded corners! • Mockito - Mocked objects for testing! • Victor - SVGs as resources!
Finding Libraries
Collections • Explore: https://android-arsenal.com/ • Demo: https://play.google.com/store/apps/details? id=com.desarrollodroide.repos
Gradle, Please • Shortcut for getting exact dependency string •
http://gradleplease.appspot.com
Google • A search engine: http://google.com • Type in what
you want • Take a gamble with “I’m feeling lucky”
Thank You! • http://blog.danlew.net • @danlew42 • +DanielLew