diff --git a/.gitignore b/.gitignore
index 39fb081..2c41655 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,9 +1,8 @@
*.iml
.gradle
/local.properties
-/.idea/workspace.xml
-/.idea/libraries
.DS_Store
/build
/captures
.externalNativeBuild
+.idea
\ No newline at end of file
diff --git a/.idea/__vcs.xml b/.idea/__vcs.xml
deleted file mode 100644
index 94a25f7..0000000
--- a/.idea/__vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
deleted file mode 100644
index 7ac24c7..0000000
--- a/.idea/gradle.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index fee3a84..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index bd4fb0f..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
deleted file mode 100644
index 7f68460..0000000
--- a/.idea/runConfigurations.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 94a25f7..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index ceb69ee..cd237e6 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,20 +1,14 @@
-project.ext {
- appcompat = "25.3.1"
- arch = "1.0.0-alpha1"
- retrofit = "2.0.2"
- constraintLayout = "1.0.2"
- dagger_version = "2.11"
-}
-
apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-kapt'
android {
- compileSdkVersion 25
- buildToolsVersion "25.0.3"
+ compileSdkVersion 27
+ buildToolsVersion "27.0.1"
defaultConfig {
applicationId "com.example.test.mvvm_sample_app"
minSdkVersion 19
- targetSdkVersion 25
+ targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
@@ -25,7 +19,6 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
-
dataBinding {
enabled = true
}
@@ -35,30 +28,55 @@ android {
}
}
+project.ext {
+ appcompat = "27.0.2"
+ arch = "1.0.0"
+ retrofit = "2.3.0"
+ constraintLayout = "1.0.2"
+ dagger_version = "2.13"
+}
+
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
- androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
- exclude group: 'com.android.support', module: 'support-annotations'
- })
+ // kotlin
+ compile "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ kapt "com.android.databinding:compiler:3.1.0-alpha08"
+ // google support libraries
compile "com.android.support:appcompat-v7:$project.appcompat"
compile "com.android.support:cardview-v7:$project.appcompat"
compile "com.android.support:recyclerview-v7:$project.appcompat"
+ compile "com.android.support.constraint:constraint-layout:$project.constraintLayout"
+ compile "com.android.support:support-v4:$project.appcompat"
+ compile "com.android.support:design:$project.appcompat"
+
+ // architecture components
compile "android.arch.lifecycle:runtime:$project.arch"
compile "android.arch.lifecycle:extensions:$project.arch"
+ kapt "android.arch.lifecycle:compiler:$project.arch"
+
+ // network libraries
compile "com.squareup.retrofit2:retrofit:$project.retrofit"
compile "com.squareup.retrofit2:converter-gson:$project.retrofit"
- annotationProcessor "android.arch.lifecycle:compiler:$project.arch"
- compile "com.android.support.constraint:constraint-layout:$project.constraintLayout"
- compile "com.android.support:support-v4:$project.appcompat"
+ // dagger2 dependency injection
compile "com.google.dagger:dagger:$project.dagger_version"
compile "com.google.dagger:dagger-android:$project.dagger_version"
compile "com.google.dagger:dagger-android-support:$project.dagger_version"
+ kapt "com.google.dagger:dagger-android-processor:$dagger_version"
+ kapt "com.google.dagger:dagger-compiler:$dagger_version"
- annotationProcessor "com.google.dagger:dagger-android-processor:$dagger_version"
- annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
-
+ // test libraries
testCompile 'junit:junit:4.12'
- compile 'com.android.support:design:25.3.1'
-}
+ androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
+ exclude group: 'com.android.support', module: 'support-annotations'
+ })
+ androidTestCompile('com.android.support.test.espresso:espresso-contrib:2.2') {
+ // Necessary to avoid version conflicts
+ exclude group: 'com.android.support', module: 'appcompat'
+ exclude group: 'com.android.support', module: 'support-v4'
+ exclude group: 'com.android.support', module: 'support-annotations'
+ exclude module: 'recyclerview-v7'
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/androidTest/java/com/example/test/mvvmsampleapp/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/example/test/mvvmsampleapp/ExampleInstrumentedTest.java
deleted file mode 100644
index 27bdca3..0000000
--- a/app/src/androidTest/java/com/example/test/mvvmsampleapp/ExampleInstrumentedTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.example.test.mvvmsampleapp;
-
-import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static org.junit.Assert.*;
-
-/**
- * Instrumentation test, which will execute on an Android device.
- *
- * @see Testing documentation
- */
-@RunWith(AndroidJUnit4.class)
-public class ExampleInstrumentedTest {
- @Test
- public void useAppContext() throws Exception {
- // Context of the app under test.
- Context appContext = InstrumentationRegistry.getTargetContext();
-
- assertEquals("com.example.test.mvvm_sample_app", appContext.getPackageName());
- }
-}
diff --git a/app/src/androidTest/java/com/example/test/mvvmsampleapp/UiTests.kt b/app/src/androidTest/java/com/example/test/mvvmsampleapp/UiTests.kt
new file mode 100644
index 0000000..78f6e40
--- /dev/null
+++ b/app/src/androidTest/java/com/example/test/mvvmsampleapp/UiTests.kt
@@ -0,0 +1,52 @@
+package com.example.test.mvvmsampleapp
+
+import android.support.test.espresso.Espresso.onView
+import android.support.test.espresso.action.ViewActions.click
+import android.support.test.espresso.assertion.ViewAssertions.matches
+import android.support.test.espresso.contrib.RecyclerViewActions
+import android.support.test.espresso.matcher.ViewMatchers.isDisplayed
+import android.support.test.espresso.matcher.ViewMatchers.withId
+import android.support.test.rule.ActivityTestRule
+import android.support.test.runner.AndroidJUnit4
+import com.example.test.mvvmsampleapp.view.ui.MainActivity
+import com.example.test.mvvmsampleapp.view.viewholders.ProjectViewHolder
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+
+
+
+
+/**
+ * Instrumentation test, which will execute on an Android device.
+ *
+ * @see [Testing documentation](http://d.android.com/tools/testing)
+ */
+@RunWith(AndroidJUnit4::class)
+class UiTests {
+
+ @Rule
+ @JvmField
+ var mainActivityTestRule = ActivityTestRule(MainActivity::class.java)
+
+ /**
+ * Lazy example test, phone should be connected to the internet.
+ * Ideally you need to implement a mock web server.
+ */
+ @Before
+ fun waitForLoading() {
+ onView(withId(R.id.loading_projects)).check(matches(isDisplayed()))
+ Thread.sleep(1000)
+ }
+
+ @Test
+ fun clickFirstElement() {
+ onView(withId(R.id.project_list))
+ .perform(RecyclerViewActions.actionOnItemAtPosition(0, click()))
+
+ onView(withId(R.id.imageView)).check(matches(isDisplayed()))
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 6d7a09c..fc31468 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -5,7 +5,7 @@
+
+ override fun onCreate() {
+ super.onCreate()
+ AppInjector.init(this)
+ }
+
+ override fun activityInjector(): DispatchingAndroidInjector? {
+ return dispatchingAndroidInjector
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/MVVMApplication.java b/app/src/main/java/com/example/test/mvvmsampleapp/MVVMApplication.java
deleted file mode 100644
index a8911f4..0000000
--- a/app/src/main/java/com/example/test/mvvmsampleapp/MVVMApplication.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.example.test.mvvmsampleapp;
-
-import android.app.Activity;
-import android.app.Application;
-
-import com.example.test.mvvmsampleapp.di.AppInjector;
-
-import javax.inject.Inject;
-
-import dagger.android.DispatchingAndroidInjector;
-import dagger.android.HasActivityInjector;
-
-public class MVVMApplication extends Application implements HasActivityInjector {
-
- @Inject
- DispatchingAndroidInjector dispatchingAndroidInjector;
-
- @Override
- public void onCreate() {
- super.onCreate();
- AppInjector.init(this);
- }
-
- @Override
- public DispatchingAndroidInjector activityInjector() {
- return dispatchingAndroidInjector;
- }
-}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/di/AppComponent.java b/app/src/main/java/com/example/test/mvvmsampleapp/di/AppComponent.java
deleted file mode 100644
index b3c73ab..0000000
--- a/app/src/main/java/com/example/test/mvvmsampleapp/di/AppComponent.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.example.test.mvvmsampleapp.di;
-
-import com.example.test.mvvmsampleapp.MVVMApplication;
-import android.app.Application;
-import javax.inject.Singleton;
-
-import dagger.BindsInstance;
-import dagger.Component;
-import dagger.android.AndroidInjectionModule;
-
-@Singleton
-@Component(modules = {
- AndroidInjectionModule.class,
- AppModule.class,
- MainActivityModule.class
-})
-public interface AppComponent {
- @Component.Builder
- interface Builder {
- @BindsInstance Builder application(Application application);
- AppComponent build();
- }
- void inject(MVVMApplication mvvmApplication);
-}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/di/AppComponent.kt b/app/src/main/java/com/example/test/mvvmsampleapp/di/AppComponent.kt
new file mode 100644
index 0000000..eea4d7a
--- /dev/null
+++ b/app/src/main/java/com/example/test/mvvmsampleapp/di/AppComponent.kt
@@ -0,0 +1,22 @@
+package com.example.test.mvvmsampleapp.di
+
+import android.app.Application
+import com.example.test.mvvmsampleapp.App
+import dagger.BindsInstance
+import dagger.Component
+import dagger.android.AndroidInjectionModule
+import javax.inject.Singleton
+
+@Singleton
+@Component(modules = [(AndroidInjectionModule::class), (AppModule::class), (MainActivityModule::class)])
+interface AppComponent {
+ @Component.Builder
+ interface Builder {
+ @BindsInstance
+ fun application(application: Application): Builder
+
+ fun build(): AppComponent
+ }
+
+ fun inject(app: App)
+}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/di/AppInjector.java b/app/src/main/java/com/example/test/mvvmsampleapp/di/AppInjector.java
deleted file mode 100644
index a8a3be7..0000000
--- a/app/src/main/java/com/example/test/mvvmsampleapp/di/AppInjector.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.example.test.mvvmsampleapp.di;
-
-import android.app.Activity;
-import android.app.Application;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentActivity;
-import android.support.v4.app.FragmentManager;
-
-import com.example.test.mvvmsampleapp.MVVMApplication;
-
-import dagger.android.AndroidInjection;
-import dagger.android.support.AndroidSupportInjection;
-import dagger.android.support.HasSupportFragmentInjector;
-
-/**
- * AppInjector is a helper class to automatically inject fragments if they implement {@link Injectable}.
- */
-public class AppInjector {
- private AppInjector() {}
-
- public static void init(MVVMApplication mvvmApplication) {
- DaggerAppComponent.builder().application(mvvmApplication)
- .build().inject(mvvmApplication);
-
- mvvmApplication
- .registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
- @Override
- public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
- handleActivity(activity);
- }
-
- @Override
- public void onActivityStarted(Activity activity) {
-
- }
-
- @Override
- public void onActivityResumed(Activity activity) {
-
- }
-
- @Override
- public void onActivityPaused(Activity activity) {
-
- }
-
- @Override
- public void onActivityStopped(Activity activity) {
-
- }
-
- @Override
- public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
-
- }
-
- @Override
- public void onActivityDestroyed(Activity activity) {
-
- }
- });
- }
-
- private static void handleActivity(Activity activity) {
- if (activity instanceof HasSupportFragmentInjector) {
- AndroidInjection.inject(activity);
- }
- if (activity instanceof FragmentActivity) {
- ((FragmentActivity) activity).getSupportFragmentManager()
- .registerFragmentLifecycleCallbacks(
- new FragmentManager.FragmentLifecycleCallbacks() {
- @Override
- public void onFragmentCreated(FragmentManager fm, Fragment fragment,
- Bundle savedInstanceState) {
- if (fragment instanceof Injectable) {
- AndroidSupportInjection.inject(fragment);
- }
- }
- }, true);
- }
- }
-}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/di/AppInjector.kt b/app/src/main/java/com/example/test/mvvmsampleapp/di/AppInjector.kt
new file mode 100644
index 0000000..f292a15
--- /dev/null
+++ b/app/src/main/java/com/example/test/mvvmsampleapp/di/AppInjector.kt
@@ -0,0 +1,73 @@
+package com.example.test.mvvmsampleapp.di
+
+import android.app.Activity
+import android.app.Application
+import android.os.Bundle
+import android.support.v4.app.Fragment
+import android.support.v4.app.FragmentActivity
+import android.support.v4.app.FragmentManager
+
+import com.example.test.mvvmsampleapp.App
+
+import dagger.android.AndroidInjection
+import dagger.android.support.AndroidSupportInjection
+import dagger.android.support.HasSupportFragmentInjector
+
+/**
+ * AppInjector is a helper class to automatically inject fragments if they implement [Injectable].
+ */
+object AppInjector {
+
+ fun init(app: App) {
+ DaggerAppComponent
+ .builder()
+ .application(app)
+ .build()
+ .inject(app)
+
+ app.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
+ override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
+ handleActivity(activity)
+ }
+
+ override fun onActivityStarted(activity: Activity) {
+
+ }
+
+ override fun onActivityResumed(activity: Activity) {
+
+ }
+
+ override fun onActivityPaused(activity: Activity) {
+
+ }
+
+ override fun onActivityStopped(activity: Activity) {
+
+ }
+
+ override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle?) {
+
+ }
+
+ override fun onActivityDestroyed(activity: Activity) {
+
+ }
+ })
+ }
+
+ private fun handleActivity(activity: Activity) {
+ if (activity is HasSupportFragmentInjector) {
+ AndroidInjection.inject(activity)
+ }
+ (activity as? FragmentActivity)?.supportFragmentManager?.registerFragmentLifecycleCallbacks(
+ object : FragmentManager.FragmentLifecycleCallbacks() {
+ override fun onFragmentCreated(fm: FragmentManager?, fragment: Fragment?,
+ savedInstanceState: Bundle?) {
+ if (fragment is Injectable) {
+ AndroidSupportInjection.inject(fragment)
+ }
+ }
+ }, true)
+ }
+}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/di/AppModule.java b/app/src/main/java/com/example/test/mvvmsampleapp/di/AppModule.java
deleted file mode 100644
index 3070bfc..0000000
--- a/app/src/main/java/com/example/test/mvvmsampleapp/di/AppModule.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.example.test.mvvmsampleapp.di;
-
-import android.arch.lifecycle.ViewModelProvider;
-
-import com.example.test.mvvmsampleapp.service.repository.GitHubService;
-import com.example.test.mvvmsampleapp.viewmodel.ProjectViewModelFactory;
-
-import javax.inject.Singleton;
-
-import dagger.Module;
-import dagger.Provides;
-import retrofit2.Retrofit;
-import retrofit2.converter.gson.GsonConverterFactory;
-
-@Module(subcomponents = ViewModelSubComponent.class)
-class AppModule {
- @Singleton @Provides
- GitHubService provideGithubService() {
- return new Retrofit.Builder()
- .baseUrl(GitHubService.HTTPS_API_GITHUB_URL)
- .addConverterFactory(GsonConverterFactory.create())
- .build()
- .create(GitHubService.class);
- }
-
- @Singleton
- @Provides
- ViewModelProvider.Factory provideViewModelFactory(
- ViewModelSubComponent.Builder viewModelSubComponent) {
-
- return new ProjectViewModelFactory(viewModelSubComponent.build());
- }
-}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/di/AppModule.kt b/app/src/main/java/com/example/test/mvvmsampleapp/di/AppModule.kt
new file mode 100644
index 0000000..94c6444
--- /dev/null
+++ b/app/src/main/java/com/example/test/mvvmsampleapp/di/AppModule.kt
@@ -0,0 +1,32 @@
+package com.example.test.mvvmsampleapp.di
+
+import android.arch.lifecycle.ViewModelProvider
+import com.example.test.mvvmsampleapp.service.repository.GitHubService
+import com.example.test.mvvmsampleapp.viewmodel.ProjectViewModelFactory
+import dagger.Module
+import dagger.Provides
+import retrofit2.Retrofit
+import retrofit2.converter.gson.GsonConverterFactory
+import javax.inject.Singleton
+
+@Module(subcomponents = [(ViewModelSubComponent::class)])
+internal class AppModule {
+
+ @Singleton
+ @Provides
+ fun provideGithubService(): GitHubService {
+ return Retrofit.Builder()
+ .baseUrl(GitHubService.HTTPS_API_GITHUB_URL)
+ .addConverterFactory(GsonConverterFactory.create())
+ .build()
+ .create(GitHubService::class.java)
+ }
+
+ @Singleton
+ @Provides
+ fun provideViewModelFactory(
+ viewModelSubComponent: ViewModelSubComponent.Builder): ViewModelProvider.Factory {
+
+ return ProjectViewModelFactory(viewModelSubComponent.build())
+ }
+}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/di/FragmentBuildersModule.java b/app/src/main/java/com/example/test/mvvmsampleapp/di/FragmentBuildersModule.java
deleted file mode 100644
index a8fc351..0000000
--- a/app/src/main/java/com/example/test/mvvmsampleapp/di/FragmentBuildersModule.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.example.test.mvvmsampleapp.di;
-
-import com.example.test.mvvmsampleapp.view.ui.ProjectFragment;
-import com.example.test.mvvmsampleapp.view.ui.ProjectListFragment;
-
-import dagger.Module;
-import dagger.android.ContributesAndroidInjector;
-
-@Module
-public abstract class FragmentBuildersModule {
- @ContributesAndroidInjector
- abstract ProjectFragment contributeProjectFragment();
-
- @ContributesAndroidInjector
- abstract ProjectListFragment contributeProjectListFragment();
-}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/di/FragmentBuildersModule.kt b/app/src/main/java/com/example/test/mvvmsampleapp/di/FragmentBuildersModule.kt
new file mode 100644
index 0000000..277b7dc
--- /dev/null
+++ b/app/src/main/java/com/example/test/mvvmsampleapp/di/FragmentBuildersModule.kt
@@ -0,0 +1,18 @@
+package com.example.test.mvvmsampleapp.di
+
+import com.example.test.mvvmsampleapp.view.ui.ProjectFragment
+import com.example.test.mvvmsampleapp.view.ui.ProjectListFragment
+
+import dagger.Module
+import dagger.android.ContributesAndroidInjector
+
+@Module
+abstract class FragmentBuildersModule {
+
+ @ContributesAndroidInjector
+ internal abstract fun contributeProjectFragment(): ProjectFragment
+
+ @ContributesAndroidInjector
+ internal abstract fun contributeProjectListFragment(): ProjectListFragment
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/di/Injectable.java b/app/src/main/java/com/example/test/mvvmsampleapp/di/Injectable.java
deleted file mode 100644
index 57c83b7..0000000
--- a/app/src/main/java/com/example/test/mvvmsampleapp/di/Injectable.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.example.test.mvvmsampleapp.di;
-
-/**
- * Marker interface for fragments.
- */
-public interface Injectable {
-}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/di/Injectable.kt b/app/src/main/java/com/example/test/mvvmsampleapp/di/Injectable.kt
new file mode 100644
index 0000000..3042210
--- /dev/null
+++ b/app/src/main/java/com/example/test/mvvmsampleapp/di/Injectable.kt
@@ -0,0 +1,6 @@
+package com.example.test.mvvmsampleapp.di
+
+/**
+ * Marker interface for fragments.
+ */
+interface Injectable
\ No newline at end of file
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/di/MainActivityModule.java b/app/src/main/java/com/example/test/mvvmsampleapp/di/MainActivityModule.java
deleted file mode 100644
index 6314631..0000000
--- a/app/src/main/java/com/example/test/mvvmsampleapp/di/MainActivityModule.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.example.test.mvvmsampleapp.di;
-
-import com.example.test.mvvmsampleapp.view.ui.MainActivity;
-
-import dagger.Module;
-import dagger.android.ContributesAndroidInjector;
-
-@Module
-public abstract class MainActivityModule {
- @ContributesAndroidInjector(modules = FragmentBuildersModule.class)
- abstract MainActivity contributeMainActivity();
-}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/di/MainActivityModule.kt b/app/src/main/java/com/example/test/mvvmsampleapp/di/MainActivityModule.kt
new file mode 100644
index 0000000..e5639db
--- /dev/null
+++ b/app/src/main/java/com/example/test/mvvmsampleapp/di/MainActivityModule.kt
@@ -0,0 +1,14 @@
+package com.example.test.mvvmsampleapp.di
+
+import com.example.test.mvvmsampleapp.view.ui.MainActivity
+
+import dagger.Module
+import dagger.android.ContributesAndroidInjector
+
+@Module
+abstract class MainActivityModule {
+
+ @ContributesAndroidInjector(modules = [(FragmentBuildersModule::class)])
+ internal abstract fun contributeMainActivity(): MainActivity
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/di/ViewModelSubComponent.java b/app/src/main/java/com/example/test/mvvmsampleapp/di/ViewModelSubComponent.java
deleted file mode 100644
index 5999ff5..0000000
--- a/app/src/main/java/com/example/test/mvvmsampleapp/di/ViewModelSubComponent.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.example.test.mvvmsampleapp.di;
-
-import com.example.test.mvvmsampleapp.viewmodel.ProjectListViewModel;
-import com.example.test.mvvmsampleapp.viewmodel.ProjectViewModel;
-
-import dagger.Subcomponent;
-
-/**
- * A sub component to create ViewModels. It is called by the
- * {@link com.example.test.mvvmsampleapp.viewmodel.ProjectViewModelFactory}.
- */
-@Subcomponent
-public interface ViewModelSubComponent {
- @Subcomponent.Builder
- interface Builder {
- ViewModelSubComponent build();
- }
-
- ProjectListViewModel projectListViewModel();
- ProjectViewModel projectViewModel();
-}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/di/ViewModelSubComponent.kt b/app/src/main/java/com/example/test/mvvmsampleapp/di/ViewModelSubComponent.kt
new file mode 100644
index 0000000..ddd7d79
--- /dev/null
+++ b/app/src/main/java/com/example/test/mvvmsampleapp/di/ViewModelSubComponent.kt
@@ -0,0 +1,24 @@
+package com.example.test.mvvmsampleapp.di
+
+import com.example.test.mvvmsampleapp.viewmodel.ProjectListViewModel
+import com.example.test.mvvmsampleapp.viewmodel.ProjectViewModel
+
+import dagger.Subcomponent
+
+/**
+ * A sub component to create ViewModels. It is called by the
+ * [com.example.test.mvvmsampleapp.viewmodel.ProjectViewModelFactory].
+ */
+@Subcomponent
+interface ViewModelSubComponent {
+
+ @Subcomponent.Builder
+ interface Builder {
+ fun build(): ViewModelSubComponent
+ }
+
+ fun projectListViewModel(): ProjectListViewModel
+
+ fun projectViewModel(): ProjectViewModel
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/service/model/Project.java b/app/src/main/java/com/example/test/mvvmsampleapp/service/model/Project.java
deleted file mode 100644
index 040dbc6..0000000
--- a/app/src/main/java/com/example/test/mvvmsampleapp/service/model/Project.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.example.test.mvvmsampleapp.service.model;
-
-import java.util.Date;
-
-public class Project {
- public long id;
- public String name;
- public String full_name;
- public User owner;
- public String html_url;
- public String description;
- public String url;
- public Date created_at;
- public Date updated_at;
- public Date pushed_at;
- public String git_url;
- public String ssh_url;
- public String clone_url;
- public String svn_url;
- public String homepage;
- public int stargazers_count;
- public int watchers_count;
- public String language;
- public boolean has_issues;
- public boolean has_downloads;
- public boolean has_wiki;
- public boolean has_pages;
- public int forks_count;
- public int open_issues_count;
- public int forks;
- public int open_issues;
- public int watchers;
- public String default_branch;
-
- public Project() {
- }
-
- public Project(String name) {
- this.name = name;
- }
-}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/service/model/Project.kt b/app/src/main/java/com/example/test/mvvmsampleapp/service/model/Project.kt
new file mode 100644
index 0000000..a552bbd
--- /dev/null
+++ b/app/src/main/java/com/example/test/mvvmsampleapp/service/model/Project.kt
@@ -0,0 +1,33 @@
+package com.example.test.mvvmsampleapp.service.model
+
+import java.util.*
+
+data class Project(
+ var id: Long = 0,
+ var name: String? = null,
+ var full_name: String? = null,
+ var owner: User? = null,
+ var html_url: String? = null,
+ var description: String? = null,
+ var url: String? = null,
+ var created_at: Date? = null,
+ var updated_at: Date? = null,
+ var pushed_at: Date? = null,
+ var git_url: String? = null,
+ var ssh_url: String? = null,
+ var clone_url: String? = null,
+ var svn_url: String? = null,
+ var homepage: String? = null,
+ var stargazers_count: Int = 0,
+ var watchers_count: Int = 0,
+ var language: String? = null,
+ var has_issues: Boolean = false,
+ var has_downloads: Boolean = false,
+ var has_wiki: Boolean = false,
+ var has_pages: Boolean = false,
+ var forks_count: Int = 0,
+ var open_issues_count: Int = 0,
+ var forks: Int = 0,
+ var open_issues: Int = 0,
+ var watchers: Int = 0,
+ var default_branch: String? = null)
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/service/model/User.java b/app/src/main/java/com/example/test/mvvmsampleapp/service/model/User.java
deleted file mode 100644
index 367e4bf..0000000
--- a/app/src/main/java/com/example/test/mvvmsampleapp/service/model/User.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.example.test.mvvmsampleapp.service.model;
-
-import java.util.Date;
-
-public class User {
- public String login;
- public long id;
- public String avatar_url;
- public String gravatar_id;
- public String url;
- public String html_url;
- public String followers_url;
- public String following_url;
- public String gists_url;
- public String starred_url;
- public String subscriptions_url;
- public String organizations_url;
- public String repos_url;
- public String events_url;
- public String received_events_url;
- public String type;
- public String name;
- public String blog;
- public String location;
- public String email;
- public int public_repos;
- public int public_gists;
- public int followers;
- public int following;
- public Date created_at;
- public Date updated_at;
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/service/model/User.kt b/app/src/main/java/com/example/test/mvvmsampleapp/service/model/User.kt
new file mode 100644
index 0000000..26b1dd5
--- /dev/null
+++ b/app/src/main/java/com/example/test/mvvmsampleapp/service/model/User.kt
@@ -0,0 +1,31 @@
+package com.example.test.mvvmsampleapp.service.model
+
+import java.util.*
+
+data class User(
+ var login: String? = null,
+ var id: Long = 0,
+ var avatar_url: String? = null,
+ var gravatar_id: String? = null,
+ var url: String? = null,
+ var html_url: String? = null,
+ var followers_url: String? = null,
+ var following_url: String? = null,
+ var gists_url: String? = null,
+ var starred_url: String? = null,
+ var subscriptions_url: String? = null,
+ var organizations_url: String? = null,
+ var repos_url: String? = null,
+ var events_url: String? = null,
+ var received_events_url: String? = null,
+ var type: String? = null,
+ var name: String? = null,
+ var blog: String? = null,
+ var location: String? = null,
+ var email: String? = null,
+ var public_repos: Int = 0,
+ var public_gists: Int = 0,
+ var followers: Int = 0,
+ var following: Int = 0,
+ var created_at: Date? = null,
+ var updated_at: Date? = null)
\ No newline at end of file
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/service/repository/GitHubService.java b/app/src/main/java/com/example/test/mvvmsampleapp/service/repository/GitHubService.java
deleted file mode 100644
index a1fccc9..0000000
--- a/app/src/main/java/com/example/test/mvvmsampleapp/service/repository/GitHubService.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.example.test.mvvmsampleapp.service.repository;
-
-import com.example.test.mvvmsampleapp.service.model.Project;
-
-import java.util.List;
-
-import retrofit2.Call;
-import retrofit2.http.GET;
-import retrofit2.http.Path;
-
-public interface GitHubService {
- String HTTPS_API_GITHUB_URL = "https://api.github.com/";
-
- @GET("users/{user}/repos")
- Call> getProjectList(@Path("user") String user);
-
- @GET("/repos/{user}/{reponame}")
- Call getProjectDetails(@Path("user") String user, @Path("reponame") String projectName);
-}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/service/repository/GitHubService.kt b/app/src/main/java/com/example/test/mvvmsampleapp/service/repository/GitHubService.kt
new file mode 100644
index 0000000..7524f9d
--- /dev/null
+++ b/app/src/main/java/com/example/test/mvvmsampleapp/service/repository/GitHubService.kt
@@ -0,0 +1,24 @@
+package com.example.test.mvvmsampleapp.service.repository
+
+import com.example.test.mvvmsampleapp.service.model.Project
+
+import retrofit2.Call
+import retrofit2.http.GET
+import retrofit2.http.Path
+
+/**
+ * Network service with a list of all network calls in the app via retrofit.
+ */
+interface GitHubService {
+
+ @GET("users/{user}/repos")
+ fun getProjectList(@Path("user") user: String): Call>
+
+ @GET("repos/{user}/{reponame}")
+ fun getProjectDetails(@Path("user") user: String, @Path("reponame") projectName: String?): Call
+
+ companion object {
+ val HTTPS_API_GITHUB_URL = "https://api.github.com/"
+ }
+
+}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/service/repository/ProjectRepository.java b/app/src/main/java/com/example/test/mvvmsampleapp/service/repository/ProjectRepository.java
deleted file mode 100644
index 4252afe..0000000
--- a/app/src/main/java/com/example/test/mvvmsampleapp/service/repository/ProjectRepository.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.example.test.mvvmsampleapp.service.repository;
-
-import android.arch.lifecycle.LiveData;
-import android.arch.lifecycle.MutableLiveData;
-
-import com.example.test.mvvmsampleapp.service.model.Project;
-
-import java.util.List;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-import retrofit2.Call;
-import retrofit2.Callback;
-import retrofit2.Response;
-
-@Singleton
-public class ProjectRepository {
- private GitHubService gitHubService;
-
- @Inject
- public ProjectRepository(GitHubService gitHubService) {
- this.gitHubService = gitHubService;
- }
-
- public LiveData> getProjectList(String userId) {
- final MutableLiveData> data = new MutableLiveData<>();
-
- gitHubService.getProjectList(userId).enqueue(new Callback>() {
- @Override
- public void onResponse(Call> call, Response> response) {
- data.setValue(response.body());
- }
-
- @Override
- public void onFailure(Call> call, Throwable t) {
- // TODO better error handling in part #2 ...
- data.setValue(null);
- }
- });
-
- return data;
- }
-
- public LiveData getProjectDetails(String userID, String projectName) {
- final MutableLiveData data = new MutableLiveData<>();
-
- gitHubService.getProjectDetails(userID, projectName).enqueue(new Callback() {
- @Override
- public void onResponse(Call call, Response response) {
- simulateDelay();
- data.setValue(response.body());
- }
-
- @Override
- public void onFailure(Call call, Throwable t) {
- // TODO better error handling in part #2 ...
- data.setValue(null);
- }
- });
-
- return data;
- }
-
- private void simulateDelay() {
- try {
- Thread.sleep(10);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/service/repository/ProjectRepository.kt b/app/src/main/java/com/example/test/mvvmsampleapp/service/repository/ProjectRepository.kt
new file mode 100644
index 0000000..e909ad9
--- /dev/null
+++ b/app/src/main/java/com/example/test/mvvmsampleapp/service/repository/ProjectRepository.kt
@@ -0,0 +1,65 @@
+package com.example.test.mvvmsampleapp.service.repository
+
+import android.arch.lifecycle.LiveData
+import android.arch.lifecycle.MutableLiveData
+import com.example.test.mvvmsampleapp.service.model.Project
+import retrofit2.Call
+import retrofit2.Callback
+import retrofit2.Response
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class ProjectRepository @Inject
+constructor(private val gitHubService: GitHubService) {
+
+ fun getProjectList(userId: String): LiveData> {
+ val data = MutableLiveData>()
+
+ gitHubService.getProjectList(userId)
+ .enqueue(object : Callback> {
+ override fun onResponse(call: Call>,
+ response: Response>) {
+ data.value = response.body()
+ }
+
+ override fun onFailure(call: Call>,
+ t: Throwable) {
+ // TODO better error handling in part #2 ...
+ data.value = null
+ }
+ })
+
+ return data
+ }
+
+ fun getProjectDetails(userID: String, projectName: String?): LiveData {
+ val data = MutableLiveData()
+
+ gitHubService.getProjectDetails(userID, projectName)
+ .enqueue(object : Callback {
+ override fun onResponse(call: Call,
+ response: Response) {
+ simulateDelay()
+ data.value = response.body()
+ }
+
+ override fun onFailure(call: Call,
+ t: Throwable) {
+ // TODO better error handling in part #2 ...
+ data.value = null
+ }
+ })
+
+ return data
+ }
+
+ private fun simulateDelay() {
+ try {
+ Thread.sleep(10)
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+
+ }
+}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/view/adapter/CustomBindingAdapter.java b/app/src/main/java/com/example/test/mvvmsampleapp/view/adapter/CustomBindingAdapter.java
deleted file mode 100644
index 297147f..0000000
--- a/app/src/main/java/com/example/test/mvvmsampleapp/view/adapter/CustomBindingAdapter.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.example.test.mvvmsampleapp.view.adapter;
-
-import android.databinding.BindingAdapter;
-import android.view.View;
-
-public class CustomBindingAdapter {
- @BindingAdapter("visibleGone")
- public static void showHide(View view, boolean show) {
- view.setVisibility(show ? View.VISIBLE : View.GONE);
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/view/adapter/CustomBindingAdapter.kt b/app/src/main/java/com/example/test/mvvmsampleapp/view/adapter/CustomBindingAdapter.kt
new file mode 100644
index 0000000..69849c5
--- /dev/null
+++ b/app/src/main/java/com/example/test/mvvmsampleapp/view/adapter/CustomBindingAdapter.kt
@@ -0,0 +1,9 @@
+package com.example.test.mvvmsampleapp.view.adapter
+
+import android.databinding.BindingAdapter
+import android.view.View
+
+@BindingAdapter("visibleGone")
+fun showHide(view: View, show: Boolean) {
+ view.visibility = if (show) View.VISIBLE else View.GONE
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/view/adapter/ProjectAdapter.java b/app/src/main/java/com/example/test/mvvmsampleapp/view/adapter/ProjectAdapter.java
deleted file mode 100755
index 3618fcf..0000000
--- a/app/src/main/java/com/example/test/mvvmsampleapp/view/adapter/ProjectAdapter.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package com.example.test.mvvmsampleapp.view.adapter;
-
-import android.databinding.DataBindingUtil;
-import android.support.annotation.Nullable;
-import android.support.v7.util.DiffUtil;
-import android.support.v7.widget.RecyclerView;
-import android.view.LayoutInflater;
-import android.view.ViewGroup;
-
-import com.example.test.mvvmsampleapp.R;
-import com.example.test.mvvmsampleapp.databinding.ProjectListItemBinding;
-import com.example.test.mvvmsampleapp.service.model.Project;
-import com.example.test.mvvmsampleapp.view.callback.ProjectClickCallback;
-
-import java.util.List;
-import java.util.Objects;
-
-public class ProjectAdapter extends RecyclerView.Adapter {
-
- List extends Project> projectList;
-
- @Nullable
- private final ProjectClickCallback projectClickCallback;
-
- public ProjectAdapter(@Nullable ProjectClickCallback projectClickCallback) {
- this.projectClickCallback = projectClickCallback;
- }
-
- public void setProjectList(final List extends Project> projectList) {
- if (this.projectList == null) {
- this.projectList = projectList;
- notifyItemRangeInserted(0, projectList.size());
- } else {
- DiffUtil.DiffResult result = DiffUtil.calculateDiff(new DiffUtil.Callback() {
- @Override
- public int getOldListSize() {
- return ProjectAdapter.this.projectList.size();
- }
-
- @Override
- public int getNewListSize() {
- return projectList.size();
- }
-
- @Override
- public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
- return ProjectAdapter.this.projectList.get(oldItemPosition).id ==
- projectList.get(newItemPosition).id;
- }
-
- @Override
- public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
- Project project = projectList.get(newItemPosition);
- Project old = projectList.get(oldItemPosition);
- return project.id == old.id
- && Objects.equals(project.git_url, old.git_url);
- }
- });
- this.projectList = projectList;
- result.dispatchUpdatesTo(this);
- }
- }
-
- @Override
- public ProjectViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- ProjectListItemBinding binding = DataBindingUtil
- .inflate(LayoutInflater.from(parent.getContext()), R.layout.project_list_item,
- parent, false);
-
- binding.setCallback(projectClickCallback);
-
- return new ProjectViewHolder(binding);
- }
-
- @Override
- public void onBindViewHolder(ProjectViewHolder holder, int position) {
- holder.binding.setProject(projectList.get(position));
- holder.binding.executePendingBindings();
- }
-
- @Override
- public int getItemCount() {
- return projectList == null ? 0 : projectList.size();
- }
-
- static class ProjectViewHolder extends RecyclerView.ViewHolder {
-
- final ProjectListItemBinding binding;
-
- public ProjectViewHolder(ProjectListItemBinding binding) {
- super(binding.getRoot());
- this.binding = binding;
- }
- }
-}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/view/adapter/ProjectAdapter.kt b/app/src/main/java/com/example/test/mvvmsampleapp/view/adapter/ProjectAdapter.kt
new file mode 100755
index 0000000..17ee93c
--- /dev/null
+++ b/app/src/main/java/com/example/test/mvvmsampleapp/view/adapter/ProjectAdapter.kt
@@ -0,0 +1,77 @@
+package com.example.test.mvvmsampleapp.view.adapter
+
+import android.databinding.DataBindingUtil
+import android.support.v7.util.DiffUtil
+import android.support.v7.widget.RecyclerView
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import com.example.test.mvvmsampleapp.R
+import com.example.test.mvvmsampleapp.databinding.ProjectListItemBinding
+import com.example.test.mvvmsampleapp.service.model.Project
+import com.example.test.mvvmsampleapp.view.callback.ProjectClickCallback
+import com.example.test.mvvmsampleapp.view.viewholders.ProjectViewHolder
+
+/**
+ * Adapter which shows a list of repositories.
+ */
+class ProjectAdapter(private val projectClickCallback: ProjectClickCallback?)
+ : RecyclerView.Adapter() {
+
+ internal var projectList: List? = null
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProjectViewHolder {
+ val binding = DataBindingUtil
+ .inflate(LayoutInflater.from(parent.context),
+ R.layout.project_list_item,
+ parent, false)
+
+ binding.callback = projectClickCallback
+
+ return ProjectViewHolder(binding)
+ }
+
+ override fun onBindViewHolder(holder: ProjectViewHolder, position: Int) {
+ holder.binding.project = projectList!![position]
+ holder.binding.executePendingBindings()
+ }
+
+ override fun getItemCount(): Int {
+ return if (projectList == null) 0 else projectList!!.size
+ }
+
+ fun setProjectList(projectList: List) {
+ if (this.projectList == null) {
+ this.projectList = projectList
+ notifyDataSetChanged()
+ } else {
+ calculateDiff(projectList)
+ }
+ }
+
+ private fun calculateDiff(projectList: List) {
+ val result = DiffUtil.calculateDiff(object : DiffUtil.Callback() {
+ override fun getOldListSize(): Int {
+ return this@ProjectAdapter.projectList!!.size
+ }
+
+ override fun getNewListSize(): Int {
+ return projectList.size
+ }
+
+ override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
+ return this@ProjectAdapter.projectList!![oldItemPosition].id ==
+ projectList[newItemPosition].id
+ }
+
+ override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
+ val project = projectList[newItemPosition]
+ val old = projectList[oldItemPosition]
+ return project.id == old.id &&
+ project.git_url == old.git_url
+ }
+ })
+ this.projectList = projectList
+ result.dispatchUpdatesTo(this)
+ }
+
+}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/view/callback/ProjectClickCallback.java b/app/src/main/java/com/example/test/mvvmsampleapp/view/callback/ProjectClickCallback.java
deleted file mode 100755
index dcb8d4b..0000000
--- a/app/src/main/java/com/example/test/mvvmsampleapp/view/callback/ProjectClickCallback.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.example.test.mvvmsampleapp.view.callback;
-
-import com.example.test.mvvmsampleapp.service.model.Project;
-
-public interface ProjectClickCallback {
- void onClick(Project project);
-}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/view/callback/ProjectClickCallback.kt b/app/src/main/java/com/example/test/mvvmsampleapp/view/callback/ProjectClickCallback.kt
new file mode 100755
index 0000000..a3f3b1f
--- /dev/null
+++ b/app/src/main/java/com/example/test/mvvmsampleapp/view/callback/ProjectClickCallback.kt
@@ -0,0 +1,7 @@
+package com.example.test.mvvmsampleapp.view.callback
+
+import com.example.test.mvvmsampleapp.service.model.Project
+
+interface ProjectClickCallback {
+ fun onClick(project: Project)
+}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/view/ui/MainActivity.java b/app/src/main/java/com/example/test/mvvmsampleapp/view/ui/MainActivity.java
deleted file mode 100755
index 3c8e58b..0000000
--- a/app/src/main/java/com/example/test/mvvmsampleapp/view/ui/MainActivity.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.example.test.mvvmsampleapp.view.ui;
-
-import android.arch.lifecycle.LifecycleActivity;
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
-
-import com.example.test.mvvmsampleapp.R;
-import com.example.test.mvvmsampleapp.service.model.Project;
-
-import javax.inject.Inject;
-
-import dagger.android.DispatchingAndroidInjector;
-import dagger.android.support.HasSupportFragmentInjector;
-
-public class MainActivity extends LifecycleActivity implements HasSupportFragmentInjector {
-
- @Inject
- DispatchingAndroidInjector dispatchingAndroidInjector;
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
-
- // Add project list fragment if this is first creation
- if (savedInstanceState == null) {
- ProjectListFragment fragment = new ProjectListFragment();
-
- getSupportFragmentManager().beginTransaction()
- .add(R.id.fragment_container, fragment, ProjectListFragment.TAG).commit();
- }
- }
-
- /** Shows the project detail fragment */
- public void show(Project project) {
- ProjectFragment projectFragment = ProjectFragment.forProject(project.name);
-
- getSupportFragmentManager()
- .beginTransaction()
- .addToBackStack("project")
- .replace(R.id.fragment_container,
- projectFragment, null).commit();
- }
-
- @Override
- public DispatchingAndroidInjector supportFragmentInjector() {
- return dispatchingAndroidInjector;
- }
-}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/view/ui/MainActivity.kt b/app/src/main/java/com/example/test/mvvmsampleapp/view/ui/MainActivity.kt
new file mode 100755
index 0000000..c57570e
--- /dev/null
+++ b/app/src/main/java/com/example/test/mvvmsampleapp/view/ui/MainActivity.kt
@@ -0,0 +1,49 @@
+package com.example.test.mvvmsampleapp.view.ui
+
+import android.os.Bundle
+import android.support.v4.app.Fragment
+import android.support.v7.app.AppCompatActivity
+import com.example.test.mvvmsampleapp.R
+import com.example.test.mvvmsampleapp.service.model.Project
+import dagger.android.DispatchingAndroidInjector
+import dagger.android.support.HasSupportFragmentInjector
+import javax.inject.Inject
+
+/**
+ * Main App activity which presents different fragments.
+ */
+class MainActivity : AppCompatActivity(), HasSupportFragmentInjector {
+
+ @Inject
+ lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+
+ // Add project list fragment if this is first creation
+ if (savedInstanceState == null) {
+ val fragment = ProjectListFragment()
+
+ supportFragmentManager.beginTransaction()
+ .add(R.id.fragment_container, fragment, ProjectListFragment.TAG)
+ .commit()
+ }
+ }
+
+ /** Shows the project detail fragment */
+ fun show(project: Project?) {
+ val projectFragment = ProjectFragment.newInstance(project?.name)
+
+ supportFragmentManager
+ .beginTransaction()
+ .addToBackStack("project")
+ .replace(R.id.fragment_container,
+ projectFragment, null).commit()
+ }
+
+ override fun supportFragmentInjector(): DispatchingAndroidInjector? {
+ return dispatchingAndroidInjector
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/view/ui/ProjectFragment.java b/app/src/main/java/com/example/test/mvvmsampleapp/view/ui/ProjectFragment.java
deleted file mode 100755
index e0d8c2f..0000000
--- a/app/src/main/java/com/example/test/mvvmsampleapp/view/ui/ProjectFragment.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package com.example.test.mvvmsampleapp.view.ui;
-
-import android.arch.lifecycle.LifecycleFragment;
-import android.arch.lifecycle.Observer;
-import android.arch.lifecycle.ViewModelProvider;
-import android.arch.lifecycle.ViewModelProviders;
-import android.databinding.DataBindingUtil;
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.example.test.mvvmsampleapp.R;
-import com.example.test.mvvmsampleapp.databinding.FragmentProjectDetailsBinding;
-import com.example.test.mvvmsampleapp.di.Injectable;
-import com.example.test.mvvmsampleapp.service.model.Project;
-import com.example.test.mvvmsampleapp.viewmodel.ProjectViewModel;
-
-import javax.inject.Inject;
-
-public class ProjectFragment extends LifecycleFragment implements Injectable {
- private static final String KEY_PROJECT_ID = "project_id";
- private FragmentProjectDetailsBinding binding;
-
- @Inject
- ViewModelProvider.Factory viewModelFactory;
-
- @Nullable
- @Override
- public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
- @Nullable Bundle savedInstanceState) {
- // Inflate this data binding layout
- binding = DataBindingUtil.inflate(inflater, R.layout.fragment_project_details, container, false);
-
- // Create and set the adapter for the RecyclerView.
- return binding.getRoot();
- }
-
- @Override
- public void onActivityCreated(@Nullable Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- final ProjectViewModel viewModel = ViewModelProviders.of(this, viewModelFactory)
- .get(ProjectViewModel.class);
-
- viewModel.setProjectID(getArguments().getString(KEY_PROJECT_ID));
-
- binding.setProjectViewModel(viewModel);
- binding.setIsLoading(true);
-
- observeViewModel(viewModel);
- }
-
- private void observeViewModel(final ProjectViewModel viewModel) {
- // Observe project data
- viewModel.getObservableProject().observe(this, new Observer() {
- @Override
- public void onChanged(@Nullable Project project) {
- if (project != null) {
- binding.setIsLoading(false);
- viewModel.setProject(project);
- }
- }
- });
- }
-
- /** Creates project fragment for specific project ID */
- public static ProjectFragment forProject(String projectID) {
- ProjectFragment fragment = new ProjectFragment();
- Bundle args = new Bundle();
-
- args.putString(KEY_PROJECT_ID, projectID);
- fragment.setArguments(args);
-
- return fragment;
- }
-}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/view/ui/ProjectFragment.kt b/app/src/main/java/com/example/test/mvvmsampleapp/view/ui/ProjectFragment.kt
new file mode 100755
index 0000000..b3078f3
--- /dev/null
+++ b/app/src/main/java/com/example/test/mvvmsampleapp/view/ui/ProjectFragment.kt
@@ -0,0 +1,76 @@
+package com.example.test.mvvmsampleapp.view.ui
+
+import android.arch.lifecycle.Observer
+import android.arch.lifecycle.ViewModelProvider
+import android.arch.lifecycle.ViewModelProviders
+import android.databinding.DataBindingUtil
+import android.os.Bundle
+import android.support.v4.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.example.test.mvvmsampleapp.R
+import com.example.test.mvvmsampleapp.databinding.FragmentProjectDetailsBinding
+import com.example.test.mvvmsampleapp.di.Injectable
+import com.example.test.mvvmsampleapp.viewmodel.ProjectViewModel
+import javax.inject.Inject
+
+/**
+ * Fragment for a detailed info about a GitHub Repository.
+ */
+class ProjectFragment : Fragment(), Injectable {
+
+ @Inject
+ lateinit var viewModelFactory: ViewModelProvider.Factory
+
+ private lateinit var binding: FragmentProjectDetailsBinding
+
+ companion object {
+
+ private val KEY_PROJECT_ID = "project_id"
+
+ /** Creates project fragment for specific project ID */
+ fun newInstance(projectID: String?): ProjectFragment {
+ val fragment = ProjectFragment()
+ val args = Bundle()
+
+ args.putString(KEY_PROJECT_ID, projectID)
+ fragment.arguments = args
+
+ return fragment
+ }
+ }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ // Inflate this data binding layout
+ binding = DataBindingUtil.inflate(inflater, R.layout.fragment_project_details, container, false)
+
+ // Create and set the adapter for the RecyclerView.
+ return binding.root
+ }
+
+ override fun onActivityCreated(savedInstanceState: Bundle?) {
+ super.onActivityCreated(savedInstanceState)
+
+ val viewModel = ViewModelProviders.of(this, viewModelFactory)
+ .get(ProjectViewModel::class.java)
+
+ viewModel.setProjectID(arguments?.getString(KEY_PROJECT_ID))
+
+ binding.projectViewModel = viewModel
+ binding.isLoading = true
+
+ observeViewModel(viewModel)
+ }
+
+ private fun observeViewModel(viewModel: ProjectViewModel) {
+ // Observe project data
+ viewModel.observableProject.observe(this, Observer { project ->
+ if (project != null) {
+ binding.isLoading = false
+ viewModel.setProject(project)
+ }
+ })
+ }
+}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/view/ui/ProjectListFragment.java b/app/src/main/java/com/example/test/mvvmsampleapp/view/ui/ProjectListFragment.java
deleted file mode 100755
index 2ed18a4..0000000
--- a/app/src/main/java/com/example/test/mvvmsampleapp/view/ui/ProjectListFragment.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.example.test.mvvmsampleapp.view.ui;
-
-import android.arch.lifecycle.Lifecycle;
-import android.arch.lifecycle.LifecycleFragment;
-import android.arch.lifecycle.Observer;
-import android.arch.lifecycle.ViewModelProvider;
-import android.arch.lifecycle.ViewModelProviders;
-import android.databinding.DataBindingUtil;
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.example.test.mvvmsampleapp.R;
-import com.example.test.mvvmsampleapp.databinding.FragmentProjectListBinding;
-import com.example.test.mvvmsampleapp.di.Injectable;
-import com.example.test.mvvmsampleapp.service.model.Project;
-import com.example.test.mvvmsampleapp.view.adapter.ProjectAdapter;
-import com.example.test.mvvmsampleapp.view.callback.ProjectClickCallback;
-import com.example.test.mvvmsampleapp.viewmodel.ProjectListViewModel;
-
-import java.util.List;
-
-import javax.inject.Inject;
-
-public class ProjectListFragment extends LifecycleFragment implements Injectable {
- public static final String TAG = "ProjectListFragment";
- private ProjectAdapter projectAdapter;
- private FragmentProjectListBinding binding;
-
- @Inject
- ViewModelProvider.Factory viewModelFactory;
-
- @Nullable
- @Override
- public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
- @Nullable Bundle savedInstanceState) {
- binding = DataBindingUtil.inflate(inflater, R.layout.fragment_project_list, container, false);
-
- projectAdapter = new ProjectAdapter(projectClickCallback);
- binding.projectList.setAdapter(projectAdapter);
- binding.setIsLoading(true);
-
- return binding.getRoot();
- }
-
- @Override
- public void onActivityCreated(@Nullable Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- final ProjectListViewModel viewModel = ViewModelProviders.of(this,
- viewModelFactory).get(ProjectListViewModel.class);
-
- observeViewModel(viewModel);
- }
-
- private void observeViewModel(ProjectListViewModel viewModel) {
- // Update the list when the data changes
- viewModel.getProjectListObservable().observe(this, new Observer>() {
- @Override
- public void onChanged(@Nullable List projects) {
- if (projects != null) {
- binding.setIsLoading(false);
- projectAdapter.setProjectList(projects);
- }
- }
- });
- }
-
- private final ProjectClickCallback projectClickCallback = new ProjectClickCallback() {
- @Override
- public void onClick(Project project) {
- if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
- ((MainActivity) getActivity()).show(project);
- }
- }
- };
-}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/view/ui/ProjectListFragment.kt b/app/src/main/java/com/example/test/mvvmsampleapp/view/ui/ProjectListFragment.kt
new file mode 100755
index 0000000..78bbea8
--- /dev/null
+++ b/app/src/main/java/com/example/test/mvvmsampleapp/view/ui/ProjectListFragment.kt
@@ -0,0 +1,76 @@
+package com.example.test.mvvmsampleapp.view.ui
+
+import android.arch.lifecycle.Lifecycle
+import android.arch.lifecycle.Observer
+import android.arch.lifecycle.ViewModelProvider
+import android.arch.lifecycle.ViewModelProviders
+import android.databinding.DataBindingUtil
+import android.os.Bundle
+import android.support.v4.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+
+import com.example.test.mvvmsampleapp.R
+import com.example.test.mvvmsampleapp.databinding.FragmentProjectListBinding
+import com.example.test.mvvmsampleapp.di.Injectable
+import com.example.test.mvvmsampleapp.service.model.Project
+import com.example.test.mvvmsampleapp.view.adapter.ProjectAdapter
+import com.example.test.mvvmsampleapp.view.callback.ProjectClickCallback
+import com.example.test.mvvmsampleapp.viewmodel.ProjectListViewModel
+
+import javax.inject.Inject
+
+/**
+ * Fragment with a list of GitHub repositories.
+ */
+class ProjectListFragment : Fragment(), Injectable {
+
+ @Inject
+ lateinit var viewModelFactory: ViewModelProvider.Factory
+
+ private lateinit var projectAdapter: ProjectAdapter
+ private lateinit var binding: FragmentProjectListBinding
+
+ companion object {
+ val TAG = "ProjectListFragment"
+ }
+
+ private val projectClickCallback = object : ProjectClickCallback {
+ override fun onClick(project: Project) {
+ if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
+ (activity as MainActivity).show(project)
+ }
+ }
+ }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ binding = DataBindingUtil.inflate(inflater, R.layout.fragment_project_list, container, false)
+
+ projectAdapter = ProjectAdapter(projectClickCallback)
+ binding.projectList.adapter = projectAdapter
+ binding.isLoading = true
+
+ return binding.root
+ }
+
+ override fun onActivityCreated(savedInstanceState: Bundle?) {
+ super.onActivityCreated(savedInstanceState)
+
+ val viewModel = ViewModelProviders.of(this, viewModelFactory)
+ .get(ProjectListViewModel::class.java)
+
+ observeViewModel(viewModel)
+ }
+
+ private fun observeViewModel(viewModel: ProjectListViewModel) {
+ // Update the list when the data changes
+ viewModel.projectListObservable.observe(this, Observer { projects ->
+ if (projects != null) {
+ binding.isLoading = false
+ projectAdapter.setProjectList(projects)
+ }
+ })
+ }
+}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/view/viewholders/ProjectViewHolder.kt b/app/src/main/java/com/example/test/mvvmsampleapp/view/viewholders/ProjectViewHolder.kt
new file mode 100644
index 0000000..43ca98e
--- /dev/null
+++ b/app/src/main/java/com/example/test/mvvmsampleapp/view/viewholders/ProjectViewHolder.kt
@@ -0,0 +1,6 @@
+package com.example.test.mvvmsampleapp.view.viewholders
+
+import android.support.v7.widget.RecyclerView
+import com.example.test.mvvmsampleapp.databinding.ProjectListItemBinding
+
+class ProjectViewHolder(val binding: ProjectListItemBinding) : RecyclerView.ViewHolder(binding.root)
\ No newline at end of file
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/viewmodel/ProjectListViewModel.java b/app/src/main/java/com/example/test/mvvmsampleapp/viewmodel/ProjectListViewModel.java
deleted file mode 100755
index 6e73421..0000000
--- a/app/src/main/java/com/example/test/mvvmsampleapp/viewmodel/ProjectListViewModel.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.example.test.mvvmsampleapp.viewmodel;
-
-import android.app.Application;
-import android.arch.lifecycle.AndroidViewModel;
-import android.arch.lifecycle.LiveData;
-import android.support.annotation.NonNull;
-
-import com.example.test.mvvmsampleapp.service.model.Project;
-import com.example.test.mvvmsampleapp.service.repository.ProjectRepository;
-
-import java.util.List;
-
-import javax.inject.Inject;
-
-public class ProjectListViewModel extends AndroidViewModel {
- private final LiveData> projectListObservable;
-
- @Inject
- public ProjectListViewModel(@NonNull ProjectRepository projectRepository, @NonNull Application application) {
- super(application);
-
- // If any transformation is needed, this can be simply done by Transformations class ...
- projectListObservable = projectRepository.getProjectList("Google");
- }
-
- /**
- * Expose the LiveData Projects query so the UI can observe it.
- */
- public LiveData> getProjectListObservable() {
- return projectListObservable;
- }
-}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/viewmodel/ProjectListViewModel.kt b/app/src/main/java/com/example/test/mvvmsampleapp/viewmodel/ProjectListViewModel.kt
new file mode 100755
index 0000000..47cff31
--- /dev/null
+++ b/app/src/main/java/com/example/test/mvvmsampleapp/viewmodel/ProjectListViewModel.kt
@@ -0,0 +1,22 @@
+package com.example.test.mvvmsampleapp.viewmodel
+
+import android.app.Application
+import android.arch.lifecycle.AndroidViewModel
+import android.arch.lifecycle.LiveData
+
+import com.example.test.mvvmsampleapp.service.model.Project
+import com.example.test.mvvmsampleapp.service.repository.ProjectRepository
+
+import javax.inject.Inject
+
+class ProjectListViewModel
+@Inject constructor(projectRepository: ProjectRepository,
+ application: Application) : AndroidViewModel(application) {
+
+ /**
+ * Expose the LiveData Projects query so the UI can observe it.
+ */
+ val projectListObservable: LiveData> =
+ projectRepository.getProjectList("Google")
+
+}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/viewmodel/ProjectViewModel.java b/app/src/main/java/com/example/test/mvvmsampleapp/viewmodel/ProjectViewModel.java
deleted file mode 100755
index 9f95d93..0000000
--- a/app/src/main/java/com/example/test/mvvmsampleapp/viewmodel/ProjectViewModel.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.example.test.mvvmsampleapp.viewmodel;
-
-import android.app.Application;
-import android.arch.lifecycle.AndroidViewModel;
-import android.arch.lifecycle.LiveData;
-import android.arch.lifecycle.MutableLiveData;
-import android.arch.lifecycle.Transformations;
-import android.databinding.ObservableField;
-import android.support.annotation.NonNull;
-import android.util.Log;
-
-import com.example.test.mvvmsampleapp.service.model.Project;
-import com.example.test.mvvmsampleapp.service.repository.ProjectRepository;
-
-import javax.inject.Inject;
-
-public class ProjectViewModel extends AndroidViewModel {
- private static final String TAG = ProjectViewModel.class.getName();
- private static final MutableLiveData ABSENT = new MutableLiveData();
- {
- //noinspection unchecked
- ABSENT.setValue(null);
- }
-
- private final LiveData projectObservable;
- private final MutableLiveData projectID;
-
- public ObservableField project = new ObservableField<>();
-
- @Inject
- public ProjectViewModel(@NonNull ProjectRepository projectRepository, @NonNull Application application) {
- super(application);
-
- this.projectID = new MutableLiveData<>();
-
- projectObservable = Transformations.switchMap(projectID, input -> {
- if (input.isEmpty()) {
- Log.i(TAG, "ProjectViewModel projectID is absent!!!");
- return ABSENT;
- }
-
- Log.i(TAG,"ProjectViewModel projectID is " + projectID.getValue());
-
- return projectRepository.getProjectDetails("Google", projectID.getValue());
- });
- }
-
- public LiveData getObservableProject() {
- return projectObservable;
- }
-
- public void setProject(Project project) {
- this.project.set(project);
- }
-
- public void setProjectID(String projectID) {
- this.projectID.setValue(projectID);
- }
-}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/viewmodel/ProjectViewModel.kt b/app/src/main/java/com/example/test/mvvmsampleapp/viewmodel/ProjectViewModel.kt
new file mode 100755
index 0000000..18bb114
--- /dev/null
+++ b/app/src/main/java/com/example/test/mvvmsampleapp/viewmodel/ProjectViewModel.kt
@@ -0,0 +1,55 @@
+package com.example.test.mvvmsampleapp.viewmodel
+
+import android.app.Application
+import android.arch.lifecycle.AndroidViewModel
+import android.arch.lifecycle.LiveData
+import android.arch.lifecycle.MutableLiveData
+import android.arch.lifecycle.Transformations
+import android.databinding.ObservableField
+import android.util.Log
+
+import com.example.test.mvvmsampleapp.service.model.Project
+import com.example.test.mvvmsampleapp.service.repository.ProjectRepository
+
+import javax.inject.Inject
+
+class ProjectViewModel @Inject
+constructor(projectRepository: ProjectRepository,
+ application: Application) : AndroidViewModel(application) {
+
+ val observableProject: LiveData
+ private var projectID: MutableLiveData = MutableLiveData()
+
+ var project = ObservableField()
+
+ companion object {
+
+ private val TAG = ProjectViewModel::class.java.name
+ private val ABSENT = MutableLiveData()
+
+ init {
+ ABSENT.value = null
+ }
+ }
+
+ init {
+ observableProject = Transformations.switchMap(projectID) { input ->
+
+ if (input.isEmpty()) {
+ Log.i(TAG, "ProjectViewModel projectID is absent!!!")
+ return@switchMap ABSENT
+ }
+
+ Log.i(TAG, "ProjectViewModel projectID is " + projectID.value)
+ projectRepository.getProjectDetails("Google", projectID.value)
+ }
+ }
+
+ fun setProject(project: Project) {
+ this.project.set(project)
+ }
+
+ fun setProjectID(projectID: String?) {
+ this.projectID.value = projectID
+ }
+}
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/viewmodel/ProjectViewModelFactory.java b/app/src/main/java/com/example/test/mvvmsampleapp/viewmodel/ProjectViewModelFactory.java
deleted file mode 100644
index bf19687..0000000
--- a/app/src/main/java/com/example/test/mvvmsampleapp/viewmodel/ProjectViewModelFactory.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.example.test.mvvmsampleapp.viewmodel;
-
-import android.arch.lifecycle.ViewModel;
-import android.arch.lifecycle.ViewModelProvider;
-import android.support.v4.util.ArrayMap;
-
-import com.example.test.mvvmsampleapp.di.ViewModelSubComponent;
-
-import java.util.Map;
-import java.util.concurrent.Callable;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-@Singleton
-public class ProjectViewModelFactory implements ViewModelProvider.Factory {
- private final ArrayMap> creators;
-
- @Inject
- public ProjectViewModelFactory(ViewModelSubComponent viewModelSubComponent) {
- creators = new ArrayMap<>();
-
- // View models cannot be injected directly because they won't be bound to the owner's view model scope.
- creators.put(ProjectViewModel.class, () -> viewModelSubComponent.projectViewModel());
- creators.put(ProjectListViewModel.class, () -> viewModelSubComponent.projectListViewModel());
- }
-
- @Override
- public T create(Class modelClass) {
- Callable extends ViewModel> creator = creators.get(modelClass);
- if (creator == null) {
- for (Map.Entry> entry : creators.entrySet()) {
- if (modelClass.isAssignableFrom(entry.getKey())) {
- creator = entry.getValue();
- break;
- }
- }
- }
- if (creator == null) {
- throw new IllegalArgumentException("Unknown model class " + modelClass);
- }
- try {
- return (T) creator.call();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/test/mvvmsampleapp/viewmodel/ProjectViewModelFactory.kt b/app/src/main/java/com/example/test/mvvmsampleapp/viewmodel/ProjectViewModelFactory.kt
new file mode 100644
index 0000000..755d6be
--- /dev/null
+++ b/app/src/main/java/com/example/test/mvvmsampleapp/viewmodel/ProjectViewModelFactory.kt
@@ -0,0 +1,51 @@
+package com.example.test.mvvmsampleapp.viewmodel
+
+import android.arch.lifecycle.ViewModel
+import android.arch.lifecycle.ViewModelProvider
+import android.support.v4.util.ArrayMap
+
+import com.example.test.mvvmsampleapp.di.ViewModelSubComponent
+import java.util.concurrent.Callable
+
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class ProjectViewModelFactory @Inject
+constructor(viewModelSubComponent: ViewModelSubComponent) : ViewModelProvider.Factory {
+
+ private val creators: ArrayMap, Callable> = ArrayMap()
+
+ init {
+ // View models cannot be injected directly because they won't be bound to the owner's view model scope.
+ creators.put(ProjectViewModel::class.java,
+ Callable { viewModelSubComponent.projectViewModel() })
+ creators.put(ProjectListViewModel::class.java,
+ Callable { viewModelSubComponent.projectListViewModel() })
+ }
+
+ override fun create(modelClass: Class): T {
+
+ var creator: Callable? = creators[modelClass]
+
+ if (creator == null) {
+ for ((key, value) in creators) {
+ if (modelClass.isAssignableFrom(key)) {
+ creator = value
+ break
+ }
+ }
+ }
+
+ if (creator == null) {
+ throw IllegalArgumentException("Unknown model class " + modelClass)
+ }
+
+ try {
+ return creator.call() as T
+ } catch (e: Exception) {
+ throw RuntimeException(e)
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 5a79861..62fe1c2 100755
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,8 +1,8 @@
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_project_list.xml b/app/src/main/res/layout/fragment_project_list.xml
index 1edb399..4a09426 100755
--- a/app/src/main/res/layout/fragment_project_list.xml
+++ b/app/src/main/res/layout/fragment_project_list.xml
@@ -45,7 +45,7 @@
android:contentDescription="@string/project_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:layoutManager="LinearLayoutManager"/>
+ app:layoutManager="android.support.v7.widget.LinearLayoutManager"/>
diff --git a/app/src/test/java/com/example/test/mvvmsampleapp/ExampleUnitTest.java b/app/src/test/java/com/example/test/mvvmsampleapp/ExampleUnitTest.java
deleted file mode 100644
index 7ef2e8e..0000000
--- a/app/src/test/java/com/example/test/mvvmsampleapp/ExampleUnitTest.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.example.test.mvvmsampleapp;
-
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-/**
- * Example local unit test, which will execute on the development machine (host).
- *
- * @see Testing documentation
- */
-public class ExampleUnitTest {
- @Test
- public void addition_isCorrect() throws Exception {
- assertEquals(4, 2 + 2);
- }
-}
\ No newline at end of file
diff --git a/app/src/test/java/com/example/test/mvvmsampleapp/ExampleUnitTest.kt b/app/src/test/java/com/example/test/mvvmsampleapp/ExampleUnitTest.kt
new file mode 100644
index 0000000..14b0243
--- /dev/null
+++ b/app/src/test/java/com/example/test/mvvmsampleapp/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package com.example.test.mvvmsampleapp
+
+import org.junit.Assert.assertEquals
+import org.junit.Test
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see [Testing documentation](http://d.android.com/tools/testing)
+ */
+class ExampleUnitTest {
+ @Test
+ @Throws(Exception::class)
+ fun addition_isCorrect() {
+ assertEquals(4, (2 + 2).toLong())
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index fe62d25..170d2ee 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,6 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
+ ext.kotlin_version = '1.2.10'
repositories {
maven { url 'https://maven.google.com' }
@@ -9,9 +10,11 @@ buildscript {
// You need to add the following repository to download the
// new plugin.
google()
+ mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.0.0-alpha5'
+ classpath 'com.android.tools.build:gradle:3.1.0-alpha08'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 195cbd3..bac89db 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Mon May 29 15:39:33 EDT 2017
+#Mon Dec 11 20:03:43 PST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-milestone-1-all.zip
+distributionUrl=https://services.gradle.org/distributions/gradle-4.4.1-all.zip