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
5
1.9k
About Flutter Architecture
wasabeef
1
240
2023 Flutter/Dart Summary
wasabeef
0
73
I/O Extended 2023 - Dart と Flutter の新機能
wasabeef
0
180
I/O Extended 2023 - Flutter 活用事例
wasabeef
10
3k
What it Takes to be a Flutter Developer
wasabeef
0
200
FlutterKaigi 2022 Keynote
wasabeef
1
600
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
Flutterで備える!Accessibility Nutrition Labels完全ガイド
yuukiw00w
0
140
既存デザインを変更せずにタップ領域を広げる方法
tahia910
1
270
Discover Metal 4
rei315
2
110
エンジニア向け採用ピッチ資料
inusan
0
180
地方に住むエンジニアの残酷な現実とキャリア論
ichimichi
5
1.5k
Cursor AI Agentと伴走する アプリケーションの高速リプレイス
daisuketakeda
1
130
PostgreSQLのRow Level SecurityをPHPのORMで扱う Eloquent vs Doctrine #phpcon #track2
77web
2
490
エラーって何種類あるの?
kajitack
5
340
ruby.wasmで多人数リアルタイム通信ゲームを作ろう
lnit
3
350
LT 2025-06-30: プロダクトエンジニアの役割
yamamotok
0
680
AIと”コードの評価関数”を共有する / Share the "code evaluation function" with AI
euglena1215
1
100
“いい感じ“な定量評価を求めて - Four Keysとアウトカムの間の探求 -
nealle
1
2.1k
Featured
See All Featured
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
8
810
The Art of Programming - Codeland 2020
erikaheidi
54
13k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
48
5.4k
StorybookのUI Testing Handbookを読んだ
zakiyama
30
5.9k
Navigating Team Friction
lara
187
15k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
10
940
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
107
19k
Bash Introduction
62gerente
614
210k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
53
2.8k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
Producing Creativity
orderedlist
PRO
346
40k
RailsConf 2023
tenderlove
30
1.1k
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