├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── android-wait-for-emulator ├── app ├── .gitignore ├── build.gradle ├── libs │ ├── auto-common-1.0-20150122.001631-7.jar │ ├── dagger-compiler-2.0-20150122.022637-13.jar │ └── dagger-producers-2.0-20150122.022620-1.jar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── newegg │ │ └── tr │ │ └── dagger2prac │ │ ├── ApplicationTest.java │ │ ├── model │ │ ├── ActionModelTest.java │ │ ├── ConfigManagerTest.java │ │ └── MessageModelTest.java │ │ └── ui │ │ ├── MainActivityTest.java │ │ └── SettingActivityTest.java │ ├── debug │ └── java │ │ └── com │ │ └── newegg │ │ └── tr │ │ └── dagger2prac │ │ └── view │ │ ├── MainTestCase.java │ │ ├── SettingTestCase.java │ │ ├── component │ │ ├── GlobalComponent.java │ │ ├── MainComponent.java │ │ └── SettingComponent.java │ │ └── module │ │ ├── GlobleModule.java │ │ ├── TestMainModule.java │ │ └── TestSettingModule.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── newegg │ │ │ └── tr │ │ │ └── dagger2prac │ │ │ ├── Dagger2pracApp.java │ │ │ ├── model │ │ │ ├── action │ │ │ │ ├── Action.java │ │ │ │ ├── ActionModel.java │ │ │ │ └── ActionType.java │ │ │ ├── config │ │ │ │ ├── Config.java │ │ │ │ └── ConfigManager.java │ │ │ └── message │ │ │ │ ├── MessageModel.java │ │ │ │ └── Messenger.java │ │ │ ├── presenter │ │ │ ├── MainPresenter.java │ │ │ ├── SettingPresenter.java │ │ │ └── internal │ │ │ │ ├── MainPresenterImpl.java │ │ │ │ └── SettingPresenterImpl.java │ │ │ └── view │ │ │ ├── MainPageView.java │ │ │ ├── SettingView.java │ │ │ ├── activity │ │ │ ├── BaseActivity.java │ │ │ ├── MainActivity.java │ │ │ └── SettingActivity.java │ │ │ └── scope │ │ │ ├── Main.java │ │ │ └── Setting.java │ └── res │ │ ├── drawable-hdpi │ │ └── ic_launcher.png │ │ ├── drawable-mdpi │ │ └── ic_launcher.png │ │ ├── drawable-xhdpi │ │ └── ic_launcher.png │ │ ├── drawable-xxhdpi │ │ └── ic_launcher.png │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── activity_setting.xml │ │ └── activity_setting_dialog.xml │ │ ├── menu │ │ └── menu_main.xml │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ ├── values │ │ ├── dimens.xml │ │ ├── strings.xml │ │ ├── strings_activity_settings.xml │ │ └── styles.xml │ │ └── xml │ │ ├── pref_data_sync.xml │ │ ├── pref_general.xml │ │ ├── pref_headers.xml │ │ └── pref_notification.xml │ └── release │ └── java │ └── com │ └── newegg │ └── tr │ └── dagger2prac │ └── view │ ├── component │ ├── GlobalComponent.java │ ├── MainComponent.java │ └── SettingComponent.java │ └── module │ ├── GlobleModule.java │ ├── MainModule.java │ └── SettingModule.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── keystore └── release-test.keystore └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Generated files 3 | bin/ 4 | gen/ 5 | 6 | # Gradle files 7 | .gradle/ 8 | build/ 9 | 10 | # Local configuration file (sdk path, etc) 11 | local.properties 12 | 13 | # Proguard folder generated by Eclipse 14 | proguard/ 15 | 16 | # Log Files 17 | *.log 18 | 19 | # Android Studio config files 20 | *.iml 21 | .idea -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | jdk: oraclejdk7 3 | 4 | env: 5 | matrix: 6 | - ANDROID_TARGET=android-21 ANDROID_ABI=armeabi-v7a 7 | 8 | android: 9 | components: 10 | - build-tools-21.1.2 11 | - android-21 12 | 13 | # Emulator Management: Create, Start and Wait 14 | before_script: 15 | - echo no | android create avd --force -n test -t android-21 --abi armeabi-v7a 16 | - emulator -avd test -no-skin -no-audio -no-window & 17 | - adb wait-for-device 18 | - adb shell input keyevent 82 & 19 | 20 | script: ./gradlew connectedAndroidTest -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dagger2Example 2 | Android unit testing example with Dagger2, Espresso 2.0 and mockito. 3 | -------------------------------------------------------------------------------- /android-wait-for-emulator: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Originally written by Ralf Kistner , but placed in the public domain 4 | 5 | set +e 6 | 7 | bootanim="" 8 | failcounter=0 9 | timeout_in_sec=360 10 | 11 | until [[ "$bootanim" =~ "stopped" ]]; do 12 | bootanim=`adb -e shell getprop init.svc.bootanim 2>&1 &` 13 | if [[ "$bootanim" =~ "device not found" || "$bootanim" =~ "device offline" 14 | || "$bootanim" =~ "running" ]]; then 15 | let "failcounter += 1" 16 | echo "Waiting for emulator to start" 17 | if [[ $failcounter -gt timeout_in_sec ]]; then 18 | echo "Timeout ($timeout_in_sec seconds) reached; failed to start emulator" 19 | exit 1 20 | fi 21 | fi 22 | sleep 1 23 | done 24 | 25 | echo "Emulator is ready" -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'com.neenbedankt.android-apt' 3 | 4 | android { 5 | compileSdkVersion 21 6 | buildToolsVersion "21.1.2" 7 | 8 | defaultConfig { 9 | applicationId "com.newegg.tr.dagger2prac" 10 | minSdkVersion 8 11 | targetSdkVersion 21 12 | versionCode 1 13 | versionName "1.0" 14 | 15 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 16 | } 17 | 18 | // jacoco { 19 | // version = '0.6.2.201302030002' 20 | // } 21 | 22 | compileOptions { 23 | sourceCompatibility JavaVersion.VERSION_1_7 24 | targetCompatibility JavaVersion.VERSION_1_7 25 | } 26 | signingConfigs { 27 | release { 28 | storeFile file("../keystore/release-test.keystore") 29 | storePassword "keyword" 30 | keyAlias "aliasTest" 31 | keyPassword "keyword" 32 | } 33 | } 34 | 35 | buildTypes { 36 | release { 37 | minifyEnabled false 38 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 39 | signingConfig signingConfigs.release 40 | } 41 | debug { 42 | minifyEnabled false 43 | debuggable true 44 | testCoverageEnabled = true 45 | } 46 | } 47 | 48 | lintOptions { 49 | abortOnError false 50 | } 51 | 52 | packagingOptions { 53 | exclude 'LICENSE.txt' 54 | exclude 'META-INF/services/javax.annotation.processing.Processor' 55 | } 56 | } 57 | 58 | dependencies { 59 | 60 | // compile fileTree(dir: 'libs', include: ['*.jar']) 61 | compile 'com.android.support:appcompat-v7:21.0.3' 62 | 63 | //guava 64 | // compile 'com.google.guava:guava:18.0' 65 | 66 | //Dagger 2 67 | compile 'com.google.dagger:dagger:2.0-SNAPSHOT' 68 | apt 'com.google.dagger:dagger-compiler:2.0-SNAPSHOT' 69 | androidTestApt 'com.google.dagger:dagger-compiler:2.0-SNAPSHOT' 70 | provided 'javax.annotation:jsr250-api:1.0' 71 | // Reference local dagger compiler jar,avoiding dagger are broken build. 72 | // apt files('libs/dagger-producers-2.0-20150122.022620-1.jar') 73 | // apt files('libs/dagger-compiler-2.0-20150122.022637-13.jar') 74 | // apt files('libs/auto-common-1.0-20150122.001631-7.jar') 75 | // apt 'com.squareup:javawriter:2.5.0' 76 | // apt 'com.google.guava:guava:18.0' 77 | 78 | //ButterKnife 79 | compile 'com.jakewharton:butterknife:6.1.0' 80 | 81 | //Mockito 82 | debugCompile "org.mockito:mockito-core:1.9.5" 83 | debugCompile "com.google.dexmaker:dexmaker:1.0" 84 | debugCompile "com.google.dexmaker:dexmaker-mockito:1.0" 85 | 86 | //Espresso 2 87 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.0') { 88 | exclude group: 'javax.inject' 89 | } 90 | androidTestCompile 'com.android.support.test:testing-support-lib:0.1' 91 | 92 | //Robolectric 93 | // androidTestCompile 'org.robolectric:robolectric:2.3' 94 | 95 | } -------------------------------------------------------------------------------- /app/libs/auto-common-1.0-20150122.001631-7.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/showang/dagger2Example/f111d721565732fdb4787160870994ec41f9df2d/app/libs/auto-common-1.0-20150122.001631-7.jar -------------------------------------------------------------------------------- /app/libs/dagger-compiler-2.0-20150122.022637-13.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/showang/dagger2Example/f111d721565732fdb4787160870994ec41f9df2d/app/libs/dagger-compiler-2.0-20150122.022637-13.jar -------------------------------------------------------------------------------- /app/libs/dagger-producers-2.0-20150122.022620-1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/showang/dagger2Example/f111d721565732fdb4787160870994ec41f9df2d/app/libs/dagger-producers-2.0-20150122.022620-1.jar -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/william/Develope/android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/newegg/tr/dagger2prac/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/androidTest/java/com/newegg/tr/dagger2prac/model/ActionModelTest.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.model; 2 | 3 | import com.newegg.tr.dagger2prac.model.action.Action; 4 | import com.newegg.tr.dagger2prac.model.action.ActionModel; 5 | import com.newegg.tr.dagger2prac.model.config.Config; 6 | import com.newegg.tr.dagger2prac.model.message.Messenger; 7 | 8 | import junit.framework.TestCase; 9 | 10 | import org.mockito.Mock; 11 | import org.mockito.MockitoAnnotations; 12 | 13 | import static org.mockito.Mockito.mock; 14 | import static org.mockito.Mockito.times; 15 | import static org.mockito.Mockito.verify; 16 | import static org.mockito.Mockito.when; 17 | 18 | /** 19 | * Created by william on 15/2/2. 20 | */ 21 | 22 | public class ActionModelTest extends TestCase { 23 | 24 | @Mock 25 | private Action action; 26 | @Mock 27 | private Messenger mMessenger; 28 | @Mock 29 | private Config mConfig; 30 | 31 | @Override 32 | protected void setUp() throws Exception { 33 | super.setUp(); 34 | MockitoAnnotations.initMocks(this); 35 | } 36 | 37 | public void testHello() { 38 | String stubPerson = "Who is not important in this case."; 39 | String stubMessage = "Test Hello in stub with %s"; 40 | String exceptResult = "Test Hello in stub with Who is not important in this case."; 41 | 42 | when(mMessenger.getHelloFormat()).thenReturn(stubMessage); 43 | 44 | when(mConfig.getUserName()).thenReturn(stubPerson); 45 | 46 | action = new ActionModel(mMessenger, mConfig); 47 | 48 | assertEquals(exceptResult, action.hello()); 49 | 50 | verify(mConfig, times(1)).getUserName(); 51 | 52 | } 53 | 54 | public void testCalcFib() { 55 | action = new ActionModel(mock(Messenger.class), mock(Config.class)); 56 | 57 | assertEquals(5, action.calcFibNumber(5)); 58 | 59 | assertEquals(8, action.calcFibNumber(6)); 60 | 61 | assertEquals(55, action.calcFibNumber(10)); 62 | 63 | assertEquals(-1, action.calcFibNumber(0)); 64 | 65 | assertEquals(-1, action.calcFibNumber(-2)); 66 | 67 | } 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/newegg/tr/dagger2prac/model/ConfigManagerTest.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.model; 2 | 3 | 4 | /** 5 | * Created by william on 15/2/3. 6 | */ 7 | //@RunWith(RobolectricTestRunner.class) 8 | public class ConfigManagerTest { 9 | 10 | // @org.junit.Test 11 | // public void testConfigUserName(){ 12 | // Activity activity = Robolectric.setupActivity(MainActivity.class); 13 | // assertTrue(activity.getTitle().toString().equals("Dagger2prac")); 14 | // } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/newegg/tr/dagger2prac/model/MessageModelTest.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.model; 2 | 3 | import com.newegg.tr.dagger2prac.model.message.MessageModel; 4 | import com.newegg.tr.dagger2prac.model.message.Messenger; 5 | 6 | import junit.framework.TestCase; 7 | 8 | /** 9 | * Created by william on 15/2/3. 10 | */ 11 | public class MessageModelTest extends TestCase { 12 | 13 | @Override 14 | protected void setUp() throws Exception { 15 | super.setUp(); 16 | } 17 | 18 | public void testHelloMessage(){ 19 | Messenger m = new MessageModel(); 20 | 21 | assertEquals("Hello %s!", m.getHelloFormat()); 22 | } 23 | 24 | public void testByeMessage(){ 25 | Messenger m = new MessageModel(); 26 | 27 | assertEquals("Bye %s!!", m.getByeFormat()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/newegg/tr/dagger2prac/ui/MainActivityTest.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.ui; 2 | 3 | import android.test.suitebuilder.annotation.LargeTest; 4 | 5 | import com.newegg.tr.dagger2prac.R; 6 | import com.newegg.tr.dagger2prac.view.component.MainComponent; 7 | import com.newegg.tr.dagger2prac.view.MainTestCase; 8 | 9 | import static android.support.test.espresso.Espresso.onView; 10 | import static android.support.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu; 11 | import static android.support.test.espresso.action.ViewActions.clearText; 12 | import static android.support.test.espresso.action.ViewActions.click; 13 | import static android.support.test.espresso.action.ViewActions.typeText; 14 | import static android.support.test.espresso.assertion.ViewAssertions.matches; 15 | import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; 16 | import static android.support.test.espresso.matcher.ViewMatchers.withId; 17 | import static android.support.test.espresso.matcher.ViewMatchers.withText; 18 | import static org.mockito.Mockito.anyInt; 19 | import static org.mockito.Mockito.when; 20 | 21 | /** 22 | * Created by william on 15/2/3. 23 | */ 24 | 25 | @LargeTest 26 | public class MainActivityTest extends MainTestCase { 27 | 28 | 29 | 30 | @Override 31 | protected void setUp() throws Exception { 32 | super.setUp(); 33 | getActivity(); 34 | MainComponent.Initializer.mInstance.inject(this); 35 | } 36 | 37 | public void testByeAction() { 38 | 39 | String mockResult = "Bye William!!(This is Mock Data)"; 40 | when(mMockAction.bye()).thenReturn(mockResult); 41 | 42 | onView(withId(R.id.mainPage_actionSpinner)).perform(click()); 43 | onView(withText("Bye")).perform(click()); 44 | 45 | onView(withId(R.id.mainPage_messageText)).check(matches(withText(mockResult))); 46 | } 47 | 48 | public void testFibAction() { 49 | onView(withId(R.id.mainPage_actionSpinner)).perform(click()); 50 | onView(withText("Fibonacci")).perform(click()); 51 | 52 | when(mMockAction.calcFibNumber(5)).thenReturn(77); 53 | when(mMockAction.calcFibNumber(10)).thenReturn(99); 54 | 55 | onView(withId(R.id.mainPage_inputEditText)).perform(typeText("5")); 56 | onView(withId(R.id.mainPage_submitButton)).perform(click()); 57 | 58 | onView(withId(R.id.mainPage_messageText)).check(matches(withText("77"))); 59 | 60 | onView(withId(R.id.mainPage_inputEditText)).perform(clearText(), typeText("10")); 61 | onView(withId(R.id.mainPage_submitButton)).perform(click()); 62 | 63 | onView(withId(R.id.mainPage_messageText)).check(matches(withText("99"))); 64 | } 65 | 66 | public void testStartSettingPage() { 67 | 68 | openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext()); 69 | 70 | onView(withText("Settings")).perform(click()); 71 | 72 | onView(withText("User Name:")).check(matches(isDisplayed())); 73 | 74 | } 75 | 76 | public void testFibError() { 77 | 78 | when(mMockAction.calcFibNumber(anyInt())).thenReturn(-1); 79 | 80 | onView(withId(R.id.mainPage_actionSpinner)).perform(click()); 81 | onView(withText("Fibonacci")).perform(click()); 82 | 83 | onView(withId(R.id.mainPage_inputEditText)).perform(typeText("0")); 84 | onView(withId(R.id.mainPage_submitButton)).perform(click()); 85 | 86 | onView(withId(R.id.mainPage_messageText)).check(matches(withText("Error!!!!"))); 87 | } 88 | 89 | public void testFibNoInputError(){ 90 | 91 | onView(withId(R.id.mainPage_actionSpinner)).perform(click()); 92 | onView(withText("Fibonacci")).perform(click()); 93 | 94 | onView(withId(R.id.mainPage_submitButton)).perform(click()); 95 | 96 | onView(withId(R.id.mainPage_messageText)).check(matches(withText("Error!!!!"))); 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/newegg/tr/dagger2prac/ui/SettingActivityTest.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.ui; 2 | 3 | import com.newegg.tr.dagger2prac.R; 4 | import com.newegg.tr.dagger2prac.view.component.SettingComponent; 5 | import com.newegg.tr.dagger2prac.view.SettingTestCase; 6 | import com.newegg.tr.dagger2prac.view.module.TestSettingModule; 7 | 8 | import static android.support.test.espresso.Espresso.onView; 9 | import static android.support.test.espresso.action.ViewActions.clearText; 10 | import static android.support.test.espresso.action.ViewActions.click; 11 | import static android.support.test.espresso.action.ViewActions.typeText; 12 | import static android.support.test.espresso.assertion.ViewAssertions.matches; 13 | import static android.support.test.espresso.matcher.ViewMatchers.withId; 14 | import static android.support.test.espresso.matcher.ViewMatchers.withText; 15 | import static org.mockito.Mockito.when; 16 | 17 | /** 18 | * Created by william on 15/2/13. 19 | */ 20 | public class SettingActivityTest extends SettingTestCase { 21 | 22 | 23 | String changedName = "William"; 24 | 25 | @Override 26 | protected void setUp() throws Exception { 27 | super.setUp(); 28 | getActivity(); 29 | SettingComponent.Initializer.mInstance.inject(this); 30 | } 31 | 32 | 33 | public void testChangeName() { 34 | 35 | onView(withId(R.id.settingPage_userNameTextView)).check(matches(withText(TestSettingModule.INIT_NAME))); 36 | 37 | onView(withId(R.id.settingPage_changeUserNameButton)).perform(click()); 38 | 39 | onView(withId(R.id.settingPage_dialogRenameEditText)).perform(clearText(), typeText(changedName)); 40 | 41 | onView(withText("OK")).perform(click()); 42 | 43 | when(mMockConfig.getUserName()).thenReturn(changedName); 44 | 45 | onView(withId(R.id.settingPage_userNameTextView)).check(matches(withText(changedName))); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /app/src/debug/java/com/newegg/tr/dagger2prac/view/MainTestCase.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.view; 2 | 3 | import android.test.ActivityInstrumentationTestCase2; 4 | 5 | import com.newegg.tr.dagger2prac.model.action.Action; 6 | import com.newegg.tr.dagger2prac.view.activity.MainActivity; 7 | import com.newegg.tr.dagger2prac.view.component.MainComponent; 8 | 9 | import javax.inject.Inject; 10 | 11 | /** 12 | * Created by william on 15/2/17. 13 | */ 14 | public class MainTestCase extends ActivityInstrumentationTestCase2 { 15 | 16 | @Inject 17 | protected Action mMockAction; 18 | 19 | public MainTestCase() { 20 | super(MainActivity.class); 21 | } 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /app/src/debug/java/com/newegg/tr/dagger2prac/view/SettingTestCase.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.view; 2 | 3 | import android.test.ActivityInstrumentationTestCase2; 4 | 5 | import com.newegg.tr.dagger2prac.model.config.Config; 6 | import com.newegg.tr.dagger2prac.view.activity.SettingActivity; 7 | 8 | import javax.inject.Inject; 9 | 10 | /** 11 | * Created by william on 15/2/16. 12 | */ 13 | public class SettingTestCase extends ActivityInstrumentationTestCase2 { 14 | 15 | @Inject 16 | protected Config mMockConfig; 17 | 18 | public SettingTestCase() { 19 | super(SettingActivity.class); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/debug/java/com/newegg/tr/dagger2prac/view/component/GlobalComponent.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.view.component; 2 | 3 | import com.newegg.tr.dagger2prac.Dagger2pracApp; 4 | import com.newegg.tr.dagger2prac.view.module.GlobleModule; 5 | import com.newegg.tr.dagger2prac.model.config.Config; 6 | 7 | import javax.inject.Singleton; 8 | 9 | import dagger.Component; 10 | 11 | /** 12 | * Created by william on 15/2/10. 13 | */ 14 | @Singleton 15 | @Component( 16 | modules = GlobleModule.class 17 | ) 18 | public interface GlobalComponent { 19 | 20 | public void inject(Dagger2pracApp app); 21 | 22 | public Config getConfig(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /app/src/debug/java/com/newegg/tr/dagger2prac/view/component/MainComponent.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.view.component; 2 | 3 | import android.app.Application; 4 | 5 | import com.newegg.tr.dagger2prac.view.MainPageView; 6 | import com.newegg.tr.dagger2prac.view.activity.MainActivity; 7 | import com.newegg.tr.dagger2prac.view.MainTestCase; 8 | import com.newegg.tr.dagger2prac.view.module.TestMainModule; 9 | 10 | import javax.inject.Singleton; 11 | 12 | import dagger.Component; 13 | 14 | 15 | /** 16 | * Created by william on 15/1/29. 17 | */ 18 | @Singleton 19 | @Component( 20 | modules = TestMainModule.class 21 | ) 22 | public interface MainComponent { 23 | 24 | void inject(MainActivity activity); 25 | 26 | void inject(MainTestCase testCase); 27 | 28 | public class Initializer { 29 | 30 | public static MainComponent mInstance; 31 | 32 | public static MainComponent init(Application app, MainPageView view) { 33 | 34 | MainComponent component = Dagger_MainComponent.builder() 35 | .testMainModule(new TestMainModule(view)) 36 | .build(); 37 | mInstance = component; 38 | return component; 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /app/src/debug/java/com/newegg/tr/dagger2prac/view/component/SettingComponent.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.view.component; 2 | 3 | 4 | import android.app.Application; 5 | 6 | import com.newegg.tr.dagger2prac.Dagger2pracApp; 7 | import com.newegg.tr.dagger2prac.model.config.Config; 8 | import com.newegg.tr.dagger2prac.view.SettingView; 9 | import com.newegg.tr.dagger2prac.view.activity.SettingActivity; 10 | import com.newegg.tr.dagger2prac.view.SettingTestCase; 11 | import com.newegg.tr.dagger2prac.view.module.TestSettingModule; 12 | 13 | import javax.inject.Singleton; 14 | 15 | import dagger.Component; 16 | 17 | /** 18 | * Created by william on 15/2/3. 19 | */ 20 | @Singleton 21 | @Component( 22 | modules = TestSettingModule.class 23 | ) 24 | public interface SettingComponent { 25 | 26 | void inject(SettingActivity activity); 27 | 28 | void inject(SettingTestCase testSetting); 29 | 30 | Config getConfig(); 31 | 32 | public class Initializer { 33 | public static SettingComponent mInstance; 34 | 35 | public static SettingComponent init(Application app, SettingView view) { 36 | 37 | SettingComponent component = Dagger_SettingComponent.builder() 38 | .testSettingModule(new TestSettingModule(view, ((Dagger2pracApp) app).MOCK_MODE)).build(); 39 | 40 | mInstance = component; 41 | return component; 42 | } 43 | 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /app/src/debug/java/com/newegg/tr/dagger2prac/view/module/GlobleModule.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.view.module; 2 | 3 | import com.newegg.tr.dagger2prac.model.config.Config; 4 | import com.newegg.tr.dagger2prac.model.config.ConfigManager; 5 | 6 | import javax.inject.Singleton; 7 | 8 | import dagger.Module; 9 | import dagger.Provides; 10 | 11 | /** 12 | * Created by william on 15/2/10. 13 | */ 14 | @Module 15 | public class GlobleModule { 16 | 17 | @Provides 18 | @Singleton 19 | public Config provideConfig(){ 20 | return new ConfigManager(); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /app/src/debug/java/com/newegg/tr/dagger2prac/view/module/TestMainModule.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.view.module; 2 | 3 | import com.newegg.tr.dagger2prac.model.action.Action; 4 | import com.newegg.tr.dagger2prac.presenter.MainPresenter; 5 | import com.newegg.tr.dagger2prac.presenter.internal.MainPresenterImpl; 6 | import com.newegg.tr.dagger2prac.view.MainPageView; 7 | 8 | import org.mockito.Mock; 9 | import org.mockito.MockitoAnnotations; 10 | 11 | import javax.inject.Singleton; 12 | 13 | import dagger.Module; 14 | import dagger.Provides; 15 | 16 | /** 17 | * Created by william on 15/2/17. 18 | */ 19 | @Module 20 | public class TestMainModule { 21 | MainPageView mView; 22 | 23 | @Mock 24 | Action mActionModel; 25 | 26 | public TestMainModule(MainPageView view) { 27 | mView = view; 28 | MockitoAnnotations.initMocks(this); 29 | } 30 | 31 | @Provides 32 | @Singleton 33 | public MainPresenter getPresenter(Action action) { 34 | 35 | return new MainPresenterImpl(mView, action); 36 | } 37 | 38 | @Provides 39 | @Singleton 40 | public Action getAction() { 41 | return mActionModel; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/debug/java/com/newegg/tr/dagger2prac/view/module/TestSettingModule.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.view.module; 2 | 3 | import com.newegg.tr.dagger2prac.model.config.Config; 4 | import com.newegg.tr.dagger2prac.model.config.ConfigManager; 5 | import com.newegg.tr.dagger2prac.presenter.SettingPresenter; 6 | import com.newegg.tr.dagger2prac.presenter.internal.SettingPresenterImpl; 7 | import com.newegg.tr.dagger2prac.view.SettingView; 8 | 9 | import org.mockito.Mock; 10 | import org.mockito.MockitoAnnotations; 11 | 12 | import javax.inject.Singleton; 13 | 14 | import dagger.Module; 15 | import dagger.Provides; 16 | 17 | import static org.mockito.Mockito.when; 18 | 19 | /** 20 | * Created by william on 15/2/13. 21 | */ 22 | @Module 23 | public class TestSettingModule { 24 | 25 | 26 | public final static String INIT_NAME = "大中天"; 27 | SettingView mView; 28 | @Mock 29 | Config mMockConfig; 30 | private boolean mIsMock; 31 | 32 | public TestSettingModule(SettingView view, boolean isMock) { 33 | mView = view; 34 | mIsMock = isMock; 35 | MockitoAnnotations.initMocks(this); 36 | when(mMockConfig.getUserName()).thenReturn(INIT_NAME); 37 | } 38 | 39 | @Singleton 40 | @Provides 41 | public SettingPresenter provideSettingPresenter(Config config) { 42 | return new SettingPresenterImpl(mView, config); 43 | } 44 | 45 | @Singleton 46 | @Provides 47 | public Config provideConfig() { 48 | return (mIsMock) ? mMockConfig : new ConfigManager(); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/newegg/tr/dagger2prac/Dagger2pracApp.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac; 2 | 3 | import android.app.Application; 4 | 5 | import com.newegg.tr.dagger2prac.view.component.*; 6 | 7 | 8 | /** 9 | * Created by william on 15/2/3. 10 | */ 11 | public class Dagger2pracApp extends Application { 12 | 13 | public static boolean MOCK_MODE = true; 14 | 15 | GlobalComponent mComponent; 16 | 17 | @Override 18 | public void onCreate() { 19 | super.onCreate(); 20 | mComponent = Dagger_GlobalComponent.create(); 21 | 22 | } 23 | 24 | public GlobalComponent component() { 25 | return mComponent; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/newegg/tr/dagger2prac/model/action/Action.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.model.action; 2 | 3 | /** 4 | * Created by william on 15/1/30. 5 | */ 6 | public interface Action { 7 | 8 | public String hello(); 9 | 10 | public String bye(); 11 | 12 | public String fibonacci(); 13 | 14 | public int calcFibNumber(int input); 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/newegg/tr/dagger2prac/model/action/ActionModel.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.model.action; 2 | 3 | import com.newegg.tr.dagger2prac.model.config.Config; 4 | import com.newegg.tr.dagger2prac.model.message.Messenger; 5 | 6 | import javax.inject.Inject; 7 | 8 | /** 9 | * Created by william on 15/1/30. 10 | */ 11 | public class ActionModel implements Action { 12 | 13 | private final Messenger mMessenger; 14 | 15 | private final Config mConfig; 16 | 17 | @Inject 18 | public ActionModel(Messenger messenger, Config config) { 19 | 20 | mMessenger = messenger; 21 | 22 | mConfig = config; 23 | } 24 | 25 | @Override 26 | public String hello() { 27 | 28 | return String.format(mMessenger.getHelloFormat(), mConfig.getUserName()); 29 | } 30 | 31 | @Override 32 | public String bye() { 33 | 34 | return String.format(mMessenger.getByeFormat(), mConfig.getUserName()); 35 | } 36 | 37 | @Override 38 | public String fibonacci() { 39 | 40 | return mMessenger.getFibInitMessage(); 41 | 42 | } 43 | 44 | @Override 45 | public int calcFibNumber(int input) { 46 | 47 | if(input <=0 ) 48 | return -1; 49 | 50 | return fibMethod(input); 51 | } 52 | 53 | private int fibMethod(int n){ 54 | if(n <= 0) 55 | throw new IllegalArgumentException("Input must be positive integer"); 56 | if(n == 1) 57 | return 1; 58 | if(n == 2) 59 | return 1; 60 | return fibMethod(n-2) + fibMethod(n-1); 61 | } 62 | 63 | 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/newegg/tr/dagger2prac/model/action/ActionType.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.model.action; 2 | 3 | /** 4 | * Created by william on 15/2/2. 5 | */ 6 | public enum ActionType { 7 | HELLO, BYE, FIBONACCI 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/newegg/tr/dagger2prac/model/config/Config.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.model.config; 2 | 3 | /** 4 | * Created by william on 15/2/3. 5 | */ 6 | public interface Config { 7 | 8 | public String getUserName(); 9 | 10 | public void setUserName(String userName); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/newegg/tr/dagger2prac/model/config/ConfigManager.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.model.config; 2 | 3 | /** 4 | * Created by william on 15/2/3. 5 | */ 6 | public class ConfigManager implements Config { 7 | 8 | private final static String DEFAULT_USER = "William"; 9 | 10 | private String mUserName = DEFAULT_USER; 11 | 12 | @Override 13 | public String getUserName() { 14 | return mUserName; 15 | } 16 | 17 | @Override 18 | public void setUserName(String userName) { 19 | mUserName = userName; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/newegg/tr/dagger2prac/model/message/MessageModel.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.model.message; 2 | 3 | /** 4 | * Created by william on 15/1/29. 5 | */ 6 | public class MessageModel implements Messenger { 7 | 8 | @Override 9 | public String getHelloFormat() { 10 | return "Hello %s!"; 11 | } 12 | 13 | @Override 14 | public String getByeFormat() { 15 | return "Bye %s!!"; 16 | } 17 | 18 | @Override 19 | public String getFibInitMessage() { 20 | return "Plz input a number."; 21 | } 22 | 23 | @Override 24 | public String getCalcText() { 25 | return "Calculating..."; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/newegg/tr/dagger2prac/model/message/Messenger.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.model.message; 2 | 3 | import dagger.Component; 4 | 5 | /** 6 | * Created by william on 15/1/29. 7 | */ 8 | public interface Messenger { 9 | 10 | public String getHelloFormat(); 11 | 12 | public String getByeFormat(); 13 | 14 | public String getFibInitMessage(); 15 | 16 | public String getCalcText(); 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/newegg/tr/dagger2prac/presenter/MainPresenter.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.presenter; 2 | 3 | import com.newegg.tr.dagger2prac.model.action.ActionType; 4 | 5 | /** 6 | * Created by william on 15/2/2. 7 | */ 8 | public interface MainPresenter { 9 | 10 | public void onActionSelected(ActionType type); 11 | 12 | public void calcFib(int fibNumber); 13 | 14 | public void updateUser(); 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/newegg/tr/dagger2prac/presenter/SettingPresenter.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.presenter; 2 | 3 | /** 4 | * Created by william on 15/2/3. 5 | */ 6 | public interface SettingPresenter { 7 | 8 | public String getUserName(); 9 | 10 | public void setUserName(String name); 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/newegg/tr/dagger2prac/presenter/internal/MainPresenterImpl.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.presenter.internal; 2 | 3 | import android.os.AsyncTask; 4 | import android.util.Log; 5 | 6 | import com.newegg.tr.dagger2prac.model.action.Action; 7 | import com.newegg.tr.dagger2prac.model.action.ActionType; 8 | import com.newegg.tr.dagger2prac.presenter.MainPresenter; 9 | import com.newegg.tr.dagger2prac.view.MainPageView; 10 | 11 | import javax.inject.Inject; 12 | 13 | /** 14 | * Created by william on 15/2/2. 15 | */ 16 | public class MainPresenterImpl implements MainPresenter { 17 | 18 | private final static ActionType DEFAULT_ACTION = ActionType.HELLO; 19 | 20 | MainPageView mView; 21 | Action mModel; 22 | 23 | ActionType currentAction = DEFAULT_ACTION; 24 | 25 | @Inject 26 | public MainPresenterImpl(MainPageView view, Action model) { 27 | mModel = model; 28 | mView = view; 29 | } 30 | 31 | @Override 32 | public void onActionSelected(ActionType type) { 33 | String result = "Error"; 34 | boolean isShowInputMethod = false; 35 | currentAction = type; 36 | switch (type){ 37 | case HELLO: 38 | result = mModel.hello(); 39 | isShowInputMethod = false; 40 | break; 41 | case BYE: 42 | result = mModel.bye(); 43 | isShowInputMethod = false; 44 | break; 45 | case FIBONACCI: 46 | result = mModel.fibonacci(); 47 | isShowInputMethod = true; 48 | break; 49 | } 50 | Log.e("MainPresenterImpl", "onActionSelected: " + result); 51 | mView.showInputMethodView(isShowInputMethod); 52 | mView.showActionResultText(result); 53 | } 54 | 55 | @Override 56 | public void calcFib(final int fibNumber) { 57 | Log.e("MainPresenterImpl", "calcFib: " + fibNumber); 58 | mView.showLoading(); 59 | 60 | new AsyncTask(){ 61 | 62 | @Override 63 | protected Integer doInBackground(Void... params) { 64 | return mModel.calcFibNumber(fibNumber); 65 | } 66 | 67 | @Override 68 | protected void onPostExecute(Integer result) { 69 | super.onPostExecute(result); 70 | 71 | if(result == -1) { 72 | mView.onActionError(); 73 | }else { 74 | mView.showActionResultText(result.toString()); 75 | } 76 | mView.hideLoading(); 77 | } 78 | }.execute(); 79 | } 80 | 81 | 82 | 83 | @Override 84 | public void updateUser() { 85 | onActionSelected(currentAction); 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /app/src/main/java/com/newegg/tr/dagger2prac/presenter/internal/SettingPresenterImpl.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.presenter.internal; 2 | 3 | import com.newegg.tr.dagger2prac.model.config.Config; 4 | import com.newegg.tr.dagger2prac.presenter.SettingPresenter; 5 | import com.newegg.tr.dagger2prac.view.SettingView; 6 | 7 | import javax.inject.Inject; 8 | 9 | /** 10 | * Created by william on 15/2/3. 11 | */ 12 | public class SettingPresenterImpl implements SettingPresenter { 13 | 14 | SettingView mView; 15 | Config mConfig; 16 | 17 | @Inject 18 | public SettingPresenterImpl(SettingView view, Config config){ 19 | mView = view; 20 | mConfig = config; 21 | } 22 | 23 | @Override 24 | public String getUserName() { 25 | return mConfig.getUserName(); 26 | } 27 | 28 | @Override 29 | public void setUserName(String name) { 30 | mConfig.setUserName(name); 31 | mView.updateUserName(name); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/newegg/tr/dagger2prac/view/MainPageView.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.view; 2 | 3 | /** 4 | * Created by william on 15/2/2. 5 | */ 6 | public interface MainPageView { 7 | 8 | public void showActionResultText(String resultText); 9 | 10 | public void showInputMethodView(boolean isShow); 11 | 12 | public void showLoading(); 13 | 14 | public void hideLoading(); 15 | 16 | public void onActionError(); 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/newegg/tr/dagger2prac/view/SettingView.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.view; 2 | 3 | /** 4 | * Created by william on 15/2/3. 5 | */ 6 | public interface SettingView { 7 | 8 | public void updateUserName(String userName); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/newegg/tr/dagger2prac/view/activity/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.view.activity; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.support.v7.app.ActionBarActivity; 6 | 7 | import butterknife.ButterKnife; 8 | 9 | /** 10 | * Created by william on 15/1/29. 11 | */ 12 | public abstract class BaseActivity extends ActionBarActivity { 13 | 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | onCreateComponent(); 18 | } 19 | 20 | protected abstract void onCreateComponent(); 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/newegg/tr/dagger2prac/view/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.view.activity; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.Menu; 7 | import android.view.MenuItem; 8 | import android.view.View; 9 | import android.widget.AdapterView; 10 | import android.widget.ArrayAdapter; 11 | import android.widget.Button; 12 | import android.widget.EditText; 13 | import android.widget.Spinner; 14 | import android.widget.TextView; 15 | 16 | import com.newegg.tr.dagger2prac.R; 17 | import com.newegg.tr.dagger2prac.model.action.ActionType; 18 | import com.newegg.tr.dagger2prac.presenter.MainPresenter; 19 | import com.newegg.tr.dagger2prac.view.MainPageView; 20 | import com.newegg.tr.dagger2prac.view.component.MainComponent; 21 | 22 | import javax.inject.Inject; 23 | 24 | import butterknife.ButterKnife; 25 | import butterknife.InjectView; 26 | 27 | 28 | public class MainActivity extends BaseActivity implements MainPageView, AdapterView.OnItemSelectedListener { 29 | 30 | public static MainComponent component; 31 | 32 | @Inject 33 | MainPresenter mPresenter; 34 | 35 | @InjectView(R.id.mainPage_messageText) 36 | TextView messageTextView; 37 | @InjectView(R.id.mainPage_actionSpinner) 38 | Spinner actionSpinner; 39 | @InjectView(R.id.mainPage_inputEditText) 40 | EditText inputText; 41 | @InjectView(R.id.mainPage_submitButton) 42 | Button submitButton; 43 | @InjectView(R.id.mainPage_progress) 44 | View progress; 45 | 46 | @Override 47 | protected void onCreateComponent() { 48 | 49 | MainComponent.Initializer.init(getApplication(), this).inject(this); 50 | } 51 | 52 | @Override 53 | protected void onCreate(Bundle savedInstanceState) { 54 | super.onCreate(savedInstanceState); 55 | setContentView(R.layout.activity_main); 56 | ButterKnife.inject(this); 57 | 58 | initSpinner(); 59 | initSubmitButton(); 60 | } 61 | 62 | @Override 63 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 64 | super.onActivityResult(requestCode, resultCode, data); 65 | if (resultCode == Activity.RESULT_OK) { 66 | mPresenter.updateUser(); 67 | } 68 | } 69 | 70 | private void initSubmitButton() { 71 | submitButton.setOnClickListener(new View.OnClickListener() { 72 | @Override 73 | public void onClick(View v) { 74 | 75 | if(inputText.getText().toString().isEmpty()) { 76 | MainActivity.this.onActionError(); 77 | return; 78 | } 79 | 80 | mPresenter.calcFib(Integer.valueOf(inputText.getText().toString())); 81 | } 82 | }); 83 | } 84 | 85 | private void initSpinner() { 86 | String[] actionTexts = {"Hello", "Bye", "Fibonacci"}; 87 | ArrayAdapter actionTextArray = new ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, actionTexts); 88 | actionSpinner.setAdapter(actionTextArray); 89 | actionSpinner.setOnItemSelectedListener(this); 90 | } 91 | 92 | @Override 93 | public boolean onCreateOptionsMenu(Menu menu) { 94 | getMenuInflater().inflate(R.menu.menu_main, menu); 95 | return true; 96 | } 97 | 98 | @Override 99 | public boolean onOptionsItemSelected(MenuItem item) { 100 | int id = item.getItemId(); 101 | 102 | if (id == R.id.action_settings) { 103 | Intent intent = new Intent(this, SettingActivity.class); 104 | startActivityForResult(intent, 17); 105 | return true; 106 | } 107 | 108 | return super.onOptionsItemSelected(item); 109 | } 110 | 111 | @Override 112 | public void showActionResultText(String resultText) { 113 | messageTextView.setText(resultText); 114 | } 115 | 116 | @Override 117 | public void showInputMethodView(boolean isShow) { 118 | int status = (isShow) ? View.VISIBLE : View.GONE; 119 | 120 | inputText.setVisibility(status); 121 | submitButton.setVisibility(status); 122 | } 123 | 124 | @Override 125 | public void showLoading() { 126 | progress.setVisibility(View.VISIBLE); 127 | } 128 | 129 | @Override 130 | public void hideLoading() { 131 | progress.setVisibility(View.GONE); 132 | } 133 | 134 | @Override 135 | public void onActionError() { 136 | messageTextView.setText(getString(R.string.main_error)); 137 | } 138 | 139 | @Override 140 | public void onItemSelected(AdapterView parent, View view, int position, long id) { 141 | switch (position) { 142 | case 0: 143 | mPresenter.onActionSelected(ActionType.HELLO); 144 | break; 145 | case 1: 146 | mPresenter.onActionSelected(ActionType.BYE); 147 | break; 148 | case 2: 149 | mPresenter.onActionSelected(ActionType.FIBONACCI); 150 | break; 151 | 152 | } 153 | } 154 | 155 | @Override 156 | public void onNothingSelected(AdapterView parent) { 157 | 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /app/src/main/java/com/newegg/tr/dagger2prac/view/activity/SettingActivity.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.view.activity; 2 | 3 | import android.app.Activity; 4 | import android.app.AlertDialog; 5 | import android.content.DialogInterface; 6 | import android.os.Bundle; 7 | import android.view.View; 8 | import android.widget.EditText; 9 | import android.widget.TextView; 10 | 11 | import com.newegg.tr.dagger2prac.R; 12 | import com.newegg.tr.dagger2prac.presenter.SettingPresenter; 13 | import com.newegg.tr.dagger2prac.view.SettingView; 14 | import com.newegg.tr.dagger2prac.view.component.SettingComponent; 15 | 16 | import javax.inject.Inject; 17 | 18 | import butterknife.ButterKnife; 19 | import butterknife.InjectView; 20 | 21 | public class SettingActivity extends BaseActivity implements SettingView, View.OnClickListener { 22 | 23 | @Inject 24 | SettingPresenter mPresenter; 25 | 26 | @InjectView(R.id.settingPage_userNameTextView) 27 | TextView mUserNameTextView; 28 | 29 | @InjectView(R.id.settingPage_changeUserNameButton) 30 | TextView mChangeNameButton; 31 | 32 | @Override 33 | protected void onCreateComponent() { 34 | SettingComponent.Initializer.init(getApplication(), this).inject(this); 35 | } 36 | 37 | @Override 38 | protected void onCreate(Bundle savedInstanceState) { 39 | super.onCreate(savedInstanceState); 40 | setContentView(R.layout.activity_setting); 41 | ButterKnife.inject(this); 42 | 43 | mChangeNameButton.setOnClickListener(this); 44 | mUserNameTextView.setOnClickListener(this); 45 | updateUserName(mPresenter.getUserName()); 46 | } 47 | 48 | @Override 49 | public void onClick(View v) { 50 | 51 | final View dialogView = getLayoutInflater().inflate(R.layout.activity_setting_dialog, null); 52 | 53 | final AlertDialog renameDialog = new AlertDialog.Builder(this).setTitle("Change User Name").setView(dialogView).setPositiveButton("OK", new DialogInterface.OnClickListener() { 54 | @Override 55 | public void onClick(DialogInterface dialog, int which) { 56 | EditText renameEditText = (EditText) dialogView.findViewById(R.id.settingPage_dialogRenameEditText); 57 | mPresenter.setUserName(renameEditText.getText().toString()); 58 | dialog.dismiss(); 59 | setResult(Activity.RESULT_OK); 60 | } 61 | }).setNegativeButton("Cancel", new DialogInterface.OnClickListener() { 62 | @Override 63 | public void onClick(DialogInterface dialog, int which) { 64 | dialog.dismiss(); 65 | } 66 | }).create(); 67 | 68 | renameDialog.show(); 69 | 70 | } 71 | 72 | @Override 73 | public void updateUserName(String userName) { 74 | mUserNameTextView.setText(userName); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/java/com/newegg/tr/dagger2prac/view/scope/Main.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.view.scope; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | import javax.inject.Scope; 7 | 8 | /** 9 | * Created by william on 15/2/10. 10 | */ 11 | @Scope 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface Main { 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/newegg/tr/dagger2prac/view/scope/Setting.java: -------------------------------------------------------------------------------- 1 | package com.newegg.tr.dagger2prac.view.scope; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | import javax.inject.Scope; 7 | 8 | /** 9 | * Created by william on 15/2/4. 10 | */ 11 | @Scope 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface Setting { 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/showang/dagger2Example/f111d721565732fdb4787160870994ec41f9df2d/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/showang/dagger2Example/f111d721565732fdb4787160870994ec41f9df2d/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/showang/dagger2Example/f111d721565732fdb4787160870994ec41f9df2d/app/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/showang/dagger2Example/f111d721565732fdb4787160870994ec41f9df2d/app/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 16 | 17 | 21 | 22 | 26 | 27 | 35 | 36 |