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
Day1 Keynote in DroidKaigi 2016
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Daichi Furiya (Wasabeef)
February 17, 2016
Programming
12k
6
Share
Day1 Keynote in DroidKaigi 2016
Day1 Keynote in DroidKaigi 2016
Daichi Furiya (Wasabeef)
February 17, 2016
More Decks by Daichi Furiya (Wasabeef)
See All by Daichi Furiya (Wasabeef)
DevFest Tokyo 2025 - Flutter のアプリアーキテクチャ現在地点
wasabeef
6
2.6k
About Flutter Architecture
wasabeef
1
310
2023 Flutter/Dart Summary
wasabeef
0
120
I/O Extended 2023 - Dart と Flutter の新機能
wasabeef
0
220
I/O Extended 2023 - Flutter 活用事例
wasabeef
10
3.1k
What it Takes to be a Flutter Developer
wasabeef
0
240
FlutterKaigi 2022 Keynote
wasabeef
1
690
Flutter Hooks を使ったアプリ開発 / App Development with the Flutter Hooks
wasabeef
2
1.5k
Flutter 2021 の振り返りと今後のアプリ開発に向けて / Looking back on Flutter 2021 and for future app development.
wasabeef
4
2.2k
Other Decks in Programming
See All in Programming
見せてもらおうか、 OpenSearchの性能とやらを!
shunta27
1
180
RSAが破られる前に知っておきたい 耐量子計算機暗号(PQC)入門 / Intro to PQC: Preparing for the Post-RSA Era
mackey0225
3
120
AI時代のPhpStorm最新事情 #phpcon_odawara
yusuke
0
130
感情を設計する
ichimichi
5
1.3k
事業会社でのセキュリティ長期インターンについて
masachikaura
0
230
AWS re:Invent 2025の少し振り返り + DevOps AgentとBacklogを連携させてみた
satoshi256kbyte
2
150
煩雑なSkills管理をSoC(関心の分離)により解決する――関心を分離し、プロンプトを部品として育てるためのOSSを作った話 / Solving Complex Skills Management Through SoC (Separation of Concerns)
nrslib
3
730
SkillがSkillを生む:QA観点出しを自動化した
sontixyou
6
3.1k
「効かない!」依存性注入(DI)を活用したAPI Platformのエラーハンドリング奮闘記
mkmk884
0
310
仕様漏れ実装漏れをなくすトレーサビリティAI基盤のご紹介
orgachem
PRO
8
5k
Reactive ❤️ Loom: A Forbidden Love Story
franz1981
2
220
夢の無限スパゲッティ製造機 -実装篇- #phpstudy
o0h
PRO
0
200
Featured
See All Featured
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
200
Why Our Code Smells
bkeepers
PRO
340
58k
A Tale of Four Properties
chriscoyier
163
24k
Code Reviewing Like a Champion
maltzj
528
40k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
55k
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1k
Designing Experiences People Love
moore
143
24k
Darren the Foodie - Storyboard
khoart
PRO
3
3.2k
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
Bootstrapping a Software Product
garrettdimon
PRO
307
120k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
260
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
330
Transcript
OSSの動向を捉えた実装方針 wasabeef DroidKaigi 2016
About me Daichi Furiya wasabeef @wasabeef_jp CyberAgent, Inc.
OSSの動向を捉えた実装方針?
Research
GitHub/trending Android Weekly Android Arsenal Twitter Research
Introduction
Languages
Kotlin Java • RetroLambda • Lightweight-Stream-API • ThreeTen Android Languages
Kotlin by JetBrains
Kotlin 1.0 Java連携 …more Kotlin
RetroLambda by Esko Luontola
Lambda Method Reference RetroLambda view.setOnClickListener(v -> { finish(); }); view.setOnClickListener(this::something);
Lightweight-Stream-API by Victor Melnik
Stream API Lightweight-Stream-API Stream.of(lines) .map(str -> str.split(t)) .filter(arr -> arr.length
== 2) .map(arr -> new Word(arr[0], arr[1])) .collect(Collectors.toList());
Optional Lightweight-Stream-API Optional.ofNullable(getSupportActionBar()) .ifPresent(ab -> { ab.setDisplayHomeAsUpEnabled(true); ab.setHomeButtonEnabled(true); }); Optional.ofNullable(i.getStringExtra(EXTRA_URI))
.map(Uri::parse) .orElse(null);
ThreeTen Android by Jake Wharton
JSR-310 ThreeTen Android // Now LocalDateTime.now(); // 2016.2.18 10:30:40 LocalDateTime.of(2016,
2, 18, 10, 30, 40); // +1 truncated second LocalDateTime.now() .plusHours(1).truncatedTo(ChronoUnit.HOURS); // Epoch LocalDateTime.now() .toInstant(ZoneOffset.UTC).toEpochMilli();
Views
Support Library Android-ObservableScrollView Calligraphy florent37/ViewAnimator View
Support Library by Google
View (RecyclerView...etc ) RenderScript MultiDex Annotations Support Library
Sample... Support Library compile 'com.android.support:support-v4:+' compile 'com.android.support:appcompat-v7:+' compile 'com.android.support:design:+' compile
'com.android.support:recyclerview-v7:+' compile 'com.android.support:cardview-v7:+' compile 'com.android.support:support-annotations:+' compile ‘com.android.support:percent:+'
Android ObservableScrollView by ksoichiro
ScrollView , ListView, RecyclerViewなどのスクロー ル制御を監視 Android-ObservableScrollView https://github.com/ksoichiro/Android-ObservableScrollView
Calligraphy by Christopher Jenkins
Calligraphy アプリ全体にFont適用 xmlでもjavaでも可 簡単 https://github.com/chrisjenx/Calligraphy
CalligraphyConfig Calligraphy CalligraphyConfig.initDefault(new CalligraphyConfig.Builder() .setDefaultFontPath("fonts/mplus-2p-regular.ttf") .setFontAttrId(R.attr.fontPath) .build();
ViewAnimator by Florent CHAMPIGNY
ViewAnimator AnimatorSet animSet = new AnimatorSet(); animSet.playTogether( ObjectAnimator.ofFloat(image, View.TRANSLATION_Y, -1000,0),
ObjectAnimator.ofFloat(image, View.ALPHA, 0,1), ObjectAnimator.ofFloat(text, View.TRANSLATION_X, -200,0) ); animSet.setInterpolator(new DescelerateInterpolator()); animSet.setDuration(2000); animSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { AnimatorSet anim = new AnimatorSet(); anim.playTogether( ObjectAnimator.ofFloat(image, View.SCALE_X, 1f, 0.5f, 1f), ObjectAnimator.ofFloat(image, View.SCALE_Y, 1f, 0.5f, 1f) ); anim.setInterpolator(new AccelerateInterpolator()); anim.setDuration(1000); anim.start(); } }); animSet.start();
ViewAnimator ViewAnimator .animate(image) .translationY(-1000, 0) .alpha(0, 1) .andAnimate(text) .dp().translationX(-200, 0)
.descelerate() .duration(2000) .thenAnimate(image) .scale(1f, 0.5f, 1f) .accelerate() .duration(1000) .start();
DataBinding
Android Data Binding by Google
xmlとjavaのBinding Annotation Processing たまにビルドエラーが出る.. Android Data Binding
Android Data Binding <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id=“@+id/user_name“
android:layout_width="wrap_content" android:layout_height="wrap_content"/> <ImageView android:id=“@+id/user_thumbnail“ android:layout_width="160dp" android:layout_height="120dp"/> </LinearLayout>
Android Data Binding <layout xmlns:android="http://schemas.android.com/apk/res/android"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView
android:id=“@+id/user_name“ android:layout_width="wrap_content" android:layout_height="wrap_content"/> <ImageView android:id=“@+id/user_thumbnail“ android:layout_width="160dp" android:layout_height="120dp"/> </LinearLayout> </layout>
Android Data Binding <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data name="MainBinding"> <variable name="user" type="com.example.User"/>
</data> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id=“@+id/user_name“ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.name}" android:textColor="@{user.isWomen? @color/pink : @color:blue}"/> <ImageView android:id=“@+id/user_thumbnail“ android:layout_width="160dp" android:layout_height="120dp" bind:imageUrl="@{user.thumbnail}"/> </LinearLayout> </layout>
Custom Setters Android Data Binding public final class ImageBindingAdapters {
@BindingAdapter({ "bind:image" }) public static void loadImage(ImageView view, String url) { Glide.with(view.getContext().getApplicationContext()) .load(url) .into(view); } } <ImageView android:layout_width="160dp" android:layout_height="120dp" bind:imageUrl="@{user.thumbnail}"/>
DataBindingUtil Android Data Binding @Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); MainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); binding.userName.setOnClickListener(v -> ...); } <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data name="MainBinding"> <variable name="user" type="com.example.User"/> </data> <!-- ... -- </layout>
Networking
(Volley) Retrofit + OkHttp Networking
Retrofit+OkHttp by Square
REST RxJava support Pluggable client Converters(Gson, Wire...) Retrofit+OkHttp
Retrofit Retrofit retrofit = new Retrofit.Builder() .client(okHttpClient) .baseUrl("https://api.github.com") .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build(); GitHubService service = retrofit.create(GitHubService.class); service.repos("wasabeef") .subscribe(repo -> { // ... }, e -> { Timber.w(e); }); public interface GitHubService { @GET(/users/{user}/repos) Observable<List<Repo>> repos(@Path(user) String user); }
JSON & ProtoBuf
(Gson) (Jackson) (Moshi) Wire Serialisations
Wire by Square
Protocol Buffers okioを利用 Server/Clientで定義を共通化 Webからは扱いづらい Wire
Wire syntax = "proto3"; package helloworld; message HelloRequest { string
name = 1; } message HelloReply { string message = 1; } hello.proto
Wire Build # java -jar wire-compiler-2.0.1-jar-with-dependencies.jar \ —proto_path=. \ —java_out=.
hello.proto Writing helloworld.HelloRequest to . Writing helloworld.HelloReply to .
Parcelables
(android-parcelable-intellij-plugin) Parceler (Auto-Value-Parcel) Icepick Parcelables
Parceler by John Ericksen
Annotation Processing AutoValue Parceler
Parceler @Parcel public class User { public String name; public
String thumbnail; User() { } } // Wrap Bundle bundle = new Bundle(); bundle.putParcelable("user", Parcels.wrap(user)); // Unwrap User user = Parcels.unwrap(getIntent().getParcelableExtra("user"));
Icepick by Frankie Sardo
Simple Icepick public class MainActivity extends Activity { @State String
name; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Icepick.restoreInstanceState(this, savedInstanceState); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); Icepick.saveInstanceState(this, outState); } }
Image Loaders
(Universal Image Loader) Picasso Glide Fresco Image Loaders
Picasso by Square
Simple Cache Transformations Debug Picasso
Simple Picasso Picasso.with(context) .load(“http://i.imgur.com/DvpvklR.png”) .setIndicatorsEnabled(true) .into(imageView);
Glide by Google (unofficial)
Glide Bitmap Pool Gif support Thumbnail Animation support Transformations
Simple Glide Glide.with(context) .load(“http://i.imgur.com/DvpvklR.png”) .crossFade() .thumbnail(.1f) .into(imageView);
Picasso? Glide?
Picasso? Glide? http://inthecheesefactory.com/blog/get-to-know-glide-recommended-by-google/en
Picasso? Glide? http://inthecheesefactory.com/blog/get-to-know-glide-recommended-by-google/en
Picasso? Glide? http://inthecheesefactory.com/blog/get-to-know-glide-recommended-by-google/en Library's size
Picasso? Glide? http://inthecheesefactory.com/blog/get-to-know-glide-recommended-by-google/en Method Count
Fresco by Facebook
Fresco Ashmem heap View Gif support Animation
Fresco
Fresco <com.facebook.drawee.view.SimpleDraweeView android:id="@+id/my_image_view" android:layout_width="20dp" android:layout_height="20dp" fresco:fadeDuration="300" fresco:actualImageScaleType="focusCrop" fresco:placeholderImage="@color/wait_color" fresco:placeholderImageScaleType="fitCenter" fresco:failureImage="@drawable/error"
fresco:failureImageScaleType="centerInside" fresco:retryImage="@drawable/retrying" fresco:retryImageScaleType="centerCrop" fresco:progressBarImage="@drawable/progress_bar" fresco:progressBarImageScaleType="centerInside" fresco:progressBarAutoRotateInterval="1000" fresco:backgroundImage="@color/blue" fresco:overlayImage="@drawable/watermark" fresco:pressedStateOverlayImage="@color/red" fresco:roundAsCircle="false" fresco:roundedCornerRadius="1dp" fresco:roundTopLeft="true" fresco:roundTopRight="false" fresco:roundBottomLeft="false" fresco:roundBottomRight="true" fresco:roundWithOverlayColor="@color/corner_color" fresco:roundingBorderWidth="2dp" fresco:roundingBorderColor="@color/border_color" />
Effects
Blurry Android StackBlur GPUImage for Android Picasso/Glide Transformations Effects
Blurry by Wasabeef
Blurry Blur RenderScript DownSampling
Android StackBlur by Enrique López Mañas
Blur RenderScript NDK Android StackBlur
Android StackBlur https://github.com/kikoso/android-stackblur
Android StackBlur https://github.com/kikoso/android-stackblur
GPUImage for Android by CyberAgent
GPUImage OpenGL ES 70 Filters Tone Curve
Picasso/Glide Transformations by Wasabeef
Transformations Picasso, Glide, Fresco Crop Blur Color Filter GPU Filter
DI
(AndroidAnnotations) (Square/Dagger) Google/Dagger Butter Knife DI
Dagger2 by Google
Annotation Processing テスト・メンテナンス Dagger2
Butter Knife by Jake Wharton
View Injection Butter Knife public class MainActivity extends Activity {
@Bind(R.id.user_name) TextView userName; @Bind(R.id.user_thumbnail) ImageView thumbnail; @BindString(R.string.title) String title; @BindDrawable(R.drawable.graphic) Drawable graphic; @BindColor(R.color.red) int red; @BindDimen(R.dimen.spacer) float spacer; }
OnClick, OnTextChange, OnFocusChange...etc Butter Knife @OnClick(R.id.user_name) public void click(View view)
{ // ... } @OnClick({ R.id.user_name, R.id.user_thumbnail }) public void click(View door) { // ... }
FRP
RxJava RxAndroid (RxBinding) (RxLifecycle) FRP
RxJava by Netflix
非同期、リスト操作が簡単 Retrolambdaがあると良い Leakが怖い Retrofitと併用 RxJava
Sample RxJava Observable.just("Google", "Apple", "MicroSoft") .map(String::toUpperCase) .subscribe(name -> { Timber.d("OnNext
" + name); }, throwable -> { Timber.d("OnError"); });
Sample RxJava Observable.just("Google", "Apple", "MicroSoft") .map(String::toUpperCase) .subscribe(name -> { Timber.d("OnNext
" + name); }, throwable -> { Timber.d("OnError"); });
lift compose rxjava-extras (by Dave Moten) RxJava
RxAndroid by RxAndroid authors
Scheduler RxAndroid
Main Thread RxAndroid Observable.just("one", "two", "three", "four", "five") .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(/* an Observer */); final Handler handler = new Handler(); Observable.just("one", "two", "three", "four", "five") .subscribeOn(Schedulers.newThread()) .observeOn(HandlerScheduler.from(handler)) .subscribe(/* an Observer */) Arbitrary Thread
DB/ORM
(ActiveAndroid) Realm (SQLBrite) Android Orma DB/ORM
Realm by Realm
Not SQLite RxJava? Thread間の制約 Realm
Android Orma by gfx
SQLite Annotation Processing RxJava Semi-automatic migration Android Orma
Event Buses
Otto EventBus (RxJava) Event Buses
Otto by Square
Deprecated! Square @Produceが少し便利 Otto
EventBus by greenrobot
EventBus EventBus3 Threading Support Annotation Processing
Debugging
Timber Hugo Debugging Stetho Leak Canary Takt Crashlytics
Timber by Jake Wharton
Logger Timber.Treeを継承して追加する ことで、出力先を自由に変えれる Timber if (BuildConfig.DEBUG) { Timber.plant(new Timber.DebugTree()); }
else { Timber.plant(new CrashReportingTree()); }
Hugo by Jake Wharton
AnnotationでMethod Callsを Loggingできる Hugo @DebugLog public String getName(String first, String
last) { return first + " " + last; } V/Example: ⇢ getName(first="Daichi", last="Furiya") V/Example: ⇠ getName [0ms] = “Daichi Furiya"
Stetho by Facebook
Chrome Developer Toolsを利 用して、Network、Dataの状 況の把握 Stetho-Realm (by uPhyca) Stetho
Stetho
Stetho
Stetho
Leak Canary by Square
メモリリークを検出 Leak Canary
Takt by Wasabeef
FPSを表示 Takt
Crashlytics by Twitter
クラッシュの検出 リアルタイム分析 NDKサポート Crashlytics
Crashlytics
Others
Multi-Dex ProGuard Others
MultiDex by Google
メソッド数の65k制限 最近は安定してきた MultiDex
Android Methods Count MultiDex https://plugins.jetbrains.com/plugin/8076
ProGuard by GuardSquare
ソースコードの難読化 未使用なリソースの削除 難しい ProGuard
ProGuard 15M sample-production.apk Total methods count: 99,280 (multidex enabled) 13M
sample-production-proguard.apk Total methods count: 54,977 Proguard あり Proguard なし
Conclusion
Thank you. twitter.com/wasabeef_jp wasabeef.jp github.com/wasabeef