diff --git a/README.md b/README.md index a8b086b..e193710 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,11 @@ Example of Github API client implemented on top of Dagger 2 DI framework. This code was created as an example for Dependency Injection with Dagger 2 series on my dev-blog: -- [Introduction to Dependency Injection](http://frogermcs.github.io/dependency-injection-with-dagger-2-introdution-to-di/) +- [Introdution to Dependency Injection](http://frogermcs.github.io/dependency-injection-with-dagger-2-introdution-to-di/) - [Dagger 2 API](http://frogermcs.github.io/dependency-injection-with-dagger-2-the-api/) - [Dagger 2 - custom scopes](http://frogermcs.github.io/dependency-injection-with-dagger-2-custom-scopes/) - [Dagger 2 - graph creation performance](http://frogermcs.github.io/dagger-graph-creation-performance/) - [Dependency injection with Dagger 2 - Producers](http://frogermcs.github.io/dependency-injection-with-dagger-2-producers/) +- [Inject everything - ViewHolder and Dagger 2 (with Multibinding and AutoFactory example)](http://frogermcs.github.io/inject-everything-viewholder-and-dagger-2-example/) This code was originally prepared for my presentation at Google I/O Extended 2015 in Tech Space Cracow. http://www.meetup.com/GDG-Krakow/events/221822600/ diff --git a/app/build.gradle b/app/build.gradle index 51b76d3..c1901a0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,16 +1,14 @@ apply plugin: 'com.android.application' -apply plugin: 'com.neenbedankt.android-apt' apply plugin: 'com.frogermcs.androiddevmetrics' android { - compileSdkVersion 23 - buildToolsVersion "23.0.2" + compileSdkVersion 28 useLibrary 'org.apache.http.legacy' defaultConfig { applicationId "frogermcs.io.githubclient" minSdkVersion 15 - targetSdkVersion 23 + targetSdkVersion 28 versionCode 1 versionName "1.0" @@ -22,38 +20,52 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + lintOptions { + warning 'InvalidPackage' + } } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:appcompat-v7:23.1.1' + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'com.android.support:support-compat:28.0.0' + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support:recyclerview-v7:28.0.0' //Dagger 2 - compile 'com.google.dagger:dagger:2.1' - compile 'com.google.dagger:dagger-producers:2.1' - apt 'com.google.dagger:dagger-compiler:2.1' - - compile 'com.jakewharton:butterknife:7.0.1' - compile 'com.jakewharton.timber:timber:4.1.0' - compile 'io.reactivex:rxandroid:1.1.0' - compile 'io.reactivex:rxjava:1.1.0' - compile 'com.jakewharton.rxbinding:rxbinding:0.3.0' - compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4' - compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0-beta4' - compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4' - compile 'com.squareup.okhttp3:okhttp:3.2.0' - compile 'com.squareup.okhttp3:logging-interceptor:3.2.0' - compile 'com.google.guava:guava:18.0' - - testCompile "org.robolectric:robolectric:3.0" - testCompile "org.mockito:mockito-core:1.10.19" - - androidTestCompile 'com.android.support:support-annotations:23.1.1' - androidTestCompile 'junit:junit:4.12' - androidTestCompile 'com.android.support.test:runner:0.4' - androidTestCompile 'com.android.support.test:rules:0.4' - androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1' - androidTestCompile "org.mockito:mockito-core:1.10.19" - androidTestCompile "com.google.dexmaker:dexmaker:1.2" - androidTestCompile "com.google.dexmaker:dexmaker-mockito:1.2" + implementation 'com.google.dagger:dagger:2.14.1' + implementation 'com.google.dagger:dagger-producers:2.14.1' + annotationProcessor 'com.google.dagger:dagger-compiler:2.14.1' + provided 'org.glassfish:javax.annotation:10.0-b28' + implementation 'com.google.auto.factory:auto-factory:1.0-beta3' + annotationProcessor 'com.google.auto.factory:auto-factory:1.0-beta3' + + implementation 'com.jakewharton:butterknife:8.8.1' + annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' + implementation 'com.jakewharton.timber:timber:4.3.1' + implementation 'io.reactivex:rxandroid:1.2.1' + implementation 'io.reactivex:rxjava:1.2.1' + implementation 'com.jakewharton.rxbinding:rxbinding:0.4.0' + implementation 'com.squareup.retrofit2:retrofit:2.1.0' + implementation 'com.squareup.retrofit2:adapter-rxjava:2.1.0' + implementation 'com.squareup.retrofit2:converter-gson:2.1.0' + implementation 'com.squareup.okhttp3:okhttp:3.4.1' + implementation 'com.squareup.okhttp3:logging-interceptor:3.4.1' + implementation 'com.google.guava:guava:23.4-android' + implementation 'com.google.code.findbugs:jsr305:2.0.1' + + testImplementation "org.robolectric:robolectric:3.1.2" + testImplementation "org.mockito:mockito-core:1.10.19" + testImplementation 'junit:junit:4.12' + + androidTestImplementation 'com.android.support:support-annotations:25.0.0' + androidTestImplementation 'com.squareup:javawriter:2.5.1' + + androidTestImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:0.5' + androidTestImplementation 'com.android.support.test:rules:0.5' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:2.2.2' + androidTestImplementation "org.mockito:mockito-core:1.10.19" + androidTestImplementation "com.google.dexmaker:dexmaker:1.2" + androidTestImplementation "com.google.dexmaker:dexmaker-mockito:1.2" + testAnnotationProcessor "com.google.auto.factory:auto-factory:1.0-beta3" } diff --git a/app/src/androidTest/java/frogermcs/io/githubclient/inject/ApplicationMock.java b/app/src/androidTest/java/frogermcs/io/githubclient/inject/ApplicationMock.java index 73e8dc0..0533059 100644 --- a/app/src/androidTest/java/frogermcs/io/githubclient/inject/ApplicationMock.java +++ b/app/src/androidTest/java/frogermcs/io/githubclient/inject/ApplicationMock.java @@ -4,6 +4,7 @@ import frogermcs.io.githubclient.AppModule; import frogermcs.io.githubclient.DaggerAppComponent; import frogermcs.io.githubclient.GithubClientApplication; +import frogermcs.io.githubclient.data.api.GithubApiModule; /** * Created by Miroslaw Stanek on 24.09.15. diff --git a/app/src/androidTest/java/frogermcs/io/githubclient/inject/GithubApiModuleMock.java b/app/src/androidTest/java/frogermcs/io/githubclient/inject/GithubApiModuleMock.java index 3b2b13a..cf86071 100644 --- a/app/src/androidTest/java/frogermcs/io/githubclient/inject/GithubApiModuleMock.java +++ b/app/src/androidTest/java/frogermcs/io/githubclient/inject/GithubApiModuleMock.java @@ -1,12 +1,13 @@ package frogermcs.io.githubclient.inject; +import frogermcs.io.githubclient.data.api.GithubApiModule; import frogermcs.io.githubclient.data.api.GithubApiService; import frogermcs.io.githubclient.data.api.UserManager; /** * Created by Miroslaw Stanek on 23.09.15. */ -public class GithubApiModuleMock { +public class GithubApiModuleMock extends GithubApiModule { private UserManager userManagerMock; diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 34f4d66..56bae07 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -14,9 +14,7 @@ android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme"> - <activity - android:name=".ui.activity.SplashActivity" - android:windowSoftInputMode="stateHidden"> + <activity android:name=".ui.activity.SplashActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> diff --git a/app/src/main/java/frogermcs/io/githubclient/AppComponent.java b/app/src/main/java/frogermcs/io/githubclient/AppComponent.java index 1f262e5..0abd9dc 100644 --- a/app/src/main/java/frogermcs/io/githubclient/AppComponent.java +++ b/app/src/main/java/frogermcs/io/githubclient/AppComponent.java @@ -1,10 +1,9 @@ package frogermcs.io.githubclient; -import android.app.Application; - import javax.inject.Singleton; import dagger.Component; +import frogermcs.io.githubclient.data.api.GithubApiModule; import frogermcs.io.githubclient.data.UserComponent; import frogermcs.io.githubclient.data.api.UserModule; import frogermcs.io.githubclient.ui.activity.component.SplashActivityComponent; @@ -16,7 +15,8 @@ @Singleton @Component( modules = { - AppModule.class + AppModule.class, + GithubApiModule.class } ) public interface AppComponent { @@ -25,5 +25,4 @@ public interface AppComponent { UserComponent plus(UserModule userModule); - Application application(); } \ No newline at end of file diff --git a/app/src/main/java/frogermcs/io/githubclient/AppProductionComponent.java b/app/src/main/java/frogermcs/io/githubclient/AppProductionComponent.java deleted file mode 100644 index ed55ec6..0000000 --- a/app/src/main/java/frogermcs/io/githubclient/AppProductionComponent.java +++ /dev/null @@ -1,20 +0,0 @@ -package frogermcs.io.githubclient; - -import com.google.common.util.concurrent.ListenableFuture; - -import dagger.producers.ProductionComponent; -import frogermcs.io.githubclient.data.api.UserManager; -import frogermcs.io.githubclient.data.api.UserModule; - -/** - * Created by Miroslaw Stanek on 05.03.2016. - */ -@ProductionComponent( - dependencies = AppComponent.class, - modules = GithubApiProducerModule.class -) -public interface AppProductionComponent { - ListenableFuture<UserManager> userManager(); - - ListenableFuture<UserModule.Factory> userModuleFactory(); -} \ No newline at end of file diff --git a/app/src/main/java/frogermcs/io/githubclient/ExecutorModule.java b/app/src/main/java/frogermcs/io/githubclient/ExecutorModule.java new file mode 100644 index 0000000..df4dd2a --- /dev/null +++ b/app/src/main/java/frogermcs/io/githubclient/ExecutorModule.java @@ -0,0 +1,21 @@ +package frogermcs.io.githubclient; + +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + +import dagger.Module; +import dagger.Provides; +import dagger.producers.Production; + +/** + * Created by froger_mcs on 12/02/2018. + */ + +@Module +final class ExecutorModule { + @Provides + @Production + static Executor executor() { + return Executors.newSingleThreadExecutor(); + } +} diff --git a/app/src/main/java/frogermcs/io/githubclient/GithubClientApplication.java b/app/src/main/java/frogermcs/io/githubclient/GithubClientApplication.java index 2a77974..aaec8a6 100644 --- a/app/src/main/java/frogermcs/io/githubclient/GithubClientApplication.java +++ b/app/src/main/java/frogermcs/io/githubclient/GithubClientApplication.java @@ -5,20 +5,18 @@ import com.frogermcs.androiddevmetrics.AndroidDevMetrics; -import java.util.concurrent.Executors; - import frogermcs.io.githubclient.data.UserComponent; import frogermcs.io.githubclient.data.api.UserModule; +import frogermcs.io.githubclient.data.model.User; import timber.log.Timber; /** * Created by Miroslaw Stanek on 22.04.15. */ -public class GithubClientApplication extends Application { + public class GithubClientApplication extends Application { private AppComponent appComponent; private UserComponent userComponent; - private AppProductionComponent appProductionComponent; public static GithubClientApplication get(Context context) { return (GithubClientApplication) context.getApplicationContext(); @@ -39,16 +37,10 @@ private void initAppComponent() { appComponent = DaggerAppComponent.builder() .appModule(new AppModule(this)) .build(); - - - appProductionComponent = DaggerAppProductionComponent.builder() - .executor(Executors.newSingleThreadExecutor()) - .appComponent(appComponent) - .build(); } - public UserComponent createUserComponent(UserModule userModule) { - userComponent = appComponent.plus(userModule); + public UserComponent createUserComponent(User user) { + userComponent = appComponent.plus(new UserModule(user)); return userComponent; } @@ -64,8 +56,4 @@ public UserComponent getUserComponent() { return userComponent; } - public AppProductionComponent getAppProductionComponent() { - return appProductionComponent; - } - } \ No newline at end of file diff --git a/app/src/main/java/frogermcs/io/githubclient/GithubApiProducerModule.java b/app/src/main/java/frogermcs/io/githubclient/data/api/GithubApiModule.java similarity index 60% rename from app/src/main/java/frogermcs/io/githubclient/GithubApiProducerModule.java rename to app/src/main/java/frogermcs/io/githubclient/data/api/GithubApiModule.java index 7a4098a..668882b 100644 --- a/app/src/main/java/frogermcs/io/githubclient/GithubApiProducerModule.java +++ b/app/src/main/java/frogermcs/io/githubclient/data/api/GithubApiModule.java @@ -1,14 +1,15 @@ -package frogermcs.io.githubclient; +package frogermcs.io.githubclient.data.api; import android.app.Application; import java.util.concurrent.TimeUnit; -import dagger.producers.ProducerModule; -import dagger.producers.Produces; -import frogermcs.io.githubclient.data.api.GithubApiService; -import frogermcs.io.githubclient.data.api.UserManager; -import frogermcs.io.githubclient.data.api.UserModule; +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; +import frogermcs.io.githubclient.BuildConfig; +import frogermcs.io.githubclient.R; import okhttp3.OkHttpClient; import okhttp3.logging.HttpLoggingInterceptor; import retrofit2.Retrofit; @@ -16,14 +17,16 @@ import retrofit2.converter.gson.GsonConverterFactory; /** - * Created by Miroslaw Stanek on 05.03.2016. + * Created by Miroslaw Stanek on 22.04.15. */ -@ProducerModule -public class GithubApiProducerModule { +@Module +public class GithubApiModule { - @Produces - public OkHttpClient produceOkHttpClient() { + @Provides + @Singleton + public OkHttpClient provideOkHttpClient() { final OkHttpClient.Builder builder = new OkHttpClient.Builder(); + if (BuildConfig.DEBUG) { HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); logging.setLevel(HttpLoggingInterceptor.Level.BODY); @@ -36,8 +39,9 @@ public OkHttpClient produceOkHttpClient() { return builder.build(); } - @Produces - public Retrofit produceRestAdapter(Application application, OkHttpClient okHttpClient) { + @Provides + @Singleton + public Retrofit provideRestAdapter(Application application, OkHttpClient okHttpClient) { Retrofit.Builder builder = new Retrofit.Builder(); builder.client(okHttpClient) .baseUrl(application.getString(R.string.endpoint)) @@ -46,18 +50,15 @@ public Retrofit produceRestAdapter(Application application, OkHttpClient okHttpC return builder.build(); } - @Produces - public GithubApiService produceGithubApiService(Retrofit restAdapter) { + @Provides + @Singleton + public GithubApiService provideGithubApiService(Retrofit restAdapter) { return restAdapter.create(GithubApiService.class); } - @Produces - public UserManager produceUserManager(GithubApiService githubApiService) { + @Provides + @Singleton + public UserManager provideUserManager(GithubApiService githubApiService) { return new UserManager(githubApiService); } - - @Produces - public UserModule.Factory produceUserModuleFactory(GithubApiService githubApiService) { - return new UserModule.Factory(githubApiService); - } } diff --git a/app/src/main/java/frogermcs/io/githubclient/data/api/RepositoriesManager.java b/app/src/main/java/frogermcs/io/githubclient/data/api/RepositoriesManager.java index cbcbb02..778a2d1 100644 --- a/app/src/main/java/frogermcs/io/githubclient/data/api/RepositoriesManager.java +++ b/app/src/main/java/frogermcs/io/githubclient/data/api/RepositoriesManager.java @@ -35,6 +35,8 @@ public ImmutableList<Repository> call(List<RepositoryResponse> repositoriesListR repository.id = repositoryResponse.id; repository.name = repositoryResponse.name; repository.url = repositoryResponse.url; + repository.stargazers_count = repositoryResponse.stargazers_count; + repository.forks_count = repositoryResponse.forks_count; listBuilder.add(repository); } return listBuilder.build(); diff --git a/app/src/main/java/frogermcs/io/githubclient/data/api/UserModule.java b/app/src/main/java/frogermcs/io/githubclient/data/api/UserModule.java index 443d5eb..c1b726b 100644 --- a/app/src/main/java/frogermcs/io/githubclient/data/api/UserModule.java +++ b/app/src/main/java/frogermcs/io/githubclient/data/api/UserModule.java @@ -12,11 +12,9 @@ public class UserModule { private User user; - private GithubApiService githubApiService; - private UserModule(User user, GithubApiService githubApiService) { + public UserModule(User user) { this.user = user; - this.githubApiService = githubApiService; } @Provides @@ -27,19 +25,7 @@ User provideUser() { @Provides @UserScope - RepositoriesManager provideRepositoriesManager() { + RepositoriesManager provideRepositoriesManager(User user, GithubApiService githubApiService) { return new RepositoriesManager(user, githubApiService); } - - public static class Factory { - private GithubApiService githubApiService; - - public Factory(GithubApiService githubApiService) { - this.githubApiService = githubApiService; - } - - public UserModule create(User user) { - return new UserModule(user, githubApiService); - } - } } diff --git a/app/src/main/java/frogermcs/io/githubclient/data/model/Repository.java b/app/src/main/java/frogermcs/io/githubclient/data/model/Repository.java index e1c0a13..e6c078a 100644 --- a/app/src/main/java/frogermcs/io/githubclient/data/model/Repository.java +++ b/app/src/main/java/frogermcs/io/githubclient/data/model/Repository.java @@ -7,6 +7,10 @@ * Created by Miroslaw Stanek on 22.04.15. */ public class Repository implements Parcelable { + public static final int TYPE_NORMAL = 0; + public static final int TYPE_BIG = 1; + public static final int TYPE_FEATURED = 2; + public static final Parcelable.Creator<Repository> CREATOR = new Parcelable.Creator<Repository>() { public Repository createFromParcel(Parcel source) { return new Repository(source); @@ -19,6 +23,8 @@ public Repository[] newArray(int size) { public long id; public String name; public String url; + public int stargazers_count; + public int forks_count; public Repository() { } @@ -27,6 +33,8 @@ private Repository(Parcel in) { this.id = in.readLong(); this.name = in.readString(); this.url = in.readString(); + this.stargazers_count = in.readInt(); + this.forks_count = in.readInt(); } @Override @@ -39,5 +47,7 @@ public void writeToParcel(Parcel dest, int flags) { dest.writeLong(this.id); dest.writeString(this.name); dest.writeString(this.url); + dest.writeInt(this.stargazers_count); + dest.writeInt(this.forks_count); } } diff --git a/app/src/main/java/frogermcs/io/githubclient/ui/activity/BaseActivity.java b/app/src/main/java/frogermcs/io/githubclient/ui/activity/BaseActivity.java index d3a2d41..b00bc17 100644 --- a/app/src/main/java/frogermcs/io/githubclient/ui/activity/BaseActivity.java +++ b/app/src/main/java/frogermcs/io/githubclient/ui/activity/BaseActivity.java @@ -4,7 +4,6 @@ import android.support.v7.app.AppCompatActivity; import frogermcs.io.githubclient.AppComponent; -import frogermcs.io.githubclient.AppProductionComponent; import frogermcs.io.githubclient.GithubClientApplication; /** @@ -19,8 +18,4 @@ protected void onCreate(Bundle savedInstanceState) { } protected abstract void setupActivityComponent(); - - public AppProductionComponent getAppProductionComponent() { - return GithubClientApplication.get(this).getAppProductionComponent(); - } } \ No newline at end of file diff --git a/app/src/main/java/frogermcs/io/githubclient/ui/activity/RepositoriesListActivity.java b/app/src/main/java/frogermcs/io/githubclient/ui/activity/RepositoriesListActivity.java index a6893ef..05c4fb3 100644 --- a/app/src/main/java/frogermcs/io/githubclient/ui/activity/RepositoriesListActivity.java +++ b/app/src/main/java/frogermcs/io/githubclient/ui/activity/RepositoriesListActivity.java @@ -1,50 +1,50 @@ package frogermcs.io.githubclient.ui.activity; import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.view.View; -import android.widget.ListView; import android.widget.ProgressBar; import com.google.common.collect.ImmutableList; -import java.util.ArrayList; - import javax.inject.Inject; -import butterknife.Bind; +import butterknife.BindView; import butterknife.ButterKnife; -import butterknife.OnItemClick; import frogermcs.io.githubclient.GithubClientApplication; import frogermcs.io.githubclient.R; import frogermcs.io.githubclient.data.model.Repository; import frogermcs.io.githubclient.ui.activity.module.RepositoriesListActivityModule; import frogermcs.io.githubclient.ui.activity.presenter.RepositoriesListActivityPresenter; import frogermcs.io.githubclient.ui.adapter.RepositoriesListAdapter; -import frogermcs.io.githubclient.utils.AnalyticsManager; public class RepositoriesListActivity extends BaseActivity { - @Bind(R.id.lvRepositories) - ListView lvRepositories; - @Bind(R.id.pbLoading) + @BindView(R.id.rvRepositories) + RecyclerView rvRepositories; + @BindView(R.id.pbLoading) ProgressBar pbLoading; @Inject RepositoriesListActivityPresenter presenter; @Inject - AnalyticsManager analyticsManager; - - private RepositoriesListAdapter repositoriesListAdapter; + RepositoriesListAdapter repositoriesListAdapter; + @Inject + LinearLayoutManager linearLayoutManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_repositories_list); ButterKnife.bind(this); + setupRepositoriesListView(); presenter.loadRepositories(); + } - repositoriesListAdapter = new RepositoriesListAdapter(this, new ArrayList<Repository>()); - lvRepositories.setAdapter(repositoriesListAdapter); + private void setupRepositoriesListView() { + rvRepositories.setAdapter(repositoriesListAdapter); + rvRepositories.setLayoutManager(linearLayoutManager); } @Override @@ -55,18 +55,15 @@ protected void setupActivityComponent() { } public void showLoading(boolean loading) { - lvRepositories.setVisibility(loading ? View.GONE : View.VISIBLE); + rvRepositories.setVisibility(loading ? View.GONE : View.VISIBLE); pbLoading.setVisibility(loading ? View.VISIBLE : View.GONE); } public void setRepositories(ImmutableList<Repository> repositories) { - repositoriesListAdapter.clear(); - repositoriesListAdapter.addAll(repositories); + repositoriesListAdapter.updateRepositoriesList(repositories); } - @OnItemClick(R.id.lvRepositories) - public void onRepositoryClick(int position) { - Repository repository = repositoriesListAdapter.getItem(position); + public void onRepositoryClick(Repository repository) { RepositoryDetailsActivity.startWithRepository(repository, this); } diff --git a/app/src/main/java/frogermcs/io/githubclient/ui/activity/RepositoryDetailsActivity.java b/app/src/main/java/frogermcs/io/githubclient/ui/activity/RepositoryDetailsActivity.java index 0e5b460..4989abd 100644 --- a/app/src/main/java/frogermcs/io/githubclient/ui/activity/RepositoryDetailsActivity.java +++ b/app/src/main/java/frogermcs/io/githubclient/ui/activity/RepositoryDetailsActivity.java @@ -7,7 +7,7 @@ import javax.inject.Inject; -import butterknife.Bind; +import butterknife.BindView; import butterknife.ButterKnife; import frogermcs.io.githubclient.GithubClientApplication; import frogermcs.io.githubclient.R; @@ -20,11 +20,11 @@ public class RepositoryDetailsActivity extends BaseActivity { private static final String ARG_REPOSITORY = "arg_repository"; - @Bind(R.id.tvRepoName) + @BindView(R.id.tvRepoName) TextView tvRepoName; - @Bind(R.id.tvRepoDetails) + @BindView(R.id.tvRepoDetails) TextView tvRepoDetails; - @Bind(R.id.tvUserName) + @BindView(R.id.tvUserName) TextView tvUserName; @Inject diff --git a/app/src/main/java/frogermcs/io/githubclient/ui/activity/SplashActivity.java b/app/src/main/java/frogermcs/io/githubclient/ui/activity/SplashActivity.java index aa4e51b..e5bbebe 100644 --- a/app/src/main/java/frogermcs/io/githubclient/ui/activity/SplashActivity.java +++ b/app/src/main/java/frogermcs/io/githubclient/ui/activity/SplashActivity.java @@ -2,6 +2,7 @@ import android.content.Intent; import android.os.Bundle; +import android.os.Debug; import android.view.View; import android.widget.Button; import android.widget.EditText; @@ -12,11 +13,12 @@ import javax.inject.Inject; -import butterknife.Bind; +import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; import frogermcs.io.githubclient.GithubClientApplication; import frogermcs.io.githubclient.R; +import frogermcs.io.githubclient.data.model.User; import frogermcs.io.githubclient.ui.activity.module.SplashActivityModule; import frogermcs.io.githubclient.ui.activity.presenter.SplashActivityPresenter; import frogermcs.io.githubclient.utils.AnalyticsManager; @@ -26,11 +28,11 @@ public class SplashActivity extends BaseActivity { - @Bind(R.id.etUsername) + @BindView(R.id.etUsername) EditText etUsername; - @Bind(R.id.pbLoading) + @BindView(R.id.pbLoading) ProgressBar pbLoading; - @Bind(R.id.btnShowRepositories) + @BindView(R.id.btnShowRepositories) Button btnShowRepositories; //These references will be satisfied by 'SplashActivityComponent.inject(this)' method @@ -67,7 +69,7 @@ protected void onDestroy() { //Local dependencies graph is constructed here @Override protected void setupActivityComponent() { - //Uncomment those lines to measure dependencies creation time + //Uncomment those lines do measure dependencies creation time //Debug.startMethodTracing("SplashTrace"); GithubClientApplication.get(this) .getAppComponent() @@ -81,7 +83,8 @@ public void onShowRepositoriesClick() { presenter.onShowRepositoriesClick(); } - public void showRepositoriesListForUser() { + public void showRepositoriesListForUser(User user) { + GithubClientApplication.get(this).createUserComponent(user); startActivity(new Intent(this, RepositoriesListActivity.class)); } diff --git a/app/src/main/java/frogermcs/io/githubclient/ui/activity/module/RepositoriesListActivityModule.java b/app/src/main/java/frogermcs/io/githubclient/ui/activity/module/RepositoriesListActivityModule.java index 83d463c..cc3a144 100644 --- a/app/src/main/java/frogermcs/io/githubclient/ui/activity/module/RepositoriesListActivityModule.java +++ b/app/src/main/java/frogermcs/io/githubclient/ui/activity/module/RepositoriesListActivityModule.java @@ -1,12 +1,23 @@ package frogermcs.io.githubclient.ui.activity.module; +import android.support.v7.widget.LinearLayoutManager; + +import java.util.Map; + import dagger.Module; import dagger.Provides; +import dagger.multibindings.IntKey; +import dagger.multibindings.IntoMap; import frogermcs.io.githubclient.data.api.RepositoriesManager; +import frogermcs.io.githubclient.data.model.Repository; import frogermcs.io.githubclient.ui.activity.ActivityScope; import frogermcs.io.githubclient.ui.activity.RepositoriesListActivity; import frogermcs.io.githubclient.ui.activity.presenter.RepositoriesListActivityPresenter; -import frogermcs.io.githubclient.utils.AnalyticsManager; +import frogermcs.io.githubclient.ui.adapter.RepositoriesListAdapter; +import frogermcs.io.githubclient.ui.adapter.viewholder.RepositoriesListViewHolderFactory; +import frogermcs.io.githubclient.ui.adapter.viewholder.RepositoryViewHolderBigFactory; +import frogermcs.io.githubclient.ui.adapter.viewholder.RepositoryViewHolderFeaturedFactory; +import frogermcs.io.githubclient.ui.adapter.viewholder.RepositoryViewHolderNormalFactory; /** * Created by Miroslaw Stanek on 23.04.15. @@ -30,4 +41,38 @@ RepositoriesListActivity provideRepositoriesListActivity() { RepositoriesListActivityPresenter provideRepositoriesListActivityPresenter(RepositoriesManager repositoriesManager) { return new RepositoriesListActivityPresenter(repositoriesListActivity, repositoriesManager); } + + @Provides + @ActivityScope + RepositoriesListAdapter provideRepositoriesListAdapter(RepositoriesListActivity repositoriesListActivity, + Map<Integer, RepositoriesListViewHolderFactory> viewHolderFactories) { + return new RepositoriesListAdapter(repositoriesListActivity, viewHolderFactories); + } + + @Provides + @ActivityScope + LinearLayoutManager provideLinearLayoutManager(RepositoriesListActivity repositoriesListActivity) { + return new LinearLayoutManager(repositoriesListActivity); + } + + @Provides + @IntoMap + @IntKey(Repository.TYPE_NORMAL) + RepositoriesListViewHolderFactory provideViewHolderNormal() { + return new RepositoryViewHolderNormalFactory(); + } + + @Provides + @IntoMap + @IntKey(Repository.TYPE_BIG) + RepositoriesListViewHolderFactory provideViewHolderBig() { + return new RepositoryViewHolderBigFactory(); + } + + @Provides + @IntoMap + @IntKey(Repository.TYPE_FEATURED) + RepositoriesListViewHolderFactory provideViewHolderFeatured() { + return new RepositoryViewHolderFeaturedFactory(); + } } \ No newline at end of file diff --git a/app/src/main/java/frogermcs/io/githubclient/ui/activity/module/SplashActivityModule.java b/app/src/main/java/frogermcs/io/githubclient/ui/activity/module/SplashActivityModule.java index df8d537..94e13a4 100644 --- a/app/src/main/java/frogermcs/io/githubclient/ui/activity/module/SplashActivityModule.java +++ b/app/src/main/java/frogermcs/io/githubclient/ui/activity/module/SplashActivityModule.java @@ -2,6 +2,9 @@ import dagger.Module; import dagger.Provides; +import frogermcs.io.githubclient.HeavyExternalLibrary; +import frogermcs.io.githubclient.HeavyLibraryWrapper; +import frogermcs.io.githubclient.data.api.UserManager; import frogermcs.io.githubclient.ui.activity.ActivityScope; import frogermcs.io.githubclient.ui.activity.SplashActivity; import frogermcs.io.githubclient.ui.activity.presenter.SplashActivityPresenter; @@ -26,7 +29,8 @@ SplashActivity provideSplashActivity() { @Provides @ActivityScope - SplashActivityPresenter provideSplashActivityPresenter(Validator validator) { - return new SplashActivityPresenter(splashActivity, validator); + SplashActivityPresenter + provideSplashActivityPresenter(Validator validator, UserManager userManager, HeavyLibraryWrapper heavyLibraryWrapper) { + return new SplashActivityPresenter(splashActivity, validator, userManager, heavyLibraryWrapper); } } \ No newline at end of file diff --git a/app/src/main/java/frogermcs/io/githubclient/ui/activity/presenter/SplashActivityPresenter.java b/app/src/main/java/frogermcs/io/githubclient/ui/activity/presenter/SplashActivityPresenter.java index 8517f15..dbbf46d 100644 --- a/app/src/main/java/frogermcs/io/githubclient/ui/activity/presenter/SplashActivityPresenter.java +++ b/app/src/main/java/frogermcs/io/githubclient/ui/activity/presenter/SplashActivityPresenter.java @@ -1,18 +1,11 @@ package frogermcs.io.githubclient.ui.activity.presenter; -import com.google.common.util.concurrent.FutureCallback; -import com.google.common.util.concurrent.Futures; - -import frogermcs.io.githubclient.AppProductionComponent; -import frogermcs.io.githubclient.GithubClientApplication; +import frogermcs.io.githubclient.HeavyLibraryWrapper; import frogermcs.io.githubclient.data.api.UserManager; -import frogermcs.io.githubclient.data.api.UserModule; import frogermcs.io.githubclient.data.model.User; import frogermcs.io.githubclient.ui.activity.SplashActivity; import frogermcs.io.githubclient.utils.SimpleObserver; import frogermcs.io.githubclient.utils.Validator; -import rx.Observable; -import rx.functions.Func2; /** * Created by Miroslaw Stanek on 23.04.15. @@ -22,59 +15,39 @@ public class SplashActivityPresenter { private SplashActivity splashActivity; private Validator validator; - private AppProductionComponent appProductionComponent; - private UserManager userManager; + private HeavyLibraryWrapper heavyLibraryWrapper; - public SplashActivityPresenter(SplashActivity splashActivity, Validator validator) { + public SplashActivityPresenter(SplashActivity splashActivity, Validator validator, + UserManager userManager, HeavyLibraryWrapper heavyLibraryWrapper) { this.splashActivity = splashActivity; - this.appProductionComponent = splashActivity.getAppProductionComponent(); this.validator = validator; - Futures.addCallback(appProductionComponent.userManager(), new FutureCallback<UserManager>() { - @Override - public void onSuccess(UserManager result) { - SplashActivityPresenter.this.userManager = result; - } - - @Override - public void onFailure(Throwable t) { - - } - }); + this.userManager = userManager; + this.heavyLibraryWrapper = heavyLibraryWrapper; + + //This calls should be delivered to ExternalLibrary right after it will be initialized + this.heavyLibraryWrapper.callMethod(); + this.heavyLibraryWrapper.callMethod(); + this.heavyLibraryWrapper.callMethod(); + this.heavyLibraryWrapper.callMethod(); } public void onShowRepositoriesClick() { - if (userManager == null) { - return; - } - if (validator.validUsername(username)) { splashActivity.showLoading(true); - Observable.combineLatest( - Observable.from(appProductionComponent.userModuleFactory()), - userManager.getUser(username), - new Func2<UserModule.Factory, User, UserModule>() { - @Override - public UserModule call(UserModule.Factory factory, User user) { - return factory.create(user); - } - } - ) - .subscribe(new SimpleObserver<UserModule>() { - @Override - public void onNext(UserModule userModule) { - GithubClientApplication.get(splashActivity).createUserComponent(userModule); - - splashActivity.showLoading(false); - splashActivity.showRepositoriesListForUser(); - } - - @Override - public void onError(Throwable e) { - splashActivity.showLoading(false); - splashActivity.showValidationError(); - } - }); + userManager.getUser(username).subscribe(new SimpleObserver<User>() { + @Override + public void onNext(User user) { + splashActivity.showLoading(false); + splashActivity.showRepositoriesListForUser(user); + } + + @Override + public void onError(Throwable e) { + splashActivity.showLoading(false); + splashActivity.showValidationError(); + } + }); } else { splashActivity.showValidationError(); } diff --git a/app/src/main/java/frogermcs/io/githubclient/ui/adapter/RepositoriesListAdapter.java b/app/src/main/java/frogermcs/io/githubclient/ui/adapter/RepositoriesListAdapter.java index 7adeff3..863b43b 100644 --- a/app/src/main/java/frogermcs/io/githubclient/ui/adapter/RepositoriesListAdapter.java +++ b/app/src/main/java/frogermcs/io/githubclient/ui/adapter/RepositoriesListAdapter.java @@ -1,53 +1,75 @@ package frogermcs.io.githubclient.ui.adapter; -import android.content.Context; -import android.view.LayoutInflater; +import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.TextView; +import java.util.ArrayList; import java.util.List; +import java.util.Map; -import butterknife.Bind; -import butterknife.ButterKnife; import frogermcs.io.githubclient.data.model.Repository; +import frogermcs.io.githubclient.ui.activity.RepositoriesListActivity; +import frogermcs.io.githubclient.ui.adapter.viewholder.RepositoriesListViewHolderFactory; +import frogermcs.io.githubclient.ui.adapter.viewholder.RepositoryViewHolder; /** * Created by Miroslaw Stanek on 24.04.15. */ -public class RepositoriesListAdapter extends ArrayAdapter<Repository> { +public class RepositoriesListAdapter extends RecyclerView.Adapter { - private LayoutInflater inflater; + private RepositoriesListActivity repositoriesListActivity; + private Map<Integer, RepositoriesListViewHolderFactory> viewHolderFactories; - public RepositoriesListAdapter(Context context, List<Repository> objects) { - super(context, 0, objects); - this.inflater = LayoutInflater.from(context); + private final List<Repository> repositories = new ArrayList<>(); + + public RepositoriesListAdapter(RepositoriesListActivity repositoriesListActivity, + Map<Integer, RepositoriesListViewHolderFactory> viewHolderFactories) { + this.repositoriesListActivity = repositoriesListActivity; + this.viewHolderFactories = viewHolderFactories; } @Override - public View getView(int position, View convertView, ViewGroup parent) { - RepositoryHolder holder; - if (convertView == null) { - convertView = inflater.inflate(android.R.layout.simple_list_item_1, parent, false); - holder = new RepositoryHolder(convertView); - convertView.setTag(holder); - } else { - holder = (RepositoryHolder) convertView.getTag(); - } + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + final RecyclerView.ViewHolder viewHolder = viewHolderFactories.get(viewType).createViewHolder(parent); + viewHolder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onRepositoryItemClicked(viewHolder.getAdapterPosition()); + } + }); + return viewHolder; + } - Repository repository = getItem(position); - holder.text1.setText(repository.name); + private void onRepositoryItemClicked(int adapterPosition) { + repositoriesListActivity.onRepositoryClick(repositories.get(adapterPosition)); + } - return convertView; + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + ((RepositoryViewHolder) holder).bind(repositories.get(position)); } - static class RepositoryHolder { - @Bind(android.R.id.text1) - TextView text1; + @Override + public int getItemCount() { + return repositories.size(); + } - public RepositoryHolder(View view) { - ButterKnife.bind(this, view); + @Override + public int getItemViewType(int position) { + Repository repository = repositories.get(position); + if (repository.stargazers_count > 500) { + if (repository.forks_count > 100) { + return Repository.TYPE_FEATURED; + } + return Repository.TYPE_BIG; } + return Repository.TYPE_NORMAL; + } + + public void updateRepositoriesList(List<Repository> repositories) { + this.repositories.clear(); + this.repositories.addAll(repositories); + notifyDataSetChanged(); } } diff --git a/app/src/main/java/frogermcs/io/githubclient/ui/adapter/viewholder/RepositoriesListViewHolderFactory.java b/app/src/main/java/frogermcs/io/githubclient/ui/adapter/viewholder/RepositoriesListViewHolderFactory.java new file mode 100644 index 0000000..23e0134 --- /dev/null +++ b/app/src/main/java/frogermcs/io/githubclient/ui/adapter/viewholder/RepositoriesListViewHolderFactory.java @@ -0,0 +1,12 @@ +package frogermcs.io.githubclient.ui.adapter.viewholder; + +import android.support.v7.widget.RecyclerView; +import android.view.ViewGroup; + +/** + * Created by Miroslaw Stanek on 11.06.2016. + */ + +public interface RepositoriesListViewHolderFactory { + RecyclerView.ViewHolder createViewHolder(ViewGroup parent); +} diff --git a/app/src/main/java/frogermcs/io/githubclient/ui/adapter/viewholder/RepositoryViewHolder.java b/app/src/main/java/frogermcs/io/githubclient/ui/adapter/viewholder/RepositoryViewHolder.java new file mode 100644 index 0000000..afa86a2 --- /dev/null +++ b/app/src/main/java/frogermcs/io/githubclient/ui/adapter/viewholder/RepositoryViewHolder.java @@ -0,0 +1,18 @@ +package frogermcs.io.githubclient.ui.adapter.viewholder; + +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import frogermcs.io.githubclient.data.model.Repository; + +/** + * Created by Miroslaw Stanek on 11.06.2016. + */ + +public abstract class RepositoryViewHolder extends RecyclerView.ViewHolder { + public RepositoryViewHolder(View itemView) { + super(itemView); + } + + public abstract void bind(Repository repository); +} diff --git a/app/src/main/java/frogermcs/io/githubclient/ui/adapter/viewholder/RepositoryViewHolderBig.java b/app/src/main/java/frogermcs/io/githubclient/ui/adapter/viewholder/RepositoryViewHolderBig.java new file mode 100644 index 0000000..16e97a8 --- /dev/null +++ b/app/src/main/java/frogermcs/io/githubclient/ui/adapter/viewholder/RepositoryViewHolderBig.java @@ -0,0 +1,38 @@ +package frogermcs.io.githubclient.ui.adapter.viewholder; + +import android.view.LayoutInflater; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.google.auto.factory.AutoFactory; + +import butterknife.BindView; +import butterknife.ButterKnife; +import frogermcs.io.githubclient.R; +import frogermcs.io.githubclient.data.model.Repository; + +/** + * Created by Miroslaw Stanek on 11.06.2016. + */ +@AutoFactory(implementing = RepositoriesListViewHolderFactory.class) +public class RepositoryViewHolderBig extends RepositoryViewHolder { + + @BindView(R.id.tvName) + TextView tvName; + @BindView(R.id.tvStars) + TextView tvStars; + @BindView(R.id.tvForks) + TextView tvForks; + + public RepositoryViewHolderBig(ViewGroup parent) { + super(LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_big, parent, false)); + ButterKnife.bind(this, itemView); + } + + @Override + public void bind(Repository repository) { + tvName.setText(repository.name); + tvStars.setText("Stars: " + repository.stargazers_count); + tvForks.setText("Forks: " + repository.forks_count); + } +} diff --git a/app/src/main/java/frogermcs/io/githubclient/ui/adapter/viewholder/RepositoryViewHolderFeatured.java b/app/src/main/java/frogermcs/io/githubclient/ui/adapter/viewholder/RepositoryViewHolderFeatured.java new file mode 100644 index 0000000..ca49dc3 --- /dev/null +++ b/app/src/main/java/frogermcs/io/githubclient/ui/adapter/viewholder/RepositoryViewHolderFeatured.java @@ -0,0 +1,38 @@ +package frogermcs.io.githubclient.ui.adapter.viewholder; + +import android.view.LayoutInflater; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.google.auto.factory.AutoFactory; + +import butterknife.BindView; +import butterknife.ButterKnife; +import frogermcs.io.githubclient.R; +import frogermcs.io.githubclient.data.model.Repository; + +/** + * Created by Miroslaw Stanek on 11.06.2016. + */ +@AutoFactory(implementing = RepositoriesListViewHolderFactory.class) +public class RepositoryViewHolderFeatured extends RepositoryViewHolder { + + @BindView(R.id.tvName) + TextView tvName; + @BindView(R.id.tvStars) + TextView tvStars; + @BindView(R.id.tvForks) + TextView tvForks; + + public RepositoryViewHolderFeatured(ViewGroup parent) { + super(LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_featured, parent, false)); + ButterKnife.bind(this, itemView); + } + + @Override + public void bind(Repository repository) { + tvName.setText(repository.name); + tvStars.setText("Stars: " + repository.stargazers_count); + tvForks.setText("Forks: " + repository.forks_count); + } +} diff --git a/app/src/main/java/frogermcs/io/githubclient/ui/adapter/viewholder/RepositoryViewHolderNormal.java b/app/src/main/java/frogermcs/io/githubclient/ui/adapter/viewholder/RepositoryViewHolderNormal.java new file mode 100644 index 0000000..3176f4d --- /dev/null +++ b/app/src/main/java/frogermcs/io/githubclient/ui/adapter/viewholder/RepositoryViewHolderNormal.java @@ -0,0 +1,32 @@ +package frogermcs.io.githubclient.ui.adapter.viewholder; + +import android.view.LayoutInflater; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.google.auto.factory.AutoFactory; + +import butterknife.BindView; +import butterknife.ButterKnife; +import frogermcs.io.githubclient.R; +import frogermcs.io.githubclient.data.model.Repository; + +/** + * Created by Miroslaw Stanek on 11.06.2016. + */ +@AutoFactory(implementing = RepositoriesListViewHolderFactory.class) +public class RepositoryViewHolderNormal extends RepositoryViewHolder { + + @BindView(R.id.tvName) + TextView tvName; + + public RepositoryViewHolderNormal(ViewGroup parent) { + super(LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_normal, parent, false)); + ButterKnife.bind(this, itemView); + } + + @Override + public void bind(Repository repository) { + tvName.setText(repository.name); + } +} diff --git a/app/src/main/res/layout/activity_repositories_list.xml b/app/src/main/res/layout/activity_repositories_list.xml index b65dc57..ead0907 100644 --- a/app/src/main/res/layout/activity_repositories_list.xml +++ b/app/src/main/res/layout/activity_repositories_list.xml @@ -3,10 +3,11 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" - tools:context="frogermcs.io.githubclient.ui.activity.RepositoriesListActivity"> + tools:context="frogermcs.io.githubclient.ui.activity.RepositoriesListActivity" + android:orientation="vertical"> - <ListView - android:id="@+id/lvRepositories" + <android.support.v7.widget.RecyclerView + android:id="@+id/rvRepositories" android:layout_width="match_parent" android:layout_height="match_parent" /> diff --git a/app/src/main/res/layout/list_item_big.xml b/app/src/main/res/layout/list_item_big.xml new file mode 100644 index 0000000..e32243d --- /dev/null +++ b/app/src/main/res/layout/list_item_big.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="16dp"> + + <TextView + android:id="@+id/tvName" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="8dp" + android:text="Lorem ipsum dolor" + android:textSize="16sp" + android:textStyle="bold" /> + + <TextView + android:id="@+id/tvStars" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Stars: 123" + android:textSize="13sp" /> + + <TextView + android:id="@+id/tvForks" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Forks: 123" + android:textSize="13sp" /> +</LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/list_item_featured.xml b/app/src/main/res/layout/list_item_featured.xml new file mode 100644 index 0000000..77707f8 --- /dev/null +++ b/app/src/main/res/layout/list_item_featured.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="#FF9800" + android:orientation="vertical" + android:padding="16dp"> + + <TextView + android:id="@+id/tvName" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="8dp" + android:text="Lorem ipsum dolor" + android:textColor="#ffffff" + android:textSize="16sp" + android:textStyle="bold" /> + + <TextView + android:id="@+id/tvStars" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Stars: 123" + android:textColor="#ffffff" + android:textSize="13sp" /> + + <TextView + android:id="@+id/tvForks" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Forks: 123" + android:textColor="#ffffff" + android:textSize="13sp" /> +</LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/list_item_normal.xml b/app/src/main/res/layout/list_item_normal.xml new file mode 100644 index 0000000..980ad24 --- /dev/null +++ b/app/src/main/res/layout/list_item_normal.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <TextView + android:id="@+id/tvName" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:padding="16dp" + android:textSize="16sp" + android:text="Lorem ipsum dolor" /> +</LinearLayout> \ No newline at end of file diff --git a/app/src/test/java/frogermcs/io/githubclient/ui/activity/SplashActivityTests.java b/app/src/test/java/frogermcs/io/githubclient/ui/activity/SplashActivityTests.java index 6275603..0df4abf 100644 --- a/app/src/test/java/frogermcs/io/githubclient/ui/activity/SplashActivityTests.java +++ b/app/src/test/java/frogermcs/io/githubclient/ui/activity/SplashActivityTests.java @@ -1,7 +1,5 @@ package frogermcs.io.githubclient.ui.activity; -import android.support.annotation.NonNull; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -10,16 +8,13 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.robolectric.Robolectric; -import org.robolectric.RobolectricGradleTestRunner; +import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import frogermcs.io.githubclient.BuildConfig; -import frogermcs.io.githubclient.MockAppModule; import frogermcs.io.githubclient.TestGithubClientApplication; import frogermcs.io.githubclient.ui.activity.component.SplashActivityComponent; -import frogermcs.io.githubclient.ui.activity.module.MockSplashActivityModule; -import frogermcs.io.githubclient.ui.activity.module.SplashActivityModule; import frogermcs.io.githubclient.utils.AnalyticsManager; import static org.mockito.Matchers.any; @@ -30,7 +25,7 @@ /** * Created by Miroslaw Stanek on 19.09.15. */ -@RunWith(RobolectricGradleTestRunner.class) +@RunWith(RobolectricTestRunner.class) @Config( sdk = 18, constants = BuildConfig.class, diff --git a/build.gradle b/build.gradle index 6678105..3a627ad 100644 --- a/build.gradle +++ b/build.gradle @@ -1,24 +1,17 @@ buildscript { repositories { jcenter() - mavenCentral() - maven { - url "https://oss.sonatype.org/content/repositories/snapshots" - } + google() } dependencies { - classpath 'com.android.tools.build:gradle:2.0.0-beta5' - classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' - classpath 'com.frogermcs.androiddevmetrics:androiddevmetrics-plugin:0.4' + classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.frogermcs.androiddevmetrics:androiddevmetrics-plugin:0.7' } } allprojects { repositories { jcenter() - mavenCentral() - maven { - url "https://oss.sonatype.org/content/repositories/snapshots" - } + google() } } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 8c0fb64..c44b679 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index fcef1f7..f16d266 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Wed Apr 10 15:27:10 PDT 2013 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https://services.gradle.org/distributions/gradle-2.10-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-bin.zip diff --git a/gradlew b/gradlew index 91a7e26..cccdd3d 100755 --- a/gradlew +++ b/gradlew @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh ############################################################################## ## @@ -6,20 +6,38 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -30,6 +48,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,31 +59,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -90,7 +89,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -114,6 +113,7 @@ fi if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` @@ -154,11 +154,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index aec9973..e95643d 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -8,14 +8,14 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome @@ -46,10 +46,9 @@ echo location of your Java installation. goto fail :init -@rem Get command-line arguments, handling Windowz variants +@rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. @@ -60,11 +59,6 @@ set _SKIP=2 if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ :execute @rem Setup the command line