Slide 1

Slide 1 text

Building complex apps easily Mustafa Ali

Slide 2

Slide 2 text

Building a good app is hard

Slide 3

Slide 3 text

“If I have seen farther than others, it is by standing on the shoulders of giants.” - Isaac Newton Mt. St. Helens Crater Rim by brookehoyer (CC-BY SA)

Slide 4

Slide 4 text

Writing boilerplate code sucks

Slide 5

Slide 5 text

Butter Knife View “injection” library for Android Eliminates boilerplate code Performs annotation-based code generation No reflection Can “inject” listeners as well jakewharton.github.io/butterknife

Slide 6

Slide 6 text

Butter Knife Usage public class ExampleActivity extends Activity { @InjectView(R.id.title) TextView title; @InjectView(R.id.subtitle) TextView subtitle; @InjectView(R.id.footer) TextView footer; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.simple_activity); ButterKnife.inject(this); // TODO Use "injected" views... } } public void inject(ExampleActivity a) { a.subtitle = (android.widget.TextView) a.findViewById(2130963232); a.footer = (android.widget.TextView) a.findViewById(21309685455); a.title = (android.widget.TextView) a.findViewById(21309686566); }

Slide 7

Slide 7 text

Butter Knife Usage @OnClick(R.id.submit) public void sayHi(Button button) { button.setText("Live long and prosper"); } @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, "DIE DIE DIE!", LENGTH_SHORT).show(); } } @OnItemSelected(R.id.list_view) void onItemSelected(int position) { // Do something with the “chosen one” } @OnItemSelected(value = R.id.maybe_missing, callback = NOTHING_SELECTED) void onNothingSelected() { // Y u no select anything? }

Slide 8

Slide 8 text

Integrating APIs is tricky GET, PUT, POST …. WUT???

Slide 9

Slide 9 text

Retrofit Type-safe REST client for Android and Java Turns your REST API into a Java interface Each HTTP verb is represented by an annotation Requests can be both synchronous & asynchronous Automatic deserialization using GSON, Simple, etc square.github.io/retrofit

Slide 10

Slide 10 text

Retrofit Usage public interface GoogleBooksService { @GET("/books/v1/volumes") void search(@Query("q") String query, Callback callback); } GET https://www.googleapis.com/books/v1/volumes?q=android RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint("https://www.googleapis.com") .setLogLevel(RestAdapter.LogLevel.FULL) .build(); GoogleBooksService service = restAdapter.create(GoogleBooksService.class);

Slide 11

Slide 11 text

Synchronous SearchResult result = service.search(query); Retrofit Usage Asynchronous service.search(query, callback); private Callback callback = new Callback() { @Override public void success(SearchResults searchResults, Response response) { displayResults(searchResults); } @Override public void failure(RetrofitError error) { displayError(error); } };

Slide 12

Slide 12 text

Image Loading

Slide 13

Slide 13 text

Picasso Hassle-free image downloading and caching Handles ImageView recycling automatically Performs download cancellations automatically Allows complex image transformations Automatic memory and disk caching square.github.io/picasso

Slide 14

Slide 14 text

Picasso Usage Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView); Picasso.with(context) .load(url) .resize(50, 50) .centerCrop() .placeholder(R.drawable.user_placeholder) .error(R.drawable.user_placeholder_error) .into(imageView) Picasso.with(context).load(R.drawable.landing_screen).into(imageView1); Picasso.with(context).load("file:///android_asset/DvpvklR.png").into(imageView2); Picasso.with(context).load(new File(...)).into(imageView3);

Slide 15

Slide 15 text

Microsavings Small things, big benefits

Slide 16

Slide 16 text

Timber Logger built on top of android.util.Log Small and extensible API Automatic smart tagging No logging in production, ever! jakewharton.github.io/timber

Slide 17

Slide 17 text

Timber Usage public class SherlockApplication extends Application { @Override public void onCreate() { super.onCreate(); if (BuildConfig.DEBUG) { Timber.plant(new Timber.DebugTree()); } else { Timber.plant(new CrashReportingTree()); } } } Timber.i("A button with ID %s was clicked to say '%s'.", button.getId(), button.getText()); Timber.e("Search failed with error: " + error.getKind());

Slide 18

Slide 18 text

Timber Usage private static class CrashReportingTree extends Timber.HollowTree { @Override public void i(String message, Object... args) { // TODO e.g., Crashlytics.log(String.format(message, args)); } @Override public void i(Throwable t, String message, Object... args) { i(message, args); // Just add to the log. } @Override public void e(String message, Object... args) { i("ERROR: " + message, args); // Just add to the log. } @Override public void e(Throwable t, String message, Object... args) { e(message, args); // TODO e.g., Crashlytics.logException(t); } }

Slide 19

Slide 19 text

Demo

Slide 20

Slide 20 text

Q & A Ask me questions! Code available at - github.com/mustafa01ali/Sherlock

Slide 21

Slide 21 text

Thank you! You can reach out to me at @mustafa01ali