Your SlideShare is downloading. ×
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Dependency Injection for Android @ Ciklum speakers corner Kiev 29. May 2014

274

Published on

We are happy to invite you to the Speakers’ Corner today, on Thursday May 29, from 18.30 till 19.30 at SkyPoint to meet Thomas Vervik, Head of Development Bipper Communications who will talk on “How …

We are happy to invite you to the Speakers’ Corner today, on Thursday May 29, from 18.30 till 19.30 at SkyPoint to meet Thomas Vervik, Head of Development Bipper Communications who will talk on “How to save money on QA - Dependency Injection and automated testing on Android”

Thomas is Head of Development for Bipper Communications, and has been managing the company's team in Kiev since February 2012. Originally a seasoned Java server backend/frontend developer, he has the last two years started mobile development, first with HTML 5 and later Android.

Mobile development has since its birth around 2008 gone from simple apps to more complex enterprise similar software. The increase in size and complexity yields the need for structuring the code differently in order to handle the new complexity. The tools used to handle this complexity has been applied to server side development for years, but mobile development has been lagging behind.

But not anymore. New frameworks built on proven paradigms are emerging, and in this Speakers Corner we will introduce Dependency Injection for Android, the motivation for its use, and one of the implementations - Dagger. Dependency Injection has several advantages, but in this presentation we will focus on how it enables to write proper automated tests.

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
274
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
1
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • So we gonna build a sample app which shows:
    1) how to set up the object graph in Application context.
    2) how inject dependencies into an Activity
    3) when clicking button, spin off a background thread which makes an HTTP request and show the request in view
    4) build test module which mocks the HTTP client
    5) create ActivityUnitTest which loads the Test module and injects the HTTP client
  • Transcript

    • 1. Automated testing Android Dependency Injection and Dagger
    • 2. Dependency Injection Dagger Live Coding Sample 1 Live Coding Sample 2
    • 3. The Business Goal
    • 4. Why not automated tests on mobile?
    • 5. Motivation for Dependency Injection ● Decouple concrete from concrete ● Uniformity ● Reduced Dependency Carrying ● More Testable Code
    • 6. Decouple concrete from Concrete class MyStringUtils { private Context context; StringUtils(Context context) { this.context = context; } public String helloWorld() { return context.getString(R.string.hello_ciklum); } }
    • 7. Decouple concrete from Concrete class MainActivity extends Activity implements View.OnClickListener { @Inject MyStringUtils myStringUtils; void onCreate(Bundle savedInstanceState) { … } void onClick(View v) { MyStringUtils myStringUtils1 = new MyStringUtils(this.getApplication()); // new operator MyStringUtils myStringUtils2 = MyStringUtils.getInstance(this); // singleton pattern MyStringUtils myStringUtils3 = MyStringUtilsFactory.getInstance(this); // factory patterns String str1 myStr = MyStringUtils.helloWorld(this); // Static String str = myStringUtils.helloWorld(); TextView msgView = (TextView) findViewById(R.id.textView); msgView.setText(str); }}}
    • 8. Uniformity class MainActivity extends Activity implements View.OnClickListener { @Inject MyStringUtils myStringUtils; void onCreate(Bundle savedInstanceState) { … } void onClick(View v) { MyStringUtils myStringUtils1 = new MyStringUtils(this.getApplication()); // new instance MyStringUtils myStringUtils2 = MyStringUtils.getInstance(this); // Singleton pattern MyStringUtils myStringUtils3 = MyStringUtilsFactory.getInstance(this); // Factory pattern String str1 myStr = MyStringUtils.helloWorld(this); // Static String str = myStringUtils.helloWorld(); TextView msgView = (TextView) findViewById(R.id.textView); msgView.setText(str); } }}
    • 9. Dependency Carrying class MyActivity extends Activity { onClick(View v) { A a = new A(this); a.doSometing(); } } class A { Context mContext; public (Context mContext){ this.mContext = mContext; } public doSomething() { B b = new B(mContext); String str = b.getSomeString(R.strings.helloWorld); } } class B { Context mContext; public B(Context mContext) { this.mContext = mContext; } public String getSomeString(int resourceId) { return mContext.getString(resourceId); } }
    • 10. Reduced Dependency Carrying @Module class ProdModule { Context mContext; public ProdModule(Context mContext) { this.mContext = mContext; } @Provide B provideB() { return new B(context); } @Provide A provideA(B b) { return new A(b); } } class MyActivity { @Inject A a; onCreate(){ ((MyApplication)getApplication()).inject(this); } onClick(View v) { A a = new A(this); a.doSomething(); } } class A { @Inject B b; public doSomething() { String str = b.getSomeString(R.strings.helloWorld); } } class B { Context mContext; public B(Context mContext) { this.mContext = mContext; } public String getSomeString(int resourceId) { return mContext.getString(resourceId); } }
    • 11. More Testable Code class MainActivity extends Activity implements View.OnClickListener { @Inject MyStringUtils myStringUtils; void onCreate(Bundle savedInstanceState) { … } void onClick(View v) { String str = myStringUtils.helloWorld(); TextView msgView = (TextView) findViewById(R.id.textView); msgView.setText(str); } }}
    • 12. Other advantages ● More Reusable Code ● More Readable Code ● Reduced Dependencies
    • 13. Dependency Injection Dagger Live Coding Sample 1 Live Coding Sample 2
    • 14. DAGger Direct Acyclic Graph
    • 15. Coffee maker public class CoffeMaker { @Inject Heater heater; @Inject Pump pump; public void brew() { heater.on(); pump.pump(); System.out.println("coffee!"); heater.off(); } }
    • 16. class Thermosiphon implements Pump { Heater heater; Thermosiphon(Heater heater) { this.heater = heater; } @Override public void pump() { if (heater.isHot()) { System.out.println("=> => pumping => =>"); } }
    • 17. Declare Dependencies class Thermosiphon implements Pump { Heater heater; @Inject Thermosiphon(Heater heater) { this.heater = heater; } }
    • 18. Satisfy Dependencies @Module class DripCoffeeModule { @Provides Heater provideHeater() { return new ElectricHeater(); } @Provides Pump providePump(Thermosiphon pump) { return pump; } }
    • 19. Build the Graph class CoffeeApp { public static void main(String[] args) { ObjectGraph objectGraph = ObjectGraph.create(new DripCoffeeModule()); CoffeeMaker coffeeMaker = objectGraph.get(CoffeeMaker.class); coffeeMaker.brew(); } }
    • 20. Neat features ● Lazy<T> ● Module overrides
    • 21. Lazy<T> class GridingCoffeeMaker { @Inject Lazy<Grinder> lazyGrinder; public void brew() { while (needsGrinding()) { // Grinder created once and cached. Grinder grinder = lazyGrinder.get() grinder.grind(); } } }
    • 22. Module Overrides @Module( includes = DripCoffeeModule.class, injects = CoffeeMakerTest.class, overrides = true ) static class TestModule { @Provides @Singleton Heater provideHeater() { return Mockito.mock(Heater.class); } }
    • 23. Dependency Injection Dagger Live Coding Sample 1 Live Coding Sample 2
    • 24. Live coding - Sample 1 ● add dependencies (with Gradle) ● create module ● set up Dagger in Application context ● inject dependencies to Activity ● create Activity test which injects a mock
    • 25. Add depedencies (Gradle) dependencies { ……... compile 'com.squareup.dagger:dagger:1.2.1' compile 'com.squareup.dagger:dagger-compiler:1.2.1' androidTestCompile 'org.mockito:mockito-core:1.9.5' androidTestCompile 'com.google.dexmaker:dexmaker:1.0' androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.0' }
    • 26. Module @Module( injects = { MyStringUtils.class, MainActivity.class }) class ProdModule { Application application; ProdModule(Application application){ this.application = application; } @Provides @Singleton MyStringUtils provideMyStringUtils() { return new MyStringUtils(application); }
    • 27. Define Dagger Application class MyApplication extends Application { ObjectGraph mGraph; void onCreate() { super.onCreate(); mGraph = ObjectGraph.create(getModules().toArray()); } void inject(Object o){ mGraph.inject(o); } List<Object> getModules() { List<Object> result = new ArrayList<Object>(); result.add(new ProdModule(this)); return result; }}
    • 28. Create MyStringUtils class MyStringUtils { MyStringUtils(Context context) { this.context = context; } public String helloWorld() { return context.getString(R.string.hello_ciklum); } }
    • 29. Inject dependencies Activity class MainActivity extends Activity { @Inject MyStringUtils myStringUtils; void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // set dependencies to this activity ((MyApplication)getApplication()).inject(this); setContentView(R.layout.activity_main); findViewById(R.id.button).setOnClickListener(this); }
    • 30. Unit test Activity with mock class MainActivityUnitTest extends ActivityUnitTestCase<MainActivity> { @Inject MyStringUtils myStringUtils; void setUp() { // create test application context, Dagger Graph with our test module. MyApplication application = new TestApplication(); application.inject(this); // inject the dependencies we need to this class setApplication(application); // use our custom test application context } void testOnClick() { String testingStr = "olala"; when(myStringUtils.helloWorld()).thenReturn(testingStr); this.activity = startActivity(intent, null, null); // the test View view = activity.findViewById(R.id.button); activity.onClick(view); // verify the mock was invoked verify(myStringUtils, times(1)).helloWorld(); // assert view got updated correctly TextView msgView = (TextView) activity.findViewById(R.id.textView); assertEquals(testingStr, msgView.getText()); }
    • 31. Dependency Injection Dagger Live Coding Sample 1 Live Coding Sample 2
    • 32. Sample app 2 ● Threads ● HTTP mocks
    • 33. Tips, tricks and Frameworks ● https://github.com/tha022/dagger-testing-example ● https://github.com/fizz-buzz/fb-android-dagger

    ×