Download - Android and the Seven Dwarfs from Devox'15
![Page 1: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/1.jpg)
Snow White and the Seven Dwarfs
Murat Yener @yenerm
Android
![Page 2: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/2.jpg)
who am I?-Java, Android, web -Android Dev @Intel -Conference Speaker (JavaOne, Devoxx…) -GDG Istanbul Organizer -Book Author -Java Champion -GDE on Android
![Page 3: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/3.jpg)
40% discount with promo
code
VBK43 when ordering
through wiley.com
valid until end of December 2015
![Page 4: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/4.jpg)
Once upon a time…
![Page 5: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/5.jpg)
the princess…well, the Android
had some problems after eating an… apple
while waiting for the prince charming…
![Page 6: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/6.jpg)
can Seven Dwarfs help? Butterknife
Dagger
Volley / OkHttp / Retrofit
GreenBus / Otto
GreenDAO / Schematic
Priority JobQueue
Timber / Hugo
![Page 7: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/7.jpg)
Butterknife
Dependency Injection for views and actions
Cleaner code
Simple annotation based usage
Use Nullable to avoid exceptions
Based on compile time code generation
compile ‘com.jakewharton:butterknife:7.0.1’
![Page 8: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/8.jpg)
class ExampleActivity extends Activity {
@Bind(R.id.title) TextView title;
@Bind(R.id.subtitle) TextView subtitle;
@Bind(R.id.footer) TextView footer;
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_activity);
ButterKnife.bind(this);
// TODO Use fields...
}
}
![Page 9: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/9.jpg)
@Nullable @Bind(R.id.might_not_be_there) TextView mightNotBeThere;
@Nullable @OnClick(R.id.maybe_missing) void onMaybeMissingClicked() {
// TODO ...
}
![Page 10: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/10.jpg)
//Simple listener injection
@OnClick(R.id.submit)
public void submit(View view) {
// TODO submit data to server...
}
//Multi listener
@OnClick({ R.id.door1, R.id.door2, R.id.door3 })
public void pickDoor(DoorView door) {
if (door.hasPrizeBehind()) {
Toast.makeText(this, "You win!", LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Try again", LENGTH_SHORT).show();
}
}
![Page 11: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/11.jpg)
ProGuard Configuration
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewInjector { *; }
-keepclasseswithmembernames class * {
@butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
@butterknife.* <methods>;
}
![Page 12: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/12.jpg)
DaggerFast dependency injection
Standard javax.inject (JSR 330)
Make your code easy to test
Compile time code generation (No reflection)
Complicated
Hard to do for ongoing project
compile 'com.google.dagger:dagger:2.0' apt 'com.google.dagger:dagger-compiler:2.0'
![Page 13: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/13.jpg)
@Module + @Provides: mechanism for providing dependencies.
@Inject: mechanism for requesting dependencies.
@Component: bridge between modules and injections
![Page 14: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/14.jpg)
class CoffeeMaker { @Inject Heater heater; @Inject Pump pump; ...} @Moduleclass DripCoffeeModule { @Provides Heater provideHeater() { return new ElectricHeater(); } @Provides Pump providePump(Thermosiphon pump) { return pump; }}
@Component(modules = DripCoffeeModule.class) interface CoffeeShop { CoffeeMaker maker();}
![Page 15: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/15.jpg)
public @interface Component { Class<?>[] modules() default {}; Class<?>[] dependencies() default {};}
public @interface Module { Class<?>[] includes() default { };} public @interface Provides { }
public @interface MapKey { boolean unwrapValue();}
public interface Lazy<T> { T get();}
![Page 16: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/16.jpg)
ProGuard Configuration
NONE
![Page 17: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/17.jpg)
OkHttp
Widely used, simple fix for HttpClient
Internal cache
HTTP2 and SPDY support
Uses GZIP
Manual handling of background execution
compile 'com.squareup.okhttp:okhttp:2.5.0'
![Page 18: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/18.jpg)
//ClientOkHttpClient client = new OkHttpClient(); //Get URLString run(String url) throws IOException { Request request = new Request.Builder() .url(url) .build(); Response response = client.newCall(request).execute(); return response.body().string(); } //Post URL public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); String post(String url, String json) throws IOException { RequestBody body = RequestBody.create(JSON, json); Request request = new Request.Builder() .url(url) .post(body) .build(); Response response = client.newCall(request).execute(); return response.body().string(); }
![Page 19: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/19.jpg)
ProGuard Configuration
-keepattributes Signature
-keepattributes *Annotation*
-keep class com.squareup.okhttp.** { *; }
-keep interface com.squareup.okhttp.** { *; }
-dontwarn com.squareup.okhttp.**
![Page 20: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/20.jpg)
Volley
Simplest HttpClient fix for Android
Internal Queue
Internal Cache
Runs in a separate thread
Not good for large downloads
compile ‘com.mcxiaoke.volley:library-aar:1/0/0’
![Page 21: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/21.jpg)
RequestQueue queue = Volley.newRequestQueue(this); StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { @Override public void onResponse(String response) { //.. } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { //.. } }); queue.add(stringRequest);
//Cancel requests queue.cancelAll(TAG);
![Page 22: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/22.jpg)
ProGuard Configuration
NONE
![Page 23: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/23.jpg)
RetrofitREST Client for Java
Generates an implementation of the API
Uses annotation to describe URLs, query params
Object conversion to JSON request body
Multipart request body and file upload
Only good for REST APIs
compile 'com.squareup.retrofit:retrofit:1.9.0'
![Page 24: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/24.jpg)
public interface GitHubService { @Headers("Cache-Control: max-age=640000") @GET("/users/{user}/repos") List<Repo> listRepos(@Path("user") String user); @POST("/users/new") void createUser(@Body User user, Callback<User> cb);}
RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint("https://api.github.com") .build();GitHubService service = restAdapter.create(GitHubService.class);
List<Repo> repos = service.listRepos("octocat");
![Page 25: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/25.jpg)
-keep class com.squareup.okhttp.** { *; }-keep interface com.squareup.okhttp.** { *; }-dontwarn com.squareup.okhttp.**
-dontwarn rx.**-dontwarn retrofit.**-dontwarn okio.**-keep class retrofit.** { *; }
-keepclasseswithmembers class * { @retrofit.http.* <methods>;}
![Page 26: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/26.jpg)
GreenRobot EventBus
Dispatches events through a bus
Event Driven
Very easy and clean implementation
Easily transfer data between components
Uses reflection on runtime
compile 'de.greenrobot:eventbus:2.4.0'
![Page 27: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/27.jpg)
//Custom Event Object
public class SampleEvent {
private String message;
public SampleEvent(String message){
this.message=message;
}
}
//Caller
//geteventbus
eventBus.post(new SampleEvent(“An event”);
![Page 28: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/28.jpg)
//callee
//geteventbus
eventBus.register(this);
public void onEvent(SampleEvent event) {
textField.setText(event.getMessage());
};
![Page 29: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/29.jpg)
ProGuard Configuration
-keepclassmembers class ** {
public void onEvent*(**);
}
# Only required if you use AsyncExecutor
-keepclassmembers class * extends
de.greenrobot.event.util.ThrowableFailureEvent {
public <init>(java.lang.Throwable);
}
# Don't warn for missing support classes
-dontwarn de.greenrobot.event.util.*$Support
-dontwarn de.greenrobot.event.util.*$SupportManagerFragment
![Page 30: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/30.jpg)
Otto
Event bus
decouple different parts of your application
Communication between components
Uses reflection
compile 'com.squareup:otto:1.3.8'
![Page 31: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/31.jpg)
Bus bus = new Bus();bus.post(new AnswerAvailableEvent(42));bus.register(this);
@Subscribepublic void answerAvailable(AnswerAvailableEvent event) { // TODO: React to the event somehow!}
![Page 32: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/32.jpg)
-keepclassmembers class ** {
@com.squareup.otto.Subscribe public *;
@com.squareup.otto.Produce public *;
}
![Page 33: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/33.jpg)
GreenDao
from the creators of GreenRobot EventBus
Standard SqLite
No create table… etc
Uses code generation for model and dao
compile 'de.greenrobot:greendao'
![Page 34: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/34.jpg)
new DaoMaster.DevOpenHelper(this, "notes-db", null);
daoMaster = new DaoMaster(db);daoSession = daoMaster.newSession();noteDao = daoSession.getNoteDao();
Note note = new Note(null, noteText, comment, new Date());noteDao.insert(note);
![Page 35: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/35.jpg)
-keepclassmembers class * extends de.greenrobot.dao.AbstractDao {
public static java.lang.String TABLENAME;
}
-keep class **$Properties
![Page 36: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/36.jpg)
SchematicAutomatically generate ContentProviders
Backed by SQLite Database
Can be used w/ Android System
Loaders, SyncAdapter, Permissions
Harder to use (deal w/ Cursors)
apt ‘net.simonvt.schematic:schematic-compiler:0.6.0’ compile ‘net.simonvt.schematic:schematic:0.6.0’
![Page 37: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/37.jpg)
public interface ListColumns { @DataType(INTEGER) @PrimaryKey @AutoIncrement String _ID = "_id"; @DataType(TEXT) @NotNull String TITLE = "title"; } @Database(version = NotesDatabase.VERSION) public final class NotesDatabase { public static final int VERSION = 1; @Table(ListColumns.class) public static final String LISTS = "lists"; } @ContentProvider(authority = NotesProvider.AUTHORITY, database = NotesDatabase.class) public final class NotesProvider { public static final String AUTHORITY = "net.simonvt.schematic.sample.NotesProvider"; @TableEndpoint(table = NotesDatabase.LISTS) public static class Lists { @ContentUri( path = Path.LISTS, type = "vnd.android.cursor.dir/list", defaultSort = ListColumns.TITLE + " ASC") public static final Uri LISTS = Uri.parse("content://" + AUTHORITY + "/lists") }}
![Page 38: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/38.jpg)
ProGuard Configuration
NONE
![Page 39: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/39.jpg)
Priority JobQueue
Persistent queue for scheduling jobs
Easy to prioritize
Delay job execution
Group jobs for batch execution
Not really needed above 5.0
compile 'com.path:android-priority-jobqueue:1.1.2'
![Page 40: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/40.jpg)
public class PostTweetJob extends Job { public static final int PRIORITY = 1; public PostTweetJob(String text) { super(new Params(PRIORITY).requireNetwork().persist()); } @Override public void onAdded() {} @Override public void onRun() throws Throwable { webservice.postTweet(text); } @Override protected boolean shouldReRunOnThrowable(Throwable throwable) { }}
![Page 41: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/41.jpg)
ProGuard Configuration
NONE
![Page 42: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/42.jpg)
TimberLogger with a small, extensible API
Default behavior: Nothing
Behavior is added through Tree instances.
Install instance by calling Timber.plant()
DebugTree: output logs for debug builds and auto tag generation
compile 'com.jakewharton.timber:timber:4.1.0'
![Page 43: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/43.jpg)
/** A tree which logs important information for crash reporting. */private static class CrashReportingTree extends Timber.Tree { @Override protected void log(int priority, String tag, String message, Throwable t) { if (priority == Log.VERBOSE || priority == Log.DEBUG) { return; } FakeCrashLibrary.log(priority, tag, message); if (t != null) { if (priority == Log.ERROR) { FakeCrashLibrary.logError(t); } else if (priority == Log.WARN) { FakeCrashLibrary.logWarning(t); } } }}
![Page 44: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/44.jpg)
public void greetingClicked(Button button) { Timber.i("A button with ID %s was clicked.", button.getId());
//Do stuff}
![Page 45: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/45.jpg)
ProGuard Configuration
NONE
![Page 46: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/46.jpg)
Hugo
Annotation-triggered method call logging
Generates logging code
Zero effect on non-debug builds.
see next slide
![Page 47: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/47.jpg)
buildscript { repositories { mavenCentral() } dependencies { classpath 'com.jakewharton.hugo:hugo-plugin:1.2.1' } } apply plugin: 'com.android.application'apply plugin: 'com.jakewharton.hugo'
![Page 48: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/48.jpg)
@DebugLogpublic String getName(String first, String last) { SystemClock.sleep(15); // Don't ever really do this! return first + " " + last;}
V/Example: ⇢ getName(first="Jake", last="Wharton") V/Example: ⇠ getName [16ms] = "Jake Wharton"
![Page 49: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/49.jpg)
ProGuard Configuration
NONE
![Page 50: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/50.jpg)
BONUSThe Prince Charming: Lambdas on Android
![Page 51: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/51.jpg)
wait, Java 8?!?
Android 5.0 and above use Java 7
but not invokeDynamic
so no Lambdas…
![Page 52: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/52.jpg)
Retrolambda
lambda expressions
method references
try-with-resources statements
limited support for backporting default methods and static methods on interfaces
![Page 53: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/53.jpg)
buildscript { repositories { mavenCentral() }
dependencies { classpath 'me.tatarka:gradle-retrolambda:3.2.3' } }
// Required because retrolambda is on maven central repositories { mavenCentral() }
apply plugin: 'com.android.application' //or apply plugin: 'java' apply plugin: ‘me.tatarka.retrolambda'
OR
plugins { id "me.tatarka.retrolambda" version "3.2.3" }
![Page 54: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/54.jpg)
PROGUARD -dontwarn java.lang.invoke.*
Android Studio build.gradle
android { compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } }
![Page 55: Android and the Seven Dwarfs from Devox'15](https://reader031.vdocuments.site/reader031/viewer/2022011722/58f333771a28ab34258b4573/html5/thumbnails/55.jpg)
Libraries fix things…
Use them only when you have a (exprected) problem…
and don’t overuse them…
Conclusion…