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
Daichi Furiya (Wasabeef)
February 17, 2016
Programming
6
12k
Day1 Keynote in DroidKaigi 2016
Day1 Keynote in DroidKaigi 2016
Daichi Furiya (Wasabeef)
February 17, 2016
Tweet
Share
More Decks by Daichi Furiya (Wasabeef)
See All by Daichi Furiya (Wasabeef)
DevFest Tokyo 2025 - Flutter のアプリアーキテクチャ現在地点
wasabeef
6
2k
About Flutter Architecture
wasabeef
1
260
2023 Flutter/Dart Summary
wasabeef
0
81
I/O Extended 2023 - Dart と Flutter の新機能
wasabeef
0
190
I/O Extended 2023 - Flutter 活用事例
wasabeef
10
3k
What it Takes to be a Flutter Developer
wasabeef
0
200
FlutterKaigi 2022 Keynote
wasabeef
1
620
Flutter Hooks を使ったアプリ開発 / App Development with the Flutter Hooks
wasabeef
2
1.4k
Flutter 2021 の振り返りと今後のアプリ開発に向けて / Looking back on Flutter 2021 and for future app development.
wasabeef
4
2.2k
Other Decks in Programming
See All in Programming
あなたとJIT, 今すぐアセンブ ル
sisshiki1969
1
720
Kiroの仕様駆動開発から見えてきたAIコーディングとの正しい付き合い方
clshinji
1
140
画像コンペでのベースラインモデルの育て方
tattaka
3
1.8k
CSC305 Summer Lecture 05
javiergs
PRO
0
110
CEDEC2025 長期運営ゲームをあと10年続けるための0から始める自動テスト ~4000項目を50%自動化し、月1→毎日実行にした3年間~
akatsukigames_tech
0
150
UbieのAIパートナーを支えるコンテキストエンジニアリング実践
syucream
2
700
CEDEC 2025 『ゲームにおけるリアルタイム通信への QUIC導入事例の紹介』
segadevtech
3
970
Langfuseと歩む生成AI活用推進
licux
3
290
TDD 実践ミニトーク
contour_gara
0
140
LLMOpsのパフォーマンスを支える技術と現場で実践した改善
po3rin
8
980
Portapad紹介プレゼンテーション
gotoumakakeru
1
130
オホーツクでコミュニティを立ち上げた理由―地方出身プログラマの挑戦 / TechRAMEN 2025 Conference
lemonade_37
2
490
Featured
See All Featured
Making Projects Easy
brettharned
117
6.3k
How to Ace a Technical Interview
jacobian
279
23k
Side Projects
sachag
455
43k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
Typedesign – Prime Four
hannesfritz
42
2.8k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
33
2.4k
Music & Morning Musume
bryan
46
6.7k
Why Our Code Smells
bkeepers
PRO
338
57k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
15
1.6k
jQuery: Nuts, Bolts and Bling
dougneiner
64
7.9k
The Invisible Side of Design
smashingmag
301
51k
Fireside Chat
paigeccino
39
3.6k
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