Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Android Dependencies You Can Depend On
Search
Daniel Lew
March 21, 2015
Programming
840
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
72
How to Use Computers (Privately!)
dlew
0
120
Finding Meaningful, Mission-Driven Work
dlew
0
220
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
720
ClimateChangeTech.pdf
dlew
0
180
What Tech Can Do About Climate Change
dlew
0
710
Grokking Coroutines
dlew
5
1.4k
Other Decks in Programming
See All in Programming
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
410
AI Agent時代のリアーキテクチャ戦略と実践
hokaccha
9
5.2k
アクセシビリティから考える情報設計
high_g_engineer
0
420
速習iPhone Duo対応
yuukiw00w
2
870
マイコン向けの軽量Ruby「PicoRuby」で各種デバイスを制御するネイティブアプリの実現手法
bash0c7
0
460
20260914 AIエージェント時代のPlatform Engineering LLM基盤とプロダクトの責務境界線
kanfab1
7
2.3k
大喜利で理解するLLM as a Judge / Understanding LLM-as-a-Judge through Ogiri
rockname
0
170
MVNOの申込からeSIM開通までをiOSアプリでつなぐ- 本人確認・MNP・通信事業者基盤をまたぐ実装
satotakeshi
0
500
Java 27新機能 / Java 27 new features
kishida
2
180
更なる可用性を求めて、5年間運用したKotlinのアプリケーションをGoでリプレイスする話
ken_tunc
0
400
パズルゲームの作り方 / how to make puzzle games
kaityo256
PRO
2
240
Apple Intelligence を用いた個人情報誤送信防止、及びユーザーリクエスト体験の改善について
yukiny
0
220
Featured
See All Featured
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
350
Side Projects
sachag
456
43k
Marketing to machines
jonoalderson
1
5.8k
Navigating Weather and Climate Data
rabernat
0
540
RailsConf 2023
tenderlove
30
1.6k
A better future with KSS
kneath
240
18k
What does AI have to do with Human Rights?
axbom
PRO
1
2.4k
Mobile First: as difficult as doing things right
swwweet
225
10k
Faster Mobile Websites
deanohume
310
32k
Testing 201, or: Great Expectations
jmmastey
46
8.3k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
590
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1.1k
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