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
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
67
How to Use Computers (Privately!)
dlew
0
120
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
720
ClimateChangeTech.pdf
dlew
0
180
What Tech Can Do About Climate Change
dlew
0
700
Grokking Coroutines
dlew
5
1.4k
Other Decks in Programming
See All in Programming
新卒PdEのリアル
ryu1013
1
410
ALB ログから Trace を気合で繋げる技術
fohte
7
880
Hono + Inertia + React で LP を構築した話
oukayuka
2
210
Can LLMs Replicate 4 Years of Compose Migration? Exploring the boundaries of automation with 279 XML files from a real product
makun
0
130
iOS開発×AI駆動開発 〜最近使って便利だったスキルの話〜
nogu66
0
140
高専キャリア LT 発表内容
crysta1221
6
5.6k
ハーネス設計入門 〜プロンプト、コンテキストの次〜
kinopeee
54
36k
片田舎のおっさん、 Swift Buildのダイアモンド問題解決の不具合修正PRを出すが、解決方法がキャッシュをしないようにすることであり、ビルド時間が伸びると言われてマージされないので高速化もする/swiftbuild
yimajo
0
360
kubernetes コンポーネント開発入門 / 新卒N年目の勉強会&交流会!〜〇〇への誘い〜 #n_study
mazrean
0
170
バグを直したら useEffect が消えた
colorful12
3
840
初めての模倣学習とVLA
natsutan
0
490
デプロイ直後のレイテンシスパイクを調べたら、 Railsの仕様にたどり着いた
nhsykym
0
110
Featured
See All Featured
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
19k
How to train your dragon (web standard)
notwaldorf
97
6.8k
The Cult of Friendly URLs
andyhume
79
7k
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
510
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
So, you think you're a good person
axbom
PRO
2
2.1k
For a Future-Friendly Web
brad_frost
183
10k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.6k
Amusing Abliteration
ianozsvald
1
290
Marketing to machines
jonoalderson
1
5.7k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.5k
How GitHub (no longer) Works
holman
316
150k
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