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
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
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
78
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
170
Maintaining Software Correctness
dlew
4
1.1k
Grokking Coroutines (MinneBar)
dlew
5
730
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
R8 の設定見直しでアプリサイズ削減
andpad
0
220
Kotlinの15年とServer-Side Kotlin
n_takehata
1
150
當我們開始不讀 Code - AI Agent 時代,Code Review 與 Clean Code 還剩下什麼?
jame2408
1
250
HTML-in-Canvasで作る未来のWeb UI表現
clockmaker
5
5.1k
Agentic Software Factoryに、すごく賢いIF文を。 / super smart IF statement into the Agentic Software Factory.
rkaga
8
2.2k
npm との違いを手がかりにGo の依存管理を理解したい
optim
0
620
AmebaブログはKMPから卒業します
kmars0605
0
200
Optunaを作ったときにやりたかったこと、その後 (2026/10/16, Optuna Meetup #3)
iwiwi
1
440
ChromeでローカルLLM
ryu1013
0
140
C#の現在地 進化の歴史と、AI時代の.NET Everywhere
neuecc
5
5.2k
現場と育てるRailsモデリング 〜Spreadsheetから始めたモデル設計〜
siroemk
2
610
Unity6 URPによる海底をテーマにしたVJシステムの解説 | Unity Shader 完全に理解した 勉強会
gam0022
0
370
Featured
See All Featured
4 Signs Your Business is Dying
shpigford
187
23k
Being A Developer After 40
akosma
92
590k
Designing for Timeless Needs
cassininazir
1
530
Crafting Experiences
bethany
1
380
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
550
Game over? The fight for quality and originality in the time of robots
wayneb77
1
310
Building AI with AI
inesmontani
PRO
1
1.3k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
850
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
260
More Than Pixels: Becoming A User Experience Designer
marktimemedia
3
570
Technical Leadership for Architectural Decision Making
baasie
3
600
The Curse of the Amulet
leimatthew05
3
16k
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