├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── drawable-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── drawable-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── drawable-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── drawable-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── values
│ │ │ │ ├── styles.xml
│ │ │ │ ├── dimens.xml
│ │ │ │ └── strings.xml
│ │ │ ├── xml
│ │ │ │ └── appwidget_info.xml
│ │ │ ├── layout
│ │ │ │ ├── activity_main.xml
│ │ │ │ ├── widget_layout.xml
│ │ │ │ ├── repository_fragment.xml
│ │ │ │ └── repositories_fragment.xml
│ │ │ ├── values-w820dp
│ │ │ │ └── dimens.xml
│ │ │ └── menu
│ │ │ │ └── main.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── tehmou
│ │ │ │ └── rxbookapp
│ │ │ │ ├── pojo
│ │ │ │ ├── UserSettings.java
│ │ │ │ ├── GitHubRepositorySearch.java
│ │ │ │ └── GitHubRepository.java
│ │ │ │ ├── data
│ │ │ │ ├── provider
│ │ │ │ │ ├── DatabaseContract.java
│ │ │ │ │ ├── GithubContentProvider.java
│ │ │ │ │ ├── SerializedJsonContract.java
│ │ │ │ │ ├── UserSettingsContract.java
│ │ │ │ │ ├── GitHubRepositoryContract.java
│ │ │ │ │ ├── GitHubRepositorySearchContract.java
│ │ │ │ │ ├── ContractContentProviderBase.java
│ │ │ │ │ └── ContentProviderBase.java
│ │ │ │ ├── GitHubRepositoryStore.java
│ │ │ │ ├── GitHubRepositorySearchStore.java
│ │ │ │ ├── UserSettingsStore.java
│ │ │ │ ├── DataStoreModule.java
│ │ │ │ ├── HashStoreBase.java
│ │ │ │ ├── ContentProviderStoreBase.java
│ │ │ │ └── DataLayer.java
│ │ │ │ ├── network
│ │ │ │ ├── GitHubRepositorySearchResults.java
│ │ │ │ ├── GitHubService.java
│ │ │ │ └── NetworkApi.java
│ │ │ │ ├── RxBookApp.java
│ │ │ │ ├── Graph.java
│ │ │ │ ├── widget
│ │ │ │ ├── WidgetProvider.java
│ │ │ │ ├── WidgetRemoteViewFactory.java
│ │ │ │ └── WidgetService.java
│ │ │ │ ├── utils
│ │ │ │ ├── SubscriptionUtils.java
│ │ │ │ ├── TextWatcherObservable.java
│ │ │ │ └── RxBinderUtil.java
│ │ │ │ ├── viewmodels
│ │ │ │ ├── AbstractViewModel.java
│ │ │ │ ├── RepositoryViewModel.java
│ │ │ │ └── RepositoriesViewModel.java
│ │ │ │ ├── view
│ │ │ │ ├── RepositoryView.java
│ │ │ │ └── RepositoriesView.java
│ │ │ │ ├── activities
│ │ │ │ ├── ChooseRepositoryActivity.java
│ │ │ │ └── MainActivity.java
│ │ │ │ └── fragments
│ │ │ │ ├── RepositoryFragment.java
│ │ │ │ └── RepositoriesFragment.java
│ │ └── AndroidManifest.xml
│ └── test
│ │ └── java
│ │ └── com
│ │ └── tehmou
│ │ └── rxbookapp
│ │ ├── utils
│ │ ├── SubscriptionUtilsTest.java
│ │ └── RxBinderUtilTest.java
│ │ └── test
│ │ └── SubscriptionManagerTest.java
├── proguard-rules.txt
└── build.gradle
├── settings.gradle
├── .gitignore
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew.bat
├── gradlew
└── README.md
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /local.properties
3 | /.idea/workspace.xml
4 | .DS_Store
5 | build
6 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/htoooth/rx-android-architecture/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/htoooth/rx-android-architecture/HEAD/app/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/htoooth/rx-android-architecture/HEAD/app/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/htoooth/rx-android-architecture/HEAD/app/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/htoooth/rx-android-architecture/HEAD/app/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
7 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 29 18:51:17 CET 2014
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/appwidget_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/pojo/UserSettings.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.pojo;
2 |
3 | /**
4 | * Created by ttuo on 06/04/15.
5 | */
6 | public class UserSettings {
7 | private final int selectedRepositoryId;
8 |
9 | public UserSettings(int selectedRepositoryId) {
10 | this.selectedRepositoryId = selectedRepositoryId;
11 | }
12 |
13 | public int getSelectedRepositoryId() {
14 | return selectedRepositoryId;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/main.xml:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | RxBookApp
5 | Settings
6 | Add the widget to home screen to monitor a repository. Changing the repository with search will update the widget through the ContentProvider.
7 | Change
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/data/provider/DatabaseContract.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.data.provider;
2 |
3 | /**
4 | * Created by ttuo on 13/01/15.
5 | */
6 | public interface DatabaseContract {
7 | public String getName();
8 | public String getDefaultSortOrder();
9 | public String getIdColumnName();
10 | public String getIdSqlString(String id);
11 | public String getCreateTable();
12 | public String getDropTable();
13 | public String getSingleMimeType();
14 | public String getMultipleMimeType();
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/network/GitHubRepositorySearchResults.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.network;
2 |
3 | import com.tehmou.rxbookapp.pojo.GitHubRepository;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * Created by ttuo on 11/01/15.
9 | */
10 | public class GitHubRepositorySearchResults {
11 | final private List items;
12 |
13 | public GitHubRepositorySearchResults(final List items) {
14 | this.items = items;
15 | }
16 |
17 | public List getItems() {
18 | return items;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/pojo/GitHubRepositorySearch.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.pojo;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Created by ttuo on 06/01/15.
7 | */
8 | public class GitHubRepositorySearch {
9 | final private String search;
10 | final private List items;
11 |
12 | public GitHubRepositorySearch(final String search, final List items) {
13 | this.search = search;
14 | this.items = items;
15 | }
16 |
17 | public String getSearch() {
18 | return search;
19 | }
20 |
21 | public List getItems() {
22 | return items;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/network/GitHubService.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.network;
2 |
3 | import com.tehmou.rxbookapp.pojo.GitHubRepository;
4 |
5 | import java.util.Map;
6 |
7 | import retrofit.http.GET;
8 | import retrofit.http.Path;
9 | import retrofit.http.QueryMap;
10 |
11 | /**
12 | * Created by ttuo on 06/01/15.
13 | */
14 | public interface GitHubService {
15 | @GET("/search/repositories")
16 | public GitHubRepositorySearchResults search(
17 | @QueryMap Map search
18 | );
19 |
20 | @GET("/repositories/{id}")
21 | public GitHubRepository getRepository(@Path("id") Integer id);
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/RxBookApp.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp;
2 |
3 | import android.app.Application;
4 |
5 | /**
6 | * Created by pt2121 on 2/20/15.
7 | */
8 | public class RxBookApp extends Application {
9 |
10 | private static RxBookApp instance;
11 |
12 | private Graph mGraph;
13 |
14 | @Override
15 | public void onCreate() {
16 | super.onCreate();
17 | instance = this;
18 | mGraph = Graph.Initializer.init();
19 | }
20 |
21 | public static RxBookApp getInstance() {
22 | return instance;
23 | }
24 |
25 | public Graph getGraph() {
26 | return mGraph;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/proguard-rules.txt:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Applications/Android Studio.app/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the ProGuard
5 | # include property in project.properties.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Settings specified in this file will override any Gradle settings
5 | # configured through the IDE.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/data/GitHubRepositoryStore.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.data;
2 |
3 | import com.google.gson.reflect.TypeToken;
4 |
5 | import com.tehmou.rxbookapp.data.provider.GitHubRepositoryContract;
6 | import com.tehmou.rxbookapp.pojo.GitHubRepository;
7 |
8 | import android.content.ContentResolver;
9 | import android.net.Uri;
10 |
11 | /**
12 | * Created by ttuo on 07/01/15.
13 | */
14 | public class GitHubRepositoryStore extends ContentProviderStoreBase {
15 | private static final String TAG = GitHubRepositoryStore.class.getSimpleName();
16 |
17 | public GitHubRepositoryStore(ContentResolver contentResolver) {
18 | super(contentResolver, new TypeToken() {}.getType());
19 | }
20 |
21 | @Override
22 | protected Integer getIdFor(GitHubRepository item) {
23 | return item.getId();
24 | }
25 |
26 | @Override
27 | protected Uri getContentUri() {
28 | return GitHubRepositoryContract.CONTENT_URI;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/network/NetworkApi.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.network;
2 |
3 | import com.tehmou.rxbookapp.pojo.GitHubRepository;
4 |
5 | import java.util.List;
6 | import java.util.Map;
7 |
8 | import retrofit.RestAdapter;
9 |
10 | /**
11 | * Created by ttuo on 06/01/15.
12 | */
13 | public class NetworkApi {
14 | private final GitHubService gitHubService;
15 |
16 | public NetworkApi() {
17 | RestAdapter restAdapter = new RestAdapter.Builder()
18 | .setEndpoint("https://api.github.com")
19 | .setLogLevel(RestAdapter.LogLevel.NONE)
20 | .build();
21 | gitHubService = restAdapter.create(GitHubService.class);
22 | }
23 |
24 | public List search(Map search) {
25 | GitHubRepositorySearchResults results = gitHubService.search(search);
26 | return results.getItems();
27 | }
28 |
29 | public GitHubRepository getRepository(int id) {
30 | return gitHubService.getRepository(id);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/data/provider/GithubContentProvider.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.data.provider;
2 |
3 | /**
4 | * Created by ttuo on 22/03/15.
5 | */
6 | public class GithubContentProvider extends ContractContentProviderBase {
7 | public static final String PROVIDER_NAME = "com.tehmou.rxbookapp.data.provider.GithubContentProvider";
8 | private static final String DATABASE_NAME = "database";
9 | private static final int DATABASE_VERSION = 8;
10 |
11 | public GithubContentProvider() {
12 | databaseContracts.add(new GitHubRepositoryContract());
13 | databaseContracts.add(new GitHubRepositorySearchContract());
14 | databaseContracts.add(new UserSettingsContract());
15 | }
16 |
17 | @Override
18 | protected String getProviderName() {
19 | return PROVIDER_NAME;
20 | }
21 |
22 | @Override
23 | protected String getDatabaseName() {
24 | return DATABASE_NAME;
25 | }
26 |
27 | @Override
28 | protected int getDatabaseVersion() {
29 | return DATABASE_VERSION;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/Graph.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp;
2 |
3 | import com.tehmou.rxbookapp.activities.MainActivity;
4 | import com.tehmou.rxbookapp.data.DataStoreModule;
5 | import com.tehmou.rxbookapp.fragments.RepositoryFragment;
6 | import com.tehmou.rxbookapp.viewmodels.RepositoriesViewModel;
7 | import com.tehmou.rxbookapp.viewmodels.RepositoryViewModel;
8 | import com.tehmou.rxbookapp.widget.WidgetService;
9 |
10 | import javax.inject.Singleton;
11 |
12 | import dagger.Component;
13 |
14 | /**
15 | * Created by pt2121 on 2/20/15.
16 | */
17 | @Singleton
18 | @Component(modules = {DataStoreModule.class})
19 | public interface Graph {
20 |
21 | void inject(RepositoriesViewModel repositoriesViewModel);
22 | void inject(RepositoryViewModel widgetService);
23 | void inject(WidgetService widgetService);
24 | void inject(MainActivity mainActivity);
25 |
26 | public final static class Initializer {
27 |
28 | public static Graph init() {
29 | return DaggerGraph.builder()
30 | .build();
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/data/GitHubRepositorySearchStore.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.data;
2 |
3 | import com.google.gson.reflect.TypeToken;
4 |
5 | import com.tehmou.rxbookapp.data.provider.GitHubRepositorySearchContract;
6 | import com.tehmou.rxbookapp.pojo.GitHubRepositorySearch;
7 |
8 | import android.content.ContentResolver;
9 | import android.net.Uri;
10 |
11 | /**
12 | * Created by ttuo on 07/01/15.
13 | */
14 | public class GitHubRepositorySearchStore extends ContentProviderStoreBase {
15 | private static final String TAG = GitHubRepositorySearchStore.class.getSimpleName();
16 |
17 | public GitHubRepositorySearchStore(ContentResolver contentResolver) {
18 | super(contentResolver, new TypeToken() {}.getType());
19 | }
20 |
21 | @Override
22 | protected String getIdFor(GitHubRepositorySearch item) {
23 | return item.getSearch();
24 | }
25 |
26 | @Override
27 | protected Uri getContentUri() {
28 | return GitHubRepositorySearchContract.CONTENT_URI;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/widget/WidgetProvider.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.widget;
2 |
3 | import android.app.PendingIntent;
4 | import android.appwidget.AppWidgetManager;
5 | import android.appwidget.AppWidgetProvider;
6 | import android.content.Context;
7 | import android.content.Intent;
8 | import android.widget.RemoteViews;
9 |
10 | /**
11 | * Created by ttuo on 26/03/15.
12 | */
13 | public class WidgetProvider extends AppWidgetProvider {
14 |
15 | @Override
16 | public void onReceive(Context context, Intent intent) {
17 | super.onReceive(context, intent);
18 | }
19 |
20 | public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
21 | super.onUpdate(context, appWidgetManager, appWidgetIds);
22 |
23 | for (int appWidgetId : appWidgetIds) {
24 | Intent intentService = new Intent(context, WidgetService.class);
25 | intentService.setAction("refresh");
26 | intentService.putExtra("widgetId", appWidgetId);
27 | context.startService(intentService);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/data/provider/SerializedJsonContract.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.data.provider;
2 |
3 | /**
4 | * Created by ttuo on 13/01/15.
5 | */
6 | abstract public class SerializedJsonContract implements DatabaseContract {
7 | public static final String ID = "id";
8 | public static final String JSON = "json";
9 |
10 | public static final String[] PROJECTION = new String[]{ID, JSON};
11 |
12 | public String getDefaultSortOrder() {
13 | return ID + " ASC";
14 | }
15 |
16 | public String getCreateTable() {
17 | return " CREATE TABLE " + getTableName()
18 | + " ( " + getCreateIdColumn() + ", "
19 | + JSON + " TEXT NOT NULL);";
20 | }
21 |
22 | public String getDropTable() {
23 | return "DROP TABLE IF EXISTS " + getTableName();
24 | }
25 |
26 | public String getName() {
27 | return getTableName();
28 | }
29 |
30 | @Override
31 | public String getIdColumnName() {
32 | return ID;
33 | }
34 |
35 | abstract protected String getTableName();
36 | abstract protected String getCreateIdColumn();
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/pojo/GitHubRepository.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.pojo;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | /**
6 | * Created by ttuo on 06/01/15.
7 | */
8 | public class GitHubRepository {
9 | final private int id;
10 |
11 | final private String name;
12 |
13 | @SerializedName("stargazers_count")
14 | final private int stargazersCount;
15 |
16 | @SerializedName("forks_count")
17 | final private int forksCount;
18 |
19 | public GitHubRepository(int id, String name, int stargazersCount, int forksCount) {
20 | this.name = name;
21 | this.id = id;
22 | this.stargazersCount = stargazersCount;
23 | this.forksCount = forksCount;
24 | }
25 |
26 | public int getId() {
27 | return id;
28 | }
29 |
30 | public String getName() {
31 | return name;
32 | }
33 |
34 | public int getStargazersCount() {
35 | return stargazersCount;
36 | }
37 |
38 | public int getForksCount() {
39 | return forksCount;
40 | }
41 |
42 | @Override
43 | public String toString() {
44 | return name;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/widget_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
17 |
22 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/repository_fragment.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
17 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/data/provider/UserSettingsContract.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.data.provider;
2 |
3 | import android.net.Uri;
4 |
5 | /**
6 | * Created by ttuo on 11/01/15.
7 | */
8 | public class UserSettingsContract extends SerializedJsonContract {
9 | private static final String SINGLE_MIME_TYPE =
10 | "vnd.android.cursor.item/vnd.tehmou.android.rxbookapp.usersettings";
11 | private static final String MULTIPLE_MIME_TYPE =
12 | "vnd.android.cursor.dir/vnd.tehmou.android.rxbookapp.usersettings";
13 |
14 | private static final String TABLE_NAME = "usersettings";
15 | public static final Uri CONTENT_URI = Uri.parse("content://" + GithubContentProvider.PROVIDER_NAME + "/" + TABLE_NAME);
16 |
17 | @Override
18 | protected String getTableName() {
19 | return TABLE_NAME;
20 | }
21 |
22 | @Override
23 | public String getSingleMimeType() {
24 | return SINGLE_MIME_TYPE;
25 | }
26 |
27 | @Override
28 | public String getMultipleMimeType() {
29 | return MULTIPLE_MIME_TYPE;
30 | }
31 |
32 | @Override
33 | protected String getCreateIdColumn() {
34 | return ID + " INTEGER PRIMARY KEY AUTOINCREMENT";
35 | }
36 |
37 | public String getIdSqlString(String id) {
38 | return id;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/data/provider/GitHubRepositoryContract.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.data.provider;
2 |
3 | import android.net.Uri;
4 |
5 | /**
6 | * Created by ttuo on 11/01/15.
7 | */
8 | public class GitHubRepositoryContract extends SerializedJsonContract {
9 | private static final String SINGLE_MIME_TYPE =
10 | "vnd.android.cursor.item/vnd.tehmou.android.rxbookapp.repository";
11 | private static final String MULTIPLE_MIME_TYPE =
12 | "vnd.android.cursor.dir/vnd.tehmou.android.rxbookapp.repository";
13 |
14 | private static final String TABLE_NAME = "repositories";
15 | public static final Uri CONTENT_URI = Uri.parse("content://" + GithubContentProvider.PROVIDER_NAME + "/" + TABLE_NAME);
16 |
17 | @Override
18 | protected String getTableName() {
19 | return TABLE_NAME;
20 | }
21 |
22 | @Override
23 | public String getSingleMimeType() {
24 | return SINGLE_MIME_TYPE;
25 | }
26 |
27 | @Override
28 | public String getMultipleMimeType() {
29 | return MULTIPLE_MIME_TYPE;
30 | }
31 |
32 | @Override
33 | protected String getCreateIdColumn() {
34 | return ID + " INTEGER PRIMARY KEY AUTOINCREMENT";
35 | }
36 |
37 | public String getIdSqlString(String id) {
38 | return id;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/data/provider/GitHubRepositorySearchContract.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.data.provider;
2 |
3 | import android.net.Uri;
4 |
5 | /**
6 | * Created by ttuo on 11/01/15.
7 | */
8 | public class GitHubRepositorySearchContract extends SerializedJsonContract {
9 | private static final String SINGLE_MIME_TYPE =
10 | "vnd.android.cursor.item/vnd.tehmou.android.rxbookapp.repositorysearch";
11 | private static final String MULTIPLE_MIME_TYPE =
12 | "vnd.android.cursor.dir/vnd.tehmou.android.rxbookapp.repositorysearch";
13 |
14 | static final String TABLE_NAME = "repository_searches";
15 | public static final Uri CONTENT_URI = Uri.parse("content://" + GithubContentProvider.PROVIDER_NAME + "/" + TABLE_NAME);
16 |
17 | @Override
18 | protected String getTableName() {
19 | return TABLE_NAME;
20 | }
21 |
22 | @Override
23 | public String getSingleMimeType() {
24 | return SINGLE_MIME_TYPE;
25 | }
26 |
27 | @Override
28 | public String getMultipleMimeType() {
29 | return MULTIPLE_MIME_TYPE;
30 | }
31 |
32 | @Override
33 | protected String getCreateIdColumn() {
34 | return ID + " STRING PRIMARY KEY";
35 | }
36 |
37 | public String getIdSqlString(String id) {
38 | return "'" + id + "'";
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/utils/SubscriptionUtils.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.utils;
2 |
3 | import android.graphics.Color;
4 | import android.widget.TextView;
5 |
6 | import rx.Observable;
7 | import rx.Scheduler;
8 | import rx.Subscription;
9 | import rx.android.schedulers.AndroidSchedulers;
10 |
11 | /**
12 | * Created by ttuo on 13/06/14.
13 | */
14 | public class SubscriptionUtils {
15 | private SubscriptionUtils() { }
16 |
17 | static public Subscription subscribeTextViewText(final Observable observable,
18 | final TextView textView) {
19 | return subscribeTextViewText(observable, textView, AndroidSchedulers.mainThread());
20 | }
21 | static public Subscription subscribeTextViewText(final Observable observable,
22 | final TextView textView,
23 | Scheduler scheduler) {
24 | return observable
25 | .observeOn(scheduler)
26 | .subscribe(textView::setText,
27 | error -> {
28 | textView.setText(error.toString());
29 | textView.setBackgroundColor(Color.RED);
30 | }
31 | );
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/repositories_fragment.xml:
--------------------------------------------------------------------------------
1 |
11 |
15 |
21 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/data/UserSettingsStore.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.data;
2 |
3 | import android.content.ContentResolver;
4 | import android.net.Uri;
5 |
6 | import com.google.gson.reflect.TypeToken;
7 | import com.tehmou.rxbookapp.data.provider.GitHubRepositoryContract;
8 | import com.tehmou.rxbookapp.data.provider.UserSettingsContract;
9 | import com.tehmou.rxbookapp.pojo.GitHubRepository;
10 | import com.tehmou.rxbookapp.pojo.UserSettings;
11 |
12 | /**
13 | * Created by ttuo on 07/01/15.
14 | */
15 | public class UserSettingsStore extends ContentProviderStoreBase {
16 | private static final String TAG = UserSettingsStore.class.getSimpleName();
17 |
18 | public static final int DEFAULT_USER_ID = 0;
19 | private static final int DEFAULT_REPOSITORY_ID = 15491874;
20 |
21 | public UserSettingsStore(ContentResolver contentResolver) {
22 | super(contentResolver, new TypeToken() {}.getType());
23 | if (!hasUserSettings()) {
24 | insertOrUpdate(new UserSettings(DEFAULT_REPOSITORY_ID));
25 | }
26 | }
27 |
28 | @Override
29 | protected Integer getIdFor(UserSettings item) {
30 | return DEFAULT_USER_ID;
31 | }
32 |
33 | @Override
34 | protected Uri getContentUri() {
35 | return UserSettingsContract.CONTENT_URI;
36 | }
37 |
38 | private boolean hasUserSettings() {
39 | return query(DEFAULT_USER_ID) != null;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/utils/TextWatcherObservable.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.utils;
2 |
3 | import android.text.Editable;
4 | import android.text.TextWatcher;
5 | import android.widget.EditText;
6 |
7 | import rx.Observable;
8 | import rx.Subscriber;
9 | import rx.subjects.BehaviorSubject;
10 | import rx.subjects.Subject;
11 |
12 | /**
13 | * Created by ttuo on 27/01/15.
14 | */
15 | public class TextWatcherObservable {
16 | static public Observable create(EditText editText) {
17 | return Observable.create(new OnSubscribe(editText));
18 | }
19 |
20 | static class OnSubscribe implements TextWatcher, Observable.OnSubscribe {
21 | final private Subject subject = BehaviorSubject.create();
22 |
23 | private OnSubscribe(EditText editText) {
24 | editText.addTextChangedListener(this);
25 | }
26 |
27 | @Override
28 | public void call(Subscriber super String> subscriber) {
29 | subject.subscribe(subscriber);
30 | }
31 |
32 | @Override
33 | public void beforeTextChanged(CharSequence s, int start, int count, int after) {
34 |
35 | }
36 |
37 | @Override
38 | public void onTextChanged(CharSequence s, int start, int before, int count) {
39 | subject.onNext(s.toString());
40 | }
41 |
42 | @Override
43 | public void afterTextChanged(Editable s) {
44 |
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/viewmodels/AbstractViewModel.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.viewmodels;
2 |
3 | import android.util.Log;
4 |
5 | import com.tehmou.rxbookapp.data.DataLayer;
6 |
7 | import javax.inject.Inject;
8 |
9 | import rx.subscriptions.CompositeSubscription;
10 |
11 | /**
12 | * Created by ttuo on 06/04/15.
13 | */
14 | abstract public class AbstractViewModel {
15 | private static final String TAG = AbstractViewModel.class.getSimpleName();
16 | private CompositeSubscription compositeSubscription;
17 |
18 | final public void subscribeToDataStore() {
19 | Log.v(TAG, "subscribeToDataStore");
20 | unsubscribeFromDataStore();
21 | compositeSubscription = new CompositeSubscription();
22 | subscribeToDataStoreInternal(compositeSubscription);
23 | }
24 |
25 | public void dispose() {
26 | Log.v(TAG, "dispose");
27 |
28 | if (compositeSubscription != null) {
29 | Log.e(TAG, "Disposing without calling unsubscribeFromDataStore first");
30 |
31 | // Unsubscribe in case we are still for some reason subscribed
32 | unsubscribeFromDataStore();
33 | }
34 | }
35 |
36 | abstract void subscribeToDataStoreInternal(CompositeSubscription compositeSubscription);
37 |
38 | public void unsubscribeFromDataStore() {
39 | Log.v(TAG, "unsubscribeToDataStore");
40 | if (compositeSubscription != null) {
41 | compositeSubscription.clear();
42 | compositeSubscription = null;
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/data/DataStoreModule.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.data;
2 |
3 | import com.tehmou.rxbookapp.RxBookApp;
4 |
5 | import android.content.ContentResolver;
6 |
7 | import javax.inject.Singleton;
8 |
9 | import dagger.Module;
10 | import dagger.Provides;
11 |
12 | /**
13 | * Created by pt2121 on 2/20/15.
14 | */
15 | @Module
16 | public final class DataStoreModule {
17 |
18 | @Provides
19 | public DataLayer.GetUserSettings provideGetUserSettings(DataLayer dataLayer) {
20 | return dataLayer::getUserSettings;
21 | }
22 |
23 | @Provides
24 | public DataLayer.SetUserSettings provideSetUserSettings(DataLayer dataLayer) {
25 | return dataLayer::setUserSettings;
26 | }
27 |
28 | @Provides
29 | public DataLayer.FetchAndGetGitHubRepository provideFetchAndGetGitHubRepository(DataLayer dataLayer) {
30 | return dataLayer::fetchAndGetGitHubRepository;
31 | }
32 |
33 | @Provides
34 | public DataLayer.GetGitHubRepositorySearch provideGetGitHubRepositorySearch(DataLayer dataLayer) {
35 | return dataLayer::getGitHubRepositorySearch;
36 | }
37 |
38 | @Provides
39 | public DataLayer.GetGitHubRepository provideGetGitHubRepository(DataLayer dataLayer) {
40 | return dataLayer::getGitHubRepository;
41 | }
42 |
43 | @Provides
44 | public ContentResolver contentResolver() {
45 | return RxBookApp.getInstance().getContentResolver();
46 | }
47 |
48 | @Provides
49 | @Singleton
50 | public DataLayer provideDataStoreModule(ContentResolver contentResolver) {
51 | return new DataLayer(contentResolver);
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/viewmodels/RepositoryViewModel.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.viewmodels;
2 |
3 | import android.util.Log;
4 |
5 | import com.tehmou.rxbookapp.RxBookApp;
6 | import com.tehmou.rxbookapp.data.DataLayer;
7 | import com.tehmou.rxbookapp.pojo.GitHubRepository;
8 | import com.tehmou.rxbookapp.pojo.UserSettings;
9 |
10 | import javax.inject.Inject;
11 |
12 | import rx.subjects.BehaviorSubject;
13 | import rx.subjects.Subject;
14 | import rx.subscriptions.CompositeSubscription;
15 |
16 | /**
17 | * Created by ttuo on 06/04/15.
18 | */
19 | public class RepositoryViewModel extends AbstractViewModel {
20 | private static final String TAG = RepositoryViewModel.class.getSimpleName();
21 |
22 | @Inject
23 | DataLayer.GetUserSettings getUserSettings;
24 |
25 | @Inject
26 | DataLayer.FetchAndGetGitHubRepository fetchAndGetGitHubRepository;
27 |
28 | final private BehaviorSubject repository = BehaviorSubject.create();
29 |
30 | public RepositoryViewModel() {
31 | RxBookApp.getInstance().getGraph().inject(this);
32 | Log.v(TAG, "RepositoryViewModel");
33 | }
34 |
35 | @Override
36 | protected void subscribeToDataStoreInternal(CompositeSubscription compositeSubscription) {
37 | compositeSubscription.add(
38 | getUserSettings.call()
39 | .map(UserSettings::getSelectedRepositoryId)
40 | .switchMap(fetchAndGetGitHubRepository::call)
41 | .subscribe(repository)
42 | );
43 | }
44 |
45 | public BehaviorSubject getRepository() {
46 | return repository;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/widget/WidgetRemoteViewFactory.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.widget;
2 |
3 | import android.content.Context;
4 | import android.util.Log;
5 | import android.widget.RemoteViews;
6 | import android.widget.RemoteViewsService;
7 |
8 | import com.tehmou.rxbookapp.R;
9 |
10 | /**
11 | * Created by ttuo on 26/03/15.
12 | */
13 | public class WidgetRemoteViewFactory implements RemoteViewsService.RemoteViewsFactory {
14 | private static final String TAG = WidgetRemoteViewFactory.class.getSimpleName();
15 | final private Context context;
16 |
17 | public WidgetRemoteViewFactory(Context context) {
18 | this.context = context;
19 | }
20 |
21 | @Override
22 | public void onCreate() {
23 |
24 | }
25 |
26 | @Override
27 | public void onDataSetChanged() {
28 |
29 | }
30 |
31 | @Override
32 | public void onDestroy() {
33 |
34 | }
35 |
36 | @Override
37 | public int getCount() {
38 | return 1;
39 | }
40 |
41 | @Override
42 | public RemoteViews getViewAt(int position) {
43 | Log.d(TAG, "getViewAt(" + position + ")");
44 | RemoteViews rv = new RemoteViews(context.getPackageName(),
45 | R.layout.widget_layout);
46 | return rv;
47 | }
48 |
49 | @Override
50 | public RemoteViews getLoadingView() {
51 | return null;
52 | }
53 |
54 | @Override
55 | public int getViewTypeCount() {
56 | return 0;
57 | }
58 |
59 | @Override
60 | public long getItemId(int position) {
61 | return 0;
62 | }
63 |
64 | @Override
65 | public boolean hasStableIds() {
66 | return false;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
13 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/data/HashStoreBase.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.data;
2 |
3 | import java.util.Map;
4 | import java.util.concurrent.ConcurrentHashMap;
5 |
6 | import rx.Observable;
7 | import rx.subjects.BehaviorSubject;
8 | import rx.subjects.PublishSubject;
9 | import rx.subjects.Subject;
10 |
11 | /**
12 | * Created by ttuo on 11/01/15.
13 | */
14 | public class HashStoreBase {
15 | static private int counter = 0;
16 |
17 | private static final String TAG = HashStoreBase.class.getSimpleName();
18 | final private Map hash = new ConcurrentHashMap<>();
19 | final private Map> subjectsHash = new ConcurrentHashMap<>();
20 |
21 | public String put(T item) {
22 | String key = "" + counter++;
23 | hash.put(key, item);
24 | return key;
25 | }
26 |
27 | public void put(String search, T item) {
28 | hash.put(search, item);
29 | if (subjectsHash.containsKey(search)) {
30 | subjectsHash.get(search).onNext(item);
31 | }
32 | }
33 |
34 | public Observable getStream(String id) {
35 | if (!subjectsHash.containsKey(id)) {
36 | subjectsHash.put(id, PublishSubject.create());
37 | }
38 | if (hash.containsKey(id)) {
39 | // Give the last value we have to the subscriber immediately.
40 | // We do this with BehaviorSubject.
41 | final Subject subject = BehaviorSubject.create(hash.get(id));
42 | subjectsHash.get(id).subscribe(subject);
43 | return subject;
44 | } else {
45 | // Return the subject that will give the subscriber all
46 | // subsequent updates to the store value.
47 | return subjectsHash.get(id);
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/view/RepositoryView.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.view;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.widget.FrameLayout;
6 | import android.widget.TextView;
7 |
8 | import com.tehmou.rxbookapp.R;
9 | import com.tehmou.rxbookapp.pojo.GitHubRepository;
10 | import com.tehmou.rxbookapp.utils.RxBinderUtil;
11 | import com.tehmou.rxbookapp.viewmodels.RepositoriesViewModel;
12 | import com.tehmou.rxbookapp.viewmodels.RepositoryViewModel;
13 |
14 | import java.util.List;
15 |
16 | /**
17 | * Created by ttuo on 06/04/15.
18 | */
19 | public class RepositoryView extends FrameLayout {
20 | private final RxBinderUtil rxBinderUtil = new RxBinderUtil(this);
21 |
22 | private TextView titleTextView;
23 | private TextView stargazersTextView;
24 | private TextView forksTextView;
25 |
26 | public RepositoryView(Context context) {
27 | super(context);
28 | }
29 |
30 | public RepositoryView(Context context, AttributeSet attrs) {
31 | super(context, attrs);
32 | }
33 |
34 | @Override
35 | protected void onFinishInflate() {
36 | super.onFinishInflate();
37 | titleTextView = (TextView) findViewById(R.id.widget_layout_title);
38 | stargazersTextView = (TextView) findViewById(R.id.widget_layout_stargazers);
39 | forksTextView = (TextView) findViewById(R.id.widget_layout_forks);
40 | }
41 |
42 | public void setViewModel(RepositoryViewModel viewModel) {
43 | rxBinderUtil.clear();
44 | if (viewModel != null) {
45 | rxBinderUtil.bindProperty(viewModel.getRepository(), this::setRepository);
46 | }
47 | }
48 |
49 | private void setRepository(GitHubRepository repository) {
50 | titleTextView.setText(repository.getName());
51 | stargazersTextView.setText("watching: " + repository.getStargazersCount());
52 | forksTextView.setText("forks: " + repository.getForksCount());
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/test/java/com/tehmou/rxbookapp/utils/SubscriptionUtilsTest.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.utils;
2 |
3 | import org.junit.Before;
4 | import org.junit.Test;
5 | import org.junit.runner.RunWith;
6 | import org.powermock.api.mockito.PowerMockito;
7 | import org.powermock.core.classloader.annotations.PrepareForTest;
8 | import org.powermock.modules.junit4.PowerMockRunner;
9 |
10 | import android.graphics.Color;
11 | import android.widget.TextView;
12 |
13 | import rx.Observable;
14 | import rx.android.schedulers.AndroidSchedulers;
15 | import rx.schedulers.Schedulers;
16 |
17 | import static org.mockito.Matchers.contains;
18 | import static org.mockito.Matchers.eq;
19 | import static org.mockito.Mockito.mock;
20 | import static org.mockito.Mockito.verify;
21 |
22 | @RunWith(PowerMockRunner.class)
23 | @PrepareForTest(AndroidSchedulers.class)
24 | public class SubscriptionUtilsTest {
25 |
26 | @Before
27 | public void setUp() {
28 | // Mocking AndroidSchedulers.mainThread() as loopers are not mocked by android unit tests
29 | PowerMockito.stub(PowerMockito.method(AndroidSchedulers.class, "mainThread"))
30 | .toReturn(Schedulers.immediate());
31 | }
32 |
33 | @Test
34 | public void testTextViewIsUpdatedWhenValueComes() {
35 | TextView textView = mock(TextView.class);
36 | Observable observable = Observable.just("String");
37 |
38 | SubscriptionUtils.subscribeTextViewText(observable, textView);
39 |
40 | verify(textView).setText(eq("String"));
41 | }
42 |
43 | @Test
44 | public void testTextViewIsUpdatedWithErrorMessageOnError() {
45 | TextView textView = mock(TextView.class);
46 | Observable observable = Observable.error(new NullPointerException());
47 |
48 | SubscriptionUtils.subscribeTextViewText(observable, textView);
49 |
50 | verify(textView).setText(contains("NullPointerException"));
51 | verify(textView).setBackgroundColor(eq(Color.RED));
52 | }
53 |
54 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/tehmou/rxbookapp/activities/ChooseRepositoryActivity.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.activities;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.v7.app.ActionBarActivity;
6 | import android.view.Menu;
7 | import android.view.MenuItem;
8 |
9 | import com.tehmou.rxbookapp.R;
10 | import com.tehmou.rxbookapp.fragments.RepositoriesFragment;
11 | import com.tehmou.rxbookapp.fragments.RepositoryFragment;
12 |
13 |
14 | public class ChooseRepositoryActivity extends ActionBarActivity {
15 | private static final String TAG = ChooseRepositoryActivity.class.getSimpleName();
16 |
17 | @Override
18 | protected void onCreate(Bundle savedInstanceState) {
19 | super.onCreate(savedInstanceState);
20 | setContentView(R.layout.activity_main);
21 | if (savedInstanceState == null) {
22 | getSupportFragmentManager().beginTransaction()
23 | .add(R.id.container, new RepositoriesFragment())
24 | .commit();
25 | }
26 | }
27 |
28 | @Override
29 | public boolean onCreateOptionsMenu(Menu menu) {
30 |
31 | // Inflate the menu; this adds items to the action bar if it is present.
32 | getMenuInflater().inflate(R.menu.main, menu);
33 | return true;
34 | }
35 |
36 | @Override
37 | public boolean onOptionsItemSelected(MenuItem item) {
38 | // Handle action bar item clicks here. The action bar will
39 | // automatically handle clicks on the Home/Up button, so long
40 | // as you specify a parent activity in AndroidManifest.xml.
41 | int id = item.getItemId();
42 | if (id == R.id.action_settings) {
43 | return true;
44 | }
45 | return super.onOptionsItemSelected(item);
46 | }
47 |
48 | public void chooseRepository(int repositoryId) {
49 | Intent data = new Intent();
50 | data.putExtra("repositoryId", repositoryId);
51 | setResult(0, data);
52 | finish();
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/test/java/com/tehmou/rxbookapp/test/SubscriptionManagerTest.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.test;
2 |
3 | import org.junit.Before;
4 | import org.junit.Test;
5 |
6 | import rx.Subscription;
7 | import rx.subscriptions.CompositeSubscription;
8 |
9 | import static org.junit.Assert.assertTrue;
10 | import static org.junit.Assert.fail;
11 | import static org.mockito.Mockito.mock;
12 | import static org.mockito.Mockito.verify;
13 |
14 | /**
15 | * Created by tehmou on 12/25/13.
16 | */
17 | public class SubscriptionManagerTest {
18 | private CompositeSubscription subscriptionManager;
19 |
20 | @Before
21 | public void setUp() throws Exception {
22 | subscriptionManager = new CompositeSubscription();
23 | }
24 |
25 | @Test
26 | public void testUnsubscribe() {
27 | Subscription subscriptionA = mock(Subscription.class);
28 | Subscription subscriptionB = mock(Subscription.class);
29 | subscriptionManager.add(subscriptionA);
30 | subscriptionManager.add(subscriptionB);
31 |
32 | subscriptionManager.unsubscribe();
33 |
34 | verify(subscriptionA).unsubscribe();
35 | verify(subscriptionB).unsubscribe();
36 | }
37 |
38 | @Test
39 | public void testUnsubscribeOnlyOnce() {
40 | Subscription subscriptionA = new TestSubscription();
41 | subscriptionManager.add(subscriptionA);
42 | subscriptionManager.add(subscriptionA);
43 |
44 | subscriptionManager.unsubscribe();
45 |
46 | assertTrue(subscriptionManager.isUnsubscribed());
47 | }
48 |
49 | static class TestSubscription implements Subscription {
50 | private boolean isSubscribed = true;
51 |
52 | @Override
53 | public void unsubscribe() {
54 | if (!isSubscribed) {
55 | fail("unsubscribed when not subscribed");
56 | }
57 | isSubscribed = false;
58 | }
59 |
60 | @Override
61 | public boolean isUnsubscribed() {
62 | return !isSubscribed;
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/app/src/test/java/com/tehmou/rxbookapp/utils/RxBinderUtilTest.java:
--------------------------------------------------------------------------------
1 | package com.tehmou.rxbookapp.utils;
2 |
3 | import org.junit.Before;
4 | import org.junit.Test;
5 | import org.junit.runner.RunWith;
6 | import org.mockito.MockitoAnnotations;
7 | import org.mockito.Spy;
8 | import org.powermock.api.mockito.PowerMockito;
9 | import org.powermock.core.classloader.annotations.PrepareForTest;
10 | import org.powermock.modules.junit4.PowerMockRunner;
11 |
12 | import rx.Observable;
13 | import rx.android.schedulers.AndroidSchedulers;
14 | import rx.functions.Action1;
15 | import rx.schedulers.Schedulers;
16 |
17 | import static org.mockito.Matchers.anyString;
18 | import static org.mockito.Mockito.only;
19 | import static org.mockito.Mockito.times;
20 | import static org.mockito.Mockito.verify;
21 |
22 | @RunWith(PowerMockRunner.class)
23 | @PrepareForTest(AndroidSchedulers.class)
24 | public class RxBinderUtilTest {
25 |
26 | RxBinderUtil binder;
27 |
28 | @Spy
29 | Action1