diff --git a/app/src/androidTest/java/com/example/android/dagger/ApplicationTest.kt b/app/src/androidTest/java/com/example/android/dagger/ApplicationTest.kt index 6d58f80b..d3b59d16 100644 --- a/app/src/androidTest/java/com/example/android/dagger/ApplicationTest.kt +++ b/app/src/androidTest/java/com/example/android/dagger/ApplicationTest.kt @@ -21,14 +21,14 @@ import androidx.test.espresso.Espresso.onView import androidx.test.espresso.action.ViewActions.* import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.matcher.ViewMatchers.* -import com.example.android.dagger.main.MainActivity +import com.example.android.dagger.splash.SplashActivity import org.junit.Test class ApplicationTest { @Test fun runApp() { - ActivityScenario.launch(MainActivity::class.java) + ActivityScenario.launch(SplashActivity::class.java) // Should be in Registration/EnterDetails because the user is not registered onView(withText("Register to Dagger World!")).check(matches(isDisplayed())) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 09ae1a34..a966eb7a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -27,14 +27,18 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> - + + + @@ -46,4 +50,4 @@ android:screenOrientation="portrait" /> - + \ No newline at end of file diff --git a/app/src/main/java/com/example/android/dagger/di/AppComponent.kt b/app/src/main/java/com/example/android/dagger/di/AppComponent.kt index c65c7bac..f1f6c0da 100644 --- a/app/src/main/java/com/example/android/dagger/di/AppComponent.kt +++ b/app/src/main/java/com/example/android/dagger/di/AppComponent.kt @@ -19,6 +19,7 @@ package com.example.android.dagger.di import android.content.Context import com.example.android.dagger.login.LoginComponent import com.example.android.dagger.registration.RegistrationComponent +import com.example.android.dagger.splash.SplashComponent import com.example.android.dagger.user.UserManager import dagger.BindsInstance import dagger.Component @@ -42,4 +43,5 @@ interface AppComponent { fun registrationComponent(): RegistrationComponent.Factory fun loginComponent(): LoginComponent.Factory fun userManager(): UserManager + fun splashComponent(): SplashComponent.Factory } diff --git a/app/src/main/java/com/example/android/dagger/di/AppSubcomponents.kt b/app/src/main/java/com/example/android/dagger/di/AppSubcomponents.kt index fa2335da..d3ed0f27 100644 --- a/app/src/main/java/com/example/android/dagger/di/AppSubcomponents.kt +++ b/app/src/main/java/com/example/android/dagger/di/AppSubcomponents.kt @@ -18,6 +18,7 @@ package com.example.android.dagger.di import com.example.android.dagger.login.LoginComponent import com.example.android.dagger.registration.RegistrationComponent +import com.example.android.dagger.splash.SplashComponent import com.example.android.dagger.user.UserComponent import dagger.Module @@ -26,7 +27,8 @@ import dagger.Module subcomponents = [ RegistrationComponent::class, LoginComponent::class, - UserComponent::class + UserComponent::class, + SplashComponent::class ] ) class AppSubcomponents diff --git a/app/src/main/java/com/example/android/dagger/main/MainActivity.kt b/app/src/main/java/com/example/android/dagger/main/MainActivity.kt index 93be56c8..69e86db5 100644 --- a/app/src/main/java/com/example/android/dagger/main/MainActivity.kt +++ b/app/src/main/java/com/example/android/dagger/main/MainActivity.kt @@ -34,32 +34,17 @@ class MainActivity : AppCompatActivity() { @Inject lateinit var mainViewModel: MainViewModel - /** - * If the User is not registered, RegistrationActivity will be launched, - * If the User is not logged in, LoginActivity will be launched, - * else carry on with MainActivity. - */ override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - // Grabs instance of UserManager from the application graph val userManager = (application as MyApplication).appComponent.userManager() - if (!userManager.isUserLoggedIn()) { - if (!userManager.isUserRegistered()) { - startActivity(Intent(this, RegistrationActivity::class.java)) - finish() - } else { - startActivity(Intent(this, LoginActivity::class.java)) - finish() - } - } else { - setContentView(R.layout.activity_main) + // If the MainActivity needs to be displayed, we get the UserComponent from the + // application graph and gets this Activity injected + userManager.userComponent!!.inject(this) - // If the MainActivity needs to be displayed, we get the UserComponent from the - // application graph and gets this Activity injected - userManager.userComponent!!.inject(this) - setupViews() - } + super.onCreate(savedInstanceState) + + setContentView(R.layout.activity_main) + setupViews() } /** diff --git a/app/src/main/java/com/example/android/dagger/splash/SplashActivity.kt b/app/src/main/java/com/example/android/dagger/splash/SplashActivity.kt new file mode 100644 index 00000000..47b64e44 --- /dev/null +++ b/app/src/main/java/com/example/android/dagger/splash/SplashActivity.kt @@ -0,0 +1,29 @@ +package com.example.android.dagger.splash + +import android.content.Intent +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import com.example.android.dagger.MyApplication +import javax.inject.Inject + +class SplashActivity : AppCompatActivity() { + + // @Inject annotated fields will be provided by Dagger + @Inject + lateinit var splashViewModel: SplashViewModel + + override fun onCreate(savedInstanceState: Bundle?) { + + // Creates an instance of Splash component by grabbing the factory from the app graph + // and injects this activity to that Component + (application as MyApplication).appComponent.splashComponent().create().inject(this) + super.onCreate(savedInstanceState) + showActivity() + } + + private fun showActivity() { + val activity = splashViewModel.getActivityClass() + startActivity(Intent(this, activity)) + finish() + } +} diff --git a/app/src/main/java/com/example/android/dagger/splash/SplashComponent.kt b/app/src/main/java/com/example/android/dagger/splash/SplashComponent.kt new file mode 100644 index 00000000..797d7e92 --- /dev/null +++ b/app/src/main/java/com/example/android/dagger/splash/SplashComponent.kt @@ -0,0 +1,19 @@ +package com.example.android.dagger.splash + +import com.example.android.dagger.di.ActivityScope +import dagger.Subcomponent + +// Scope annotation that the SplashComponent uses +// Classes annotated with @ActivityScope will have a unique instance in this Component +@ActivityScope +// Definition of a Dagger subcomponent +@Subcomponent +interface SplashComponent { + @Subcomponent.Factory + interface Factory { + fun create(): SplashComponent + } + + // Classes that can be injected by this Component + fun inject(activity: SplashActivity) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/android/dagger/splash/SplashViewModel.kt b/app/src/main/java/com/example/android/dagger/splash/SplashViewModel.kt new file mode 100644 index 00000000..9a957693 --- /dev/null +++ b/app/src/main/java/com/example/android/dagger/splash/SplashViewModel.kt @@ -0,0 +1,36 @@ +package com.example.android.dagger.splash + +import androidx.appcompat.app.AppCompatActivity +import com.example.android.dagger.di.ActivityScope +import com.example.android.dagger.login.LoginActivity +import com.example.android.dagger.main.MainActivity +import com.example.android.dagger.registration.RegistrationActivity +import com.example.android.dagger.user.UserManager +import javax.inject.Inject + +/** + * SplashViewModel is the ViewModel that [SplashActivity] uses to + * obtain information of what Activity to show on the screen. + * + * @Inject tells Dagger how to provide instances of this type. Dagger also knows + * that UserManager is a dependency. + */ +@ActivityScope +class SplashViewModel @Inject constructor(private val userManager: UserManager) { + + /** + * If the User is not registered, RegistrationActivity will be returned, + * If the User is not logged in, LoginActivity will be returned, + * else MainActivity. + */ + fun getActivityClass(): Class = + if (!userManager.isUserLoggedIn()) { + if (!userManager.isUserRegistered()) { + RegistrationActivity::class.java + } else { + LoginActivity::class.java + } + } else { + MainActivity::class.java + } +} \ No newline at end of file diff --git a/app/src/test/java/com/example/android/dagger/splash/SplashViewModelTest.kt b/app/src/test/java/com/example/android/dagger/splash/SplashViewModelTest.kt new file mode 100644 index 00000000..543843f9 --- /dev/null +++ b/app/src/test/java/com/example/android/dagger/splash/SplashViewModelTest.kt @@ -0,0 +1,45 @@ +package com.example.android.dagger.splash + +import com.example.android.dagger.login.LoginActivity +import com.example.android.dagger.main.MainActivity +import com.example.android.dagger.registration.RegistrationActivity +import com.example.android.dagger.user.UserManager +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test +import org.mockito.Mockito.mock +import org.mockito.Mockito.`when` as whenever + +class SplashViewModelTest { + + private lateinit var userManager: UserManager + private lateinit var viewModel: SplashViewModel + + @Before + fun setup() { + userManager = mock(UserManager::class.java) + viewModel = SplashViewModel(userManager) + } + + @Test + fun `If the user is not registered then getActivityClass returns RegistrationActivity`() { + whenever(userManager.isUserRegistered()).thenReturn(false) + + assertEquals(RegistrationActivity::class.java, viewModel.getActivityClass()) + } + + @Test + fun `If the user is registered but not logged in then getActivityClass returns LoginActivity`() { + whenever(userManager.isUserRegistered()).thenReturn(true) + whenever(userManager.isUserLoggedIn()).thenReturn(false) + + assertEquals(LoginActivity::class.java, viewModel.getActivityClass()) + } + + @Test + fun `If the user is logged in then getActivityClass returns MainActivity`() { + whenever(userManager.isUserLoggedIn()).thenReturn(true) + + assertEquals(MainActivity::class.java, viewModel.getActivityClass()) + } +} \ No newline at end of file