Commit 0aecabaa authored by Robert Hitt's avatar Robert Hitt
Browse files

Added a spinning progress bar

- Also made all the stuff more asynchronous. Though it now crashes
when the screen is rotated during the network calls. Oops.
parent 7102ce6a
......@@ -37,7 +37,7 @@
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
......
apply plugin: 'com.android.application'
apply plugin: 'android-apt'
apply plugin: 'realm-android'
apply plugin: 'me.tatarka.retrolambda'
android {
compileSdkVersion 25
......@@ -19,6 +20,10 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
......@@ -30,6 +35,7 @@ dependencies {
compile 'io.realm:android-adapters:1.4.0'
compile 'com.google.code.gson:gson:2.6.2'
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.android.support:appcompat-v7:25.1.0'
compile 'com.android.support:cardview-v7:25.1.0'
......@@ -44,4 +50,7 @@ dependencies {
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
compile 'com.github.daniel-stoneuk:material-about-library:1.3.0'
compile 'com.github.castorflex.smoothprogressbar:library-circular:1.2.0'
compile 'io.reactivex:rxandroid:1.2.0'
compile 'io.reactivex:rxjava:1.1.4'
}
......@@ -7,7 +7,9 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import io.realm.RealmObject;
import io.realm.rx.RxObservableFactory;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
/**
......@@ -56,6 +58,7 @@ public class WhatsOpenClient {
.create();
sRetrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
......
......@@ -5,11 +5,12 @@ import java.util.List;
import retrofit2.Call;
import retrofit2.http.GET;
import rx.Observable;
import srct.whatsopen.model.Facility;
// Interface for Retrofit's Http request
public interface WhatsOpenService {
@GET("facilities")
Call<List<Facility>> facilityList();
Observable<List<Facility>> facilityList();
}
package srct.whatsopen.ui;
public interface MainView {
public void showProgressBar();
public void dismissProgressBar();
}
......@@ -7,16 +7,25 @@ import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.LinearLayout;
import com.astuetz.PagerSlidingTabStrip;
import butterknife.BindView;
import butterknife.ButterKnife;
import fr.castorflex.android.circularprogressbar.CircularProgressBar;
import srct.whatsopen.R;
import srct.whatsopen.ui.MainView;
import srct.whatsopen.ui.presenters.MainPresenter;
import srct.whatsopen.ui.adapters.FacilityListFragmentPagerAdapter;
public class MainActivity extends AppCompatActivity {
public class MainActivity extends AppCompatActivity implements MainView {
@BindView(R.id.progress_bar) CircularProgressBar mProgressBar;
@BindView(R.id.list_view) LinearLayout mListView;
private MainPresenter mPresenter;
......@@ -25,6 +34,8 @@ public class MainActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
// Set up presenter
mPresenter = new MainPresenter();
mPresenter.attachView(this);
......@@ -76,6 +87,16 @@ public class MainActivity extends AppCompatActivity {
}
}
@Override
public void showProgressBar() {
mProgressBar.setVisibility(View.VISIBLE);
}
@Override
public void dismissProgressBar() {
mProgressBar.setVisibility(View.GONE);
}
// Opens the About page for the app
private void expandAboutActivity() {
Intent i = new Intent(this, AboutActivity.class);
......
......@@ -41,17 +41,14 @@ public class FacilityPresenter {
final SharedPreferences.Editor editor = pref.edit();
final String facilityName = facility.getName();
realm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm bgRealm) {
// have to requery for the object as it was created on a separate thread
Facility f = bgRealm.where(Facility.class)
.equalTo("mName", facilityName).findFirst();
f.setFavorited(status);
editor.putBoolean(facilityName, status);
editor.apply();
}
realm.executeTransactionAsync(bgRealm -> {
// have to requery for the object as it was created on a separate thread
Facility f = bgRealm.where(Facility.class)
.equalTo("mName", facilityName).findFirst();
f.setFavorited(status);
editor.putBoolean(facilityName, status);
editor.apply();
}, null, null);
realm.close();
......
......@@ -12,9 +12,13 @@ import java.util.List;
import io.realm.Realm;
import io.realm.RealmList;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
import srct.whatsopen.model.Facility;
import srct.whatsopen.model.OpenTimes;
import srct.whatsopen.service.WhatsOpenClient;
......@@ -23,54 +27,67 @@ import srct.whatsopen.ui.activities.MainActivity;
public class MainPresenter {
private MainActivity mainView;
private MainActivity mMainView;
public void attachView(MainActivity view) {
this.mainView = view;
this.mMainView = view;
}
public void detachView() {
this.mainView = null;
this.mMainView = null;
}
// Gets a Call from the given Retrofit service, then asynchronously executes it
// On success, copies the resulting facility list to the Realm DB
public void loadFacilities() {
mMainView.showProgressBar();
// Get WhatsOpenClient singleton
WhatsOpenService service = WhatsOpenClient.getInstance();
// Get Realm and SharedPreference instances
Observable<List<Facility>> call = service.facilityList();
call.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map(facilities1 -> setStatus(facilities1))
.subscribeOn(Schedulers.io())
.subscribe(new Subscriber<List<Facility>>() {
@Override
public void onCompleted() {
mMainView.dismissProgressBar();
}
@Override
public void onError(Throwable e) {
mMainView.dismissProgressBar();
// should probably show some error message
}
@Override
public void onNext(List<Facility> facilities) {
writeToRealm(facilities);
}
});
}
// Sets the favorite and open status of each Facility
private List<Facility> setStatus(List<Facility> facilities) {
final SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(mMainView);
for(Facility facility : facilities) {
// Query SharedReferences for each Facility's favorite status. defaults to false
facility.setFavorited(pref.getBoolean(facility.getName(), false));
facility.setOpen(getOpenStatus(facility, Calendar.getInstance()));
}
return facilities;
}
// Asynchronously writes the facility list to Realm
private void writeToRealm(List<Facility> facilities) {
final Realm realm = Realm.getDefaultInstance();
final SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(mainView);
Call<List<Facility>> call = service.facilityList();
call.enqueue(new Callback<List<Facility>>() {
@Override
public void onResponse(Call<List<Facility>> call, Response<List<Facility>> response) {
List<Facility> facilities = response.body();
for(Facility facility : facilities) {
// Query SharedReferences for each Facility's favorite status. defaults to false
facility.setFavorited(pref.getBoolean(facility.getName(), false));
facility.setOpen(getOpenStatus(facility, Calendar.getInstance()));
}
realm.beginTransaction();
realm.copyToRealmOrUpdate(facilities);
realm.commitTransaction();
realm.close();
}
@Override
public void onFailure(Call<List<Facility>> call, Throwable t) {
// do some stuff
realm.close();
}
});
realm.executeTransactionAsync(bgRealm -> bgRealm.copyToRealmOrUpdate(facilities));
realm.close();
}
// Uses the device time to determine which facilities should be open
public boolean getOpenStatus(Facility facility, Calendar now) {
RealmList<OpenTimes> openTimesList = facility.getMainSchedule().getOpenTimesList();
......
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/fragment_facility"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical"
tools:context="srct.whatsopen.ui.activities.MainActivity">
<include
layout="@layout/toolbar_main"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>
<com.astuetz.PagerSlidingTabStrip
android:id="@+id/tabs"
app:pstsShouldExpand="true"
app:pstsIndicatorColor="@color/colorPrimary"
app:pstsIndicatorHeight="6dp"
app:pstsTabBackground="@drawable/button_bg"
<LinearLayout
android:id="@+id/list_view"
android:fitsSystemWindows="true"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="48dp"/>
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"/>
<include
layout="@layout/toolbar_main"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>
<com.astuetz.PagerSlidingTabStrip
android:id="@+id/tabs"
app:pstsShouldExpand="true"
app:pstsIndicatorColor="@color/colorPrimary"
app:pstsIndicatorHeight="6dp"
app:pstsTabBackground="@drawable/button_bg"
android:layout_width="match_parent"
android:layout_height="48dp"/>
<android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"/>
</LinearLayout>
<fr.castorflex.android.circularprogressbar.CircularProgressBar
android:id="@+id/progress_bar"
android:indeterminate="true"
android:layout_gravity="center"
app:cpb_color="@color/colorPrimary"
app:cpb_rotation_speed="1.0"
app:cpb_sweep_speed="1.0"
app:cpb_stroke_width="6dp"
app:cpb_max_sweep_angle="300"
app:cpb_min_sweep_angle="10"
android:layout_width="80dp"
android:layout_height="80dp"/>
</LinearLayout>
</FrameLayout>
package srct.whatsopen;
import org.junit.Test;
import static org.junit.Assert.*;
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}
\ No newline at end of file
......@@ -9,6 +9,8 @@ buildscript {
classpath 'com.android.tools.build:gradle:2.2.3'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
classpath "io.realm:realm-gradle-plugin:2.2.1"
classpath 'me.tatarka:gradle-retrolambda:3.3.1'
classpath 'me.tatarka.retrolambda.projectlombok:lombok.ast:0.2.3.a2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment