eleith
/
calchoochoo
Archived
1
0
Fork 0

learning dagger, rx and a few others. integrating it

This commit is contained in:
eleith 2016-12-23 16:58:17 -08:00
parent 35a3fd9ca6
commit 33be2757ac
34 changed files with 765 additions and 412 deletions

View File

@ -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">

View File

@ -1,4 +1,5 @@
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
android {
compileSdkVersion 23
@ -17,14 +18,44 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
packagingOptions {
exclude 'META-INF/services/javax.annotation.processing.Processor' // butterknife
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.readystatesoftware.sqliteasset:sqliteassethelper:2.0.1'
compile 'org.apache.commons:commons-lang3:3.4'
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.android.support:support-v4:23.4.0'
compile 'com.android.support:recyclerview-v7:23.4.0'
compile "com.android.support:design:23.4.0"
//commons-lang (used for fuzzy search)
compile 'org.apache.commons:commons-lang3:3.4'
//sqliteassethelper (used to load existing sqlite db)
compile 'com.readystatesoftware.sqliteasset:sqliteassethelper:2.0.1'
//rxjava (currently used for the event bus)
compile 'io.reactivex:rxandroid:1.2.0'
compile 'io.reactivex:rxjava:1.1.4'
//dagger2 (dependency injection)
apt 'com.google.dagger:dagger-compiler:2.7'
compile 'com.google.dagger:dagger:2.7'
provided 'javax.annotation:jsr250-api:1.0'
//butterknife (view injection)
compile 'com.jakewharton:butterknife:8.4.0'
apt 'com.jakewharton:butterknife-compiler:8.4.0'
//DBFlow
apt "com.github.Raizlabs.DBFlow:dbflow-processor:3.1.1"
compile "com.github.Raizlabs.DBFlow:dbflow-core:3.1.1"
compile "com.github.Raizlabs.DBFlow:dbflow:3.1.1"
//Parceler
compile 'org.parceler:parceler-api:1.1.1'
apt 'org.parceler:parceler:1.1.1'
}

View File

@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:name=".ChooChooApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"

View File

@ -0,0 +1,26 @@
package com.eleith.calchoochoo;
import android.app.Application;
import com.eleith.calchoochoo.dagger.AppComponent;
import com.eleith.calchoochoo.dagger.AppModule;
import com.eleith.calchoochoo.dagger.DaggerAppComponent;
import com.raizlabs.android.dbflow.config.FlowConfig;
import com.raizlabs.android.dbflow.config.FlowManager;
public class ChooChooApplication extends Application {
private AppComponent appComponent;
@Override
public void onCreate() {
super.onCreate();
appComponent = DaggerAppComponent.builder().appModule(new AppModule(this)).build();
FlowManager.init(new FlowConfig.Builder(this).build());
}
public AppComponent getAppComponent() {
return appComponent;
}
}

View File

@ -1,41 +0,0 @@
package com.eleith.calchoochoo;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class DepartingArrivingDialog extends android.support.v4.app.DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.fragment_departing_arriving_selector, null);
builder.setView(view);
View cancelButton = view.findViewById(R.id.departOrArriveCancel);
cancelButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getDialog().dismiss();
}
});
View selectButton = view.findViewById(R.id.departOrArriveSelect);
selectButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getDialog().dismiss();
}
});
return builder.create();
}
}

View File

@ -1,102 +0,0 @@
package com.eleith.calchoochoo;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.eleith.calchoochoo.data.Stop;
public class DestinationSourceFragment extends Fragment {
private DestinationSourceFragmentListener listener;
private Stop stopDestination;
private Stop stopSource;
public interface DestinationSourceFragmentListener {
void onDestinationTouch();
void onSourceTouch();
}
public DestinationSourceFragment() {
// Required empty public constructor
}
public static DestinationSourceFragment newInstance() {
DestinationSourceFragment fragment = new DestinationSourceFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle arguments = getArguments();
if (arguments != null) {
stopDestination = arguments.getParcelable(BundleKeys.DESTINATION);
stopSource = arguments.getParcelable(BundleKeys.SOURCE);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_destination_source, container, false);
TextView destinationEdit = (TextView) view.findViewById(R.id.destinationEdit);
TextView sourceEdit = (TextView) view.findViewById(R.id.sourceEdit);
TextView timeEdit = (TextView) view.findViewById(R.id.timeEdit);
if (stopDestination != null) {
destinationEdit.setText(stopDestination.getName());
}
if (stopSource != null) {
sourceEdit.setText(stopSource.getName());
}
destinationEdit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onDestinationTouch();
}
});
sourceEdit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onSourceTouch();
}
});
timeEdit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DepartingArrivingDialog dialog = new DepartingArrivingDialog();
dialog.show(getFragmentManager(), "dialog");
}
});
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof DestinationSourceFragmentListener) {
listener = (DestinationSourceFragmentListener) context;
} else {
throw new RuntimeException(context.toString() + " must implement DestinationSourceFragmentListener");
}
}
@Override
public void onDetach() {
super.onDetach();
listener = null;
}
}

View File

@ -1,41 +1,145 @@
package com.eleith.calchoochoo;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.util.Pair;
import android.support.v7.app.AppCompatActivity;
import com.eleith.calchoochoo.dagger.ScheduleExplorerActivityComponent;
import com.eleith.calchoochoo.dagger.ScheduleExplorerActivityModule;
import com.eleith.calchoochoo.data.DatabaseHelper;
import com.eleith.calchoochoo.data.Stop;
import com.eleith.calchoochoo.fragments.DestinationSourceFragment;
import com.eleith.calchoochoo.fragments.HomeFragment;
import com.eleith.calchoochoo.fragments.SearchInputFragment;
import com.eleith.calchoochoo.fragments.SearchResultsFragment;
import com.eleith.calchoochoo.utils.BundleKeys;
import com.eleith.calchoochoo.utils.Permissions;
import com.eleith.calchoochoo.utils.RxBus;
import com.eleith.calchoochoo.utils.RxMessage;
import com.eleith.calchoochoo.utils.RxMessagePair;
import com.eleith.calchoochoo.utils.RxMessageString;
import com.eleith.calchoochoo.utils.RxMessageKeys;
import java.util.ArrayList;
public class ScheduleExplorerActivity extends AppCompatActivity
implements DestinationSourceFragment.DestinationSourceFragmentListener,
SearchResultsFragment.SearchResultsFragmentListener,
SearchInputFragment.SearchInputFragmentListener {
import javax.inject.Inject;
import rx.functions.Action1;
public class ScheduleExplorerActivity extends AppCompatActivity {
private SearchResultsFragment searchResultsFragment;
private SearchInputFragment searchInputFragment;
private DatabaseHelper databaseHelper;
private LocationManager locationManager;
private Location location;
private Stop stopDestination;
private Stop stopSource;
private LocationListener locationListener;
private static final String SEARCH_REASON_DESTINATION = "destination";
private static final String SEARCH_REASON_SOURCE = "source";
private ScheduleExplorerActivityComponent scheduleExplorerActivityComponent;
@Inject RxBus rxbus;
@Inject LocationManager locationManager;
@Inject FragmentManager fragmentManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
scheduleExplorerActivityComponent = ((ChooChooApplication) getApplication()).getAppComponent()
.activityComponent(new ScheduleExplorerActivityModule(this));
scheduleExplorerActivityComponent.inject(this);
initializeLocationListener();
setContentView(R.layout.schedule_explorer_activity);
databaseHelper = new DatabaseHelper(this);
updateFragments(new DestinationSourceFragment(), new HomeFragment());
rxbus.observeEvents(RxMessage.class).subscribe(handleScheduleExplorerRxMessages());
}
private Action1<RxMessage> handleScheduleExplorerRxMessages() {
return new Action1<RxMessage>() {
@Override
public void call(RxMessage rxMessage) {
String type = rxMessage.getType();
if (type.equals(RxMessageKeys.SEARCH_INPUT_STRING) && rxMessage instanceof RxMessageString) {
filterSearchResults(((RxMessageString) rxMessage).getMessageString());
} else if(type.equals(RxMessageKeys.SEARCH_RESULT_PAIR) && rxMessage instanceof RxMessagePair) {
Pair pair = ((RxMessagePair) rxMessage).getMessagePair();
if (pair.first instanceof Stop && pair.second instanceof String) {
selectSearchResult((Stop) pair.first, (String) pair.second);
}
} else if(type.equals(RxMessageKeys.DESTINATION_SELECTED)) {
selectDestination();
} else if(type.equals(RxMessageKeys.SOURCE_SELECTED)) {
selectSource();
}
}
};
}
private void filterSearchResults(String filterString) {
if (searchResultsFragment != null && searchResultsFragment.isVisible()) {
searchResultsFragment.filterResultsBy(filterString, location);
}
}
private void selectDestination() {
searchInputFragment = new SearchInputFragment();
searchResultsFragment = new SearchResultsFragment();
Bundle searchResultsArgs = new Bundle();
ArrayList<Stop> stops = databaseHelper.getAllStations();
searchResultsArgs.putParcelableArrayList(BundleKeys.STOPS, stops);
searchResultsArgs.putParcelable(BundleKeys.LOCATION, location);
searchResultsArgs.putString(BundleKeys.SEARCH_REASON, SEARCH_REASON_DESTINATION);
searchResultsFragment.setArguments(searchResultsArgs);
updateFragments(searchInputFragment, searchResultsFragment);
}
private void selectSource() {
searchInputFragment = new SearchInputFragment();
searchResultsFragment = new SearchResultsFragment();
Bundle searchResultsArgs = new Bundle();
ArrayList<Stop> stops = databaseHelper.getAllStations();
searchResultsArgs.putParcelableArrayList(BundleKeys.STOPS, stops);
searchResultsArgs.putParcelable(BundleKeys.LOCATION, location);
searchResultsArgs.putString(BundleKeys.SEARCH_REASON, SEARCH_REASON_SOURCE);
searchResultsFragment.setArguments(searchResultsArgs);
updateFragments(searchInputFragment, searchResultsFragment);
}
private void selectSearchResult(Stop stop, String searchReason) {
if (searchReason.equals(SEARCH_REASON_DESTINATION)) {
stopDestination = stop;
} else if (searchReason.equals(SEARCH_REASON_SOURCE)) {
stopSource = stop;
}
Bundle destinationSourceArgs = new Bundle();
DestinationSourceFragment destinationSourceFragment = new DestinationSourceFragment();
destinationSourceArgs.putParcelable(BundleKeys.DESTINATION, stopDestination);
destinationSourceArgs.putParcelable(BundleKeys.SOURCE, stopSource);
destinationSourceFragment.setArguments(destinationSourceArgs);
updateFragments(destinationSourceFragment, new HomeFragment());
}
private void initializeLocationListener() {
locationListener = new LocationListener() {
public void onLocationChanged(Location newLocation) {
stopListeningForLocation();
@ -52,100 +156,10 @@ public class ScheduleExplorerActivity extends AppCompatActivity
}
};
// don't want to check for location everytime if user doesn't want to give it up ...
startListeningForLocation(true);
setContentView(R.layout.schedule_explorer_activity);
databaseHelper = new DatabaseHelper(this);
DestinationSourceFragment destinationSourceFragment = new DestinationSourceFragment();
HomeFragment homeFragment = new HomeFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.homeTopFragmentContainer, destinationSourceFragment);
transaction.replace(R.id.homeFragmentContainer, homeFragment);
transaction.addToBackStack(null);
transaction.commit();
}
@Override
public void onSearchInputChange(String searchText) {
if (searchResultsFragment != null && searchResultsFragment.isVisible()) {
searchResultsFragment.filterResultsBy(searchText, location);
}
}
@Override
public void onDestinationTouch() {
searchInputFragment = new SearchInputFragment();
searchResultsFragment = new SearchResultsFragment();
Bundle searchResultsArgs = new Bundle();
ArrayList<Stop> stops = databaseHelper.getAllStations();
searchResultsArgs.putParcelableArrayList(BundleKeys.STOPS, stops);
searchResultsArgs.putParcelable(BundleKeys.LOCATION, location);
searchResultsArgs.putString(BundleKeys.SEARCH_REASON, SEARCH_REASON_DESTINATION);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
searchResultsFragment.setArguments(searchResultsArgs);
transaction.replace(R.id.homeTopFragmentContainer, searchInputFragment);
transaction.replace(R.id.homeFragmentContainer, searchResultsFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
@Override
public void onSourceTouch() {
searchInputFragment = new SearchInputFragment();
searchResultsFragment = new SearchResultsFragment();
Bundle searchResultsArgs = new Bundle();
ArrayList<Stop> stops = databaseHelper.getAllStations();
searchResultsArgs.putParcelableArrayList(BundleKeys.STOPS, stops);
searchResultsArgs.putParcelable(BundleKeys.LOCATION, location);
searchResultsArgs.putString(BundleKeys.SEARCH_REASON, SEARCH_REASON_SOURCE);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
searchResultsFragment.setArguments(searchResultsArgs);
transaction.replace(R.id.homeTopFragmentContainer, searchInputFragment);
transaction.replace(R.id.homeFragmentContainer, searchResultsFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
@Override
public void onSearchResultSelect(Stop stop, String searchReason) {
if (searchReason == SEARCH_REASON_DESTINATION) {
stopDestination = stop;
} else if (searchReason == SEARCH_REASON_SOURCE) {
stopSource = stop;
}
Bundle destinationSourceArgs = new Bundle();
DestinationSourceFragment destinationSourceFragment = new DestinationSourceFragment();
destinationSourceArgs.putParcelable(BundleKeys.DESTINATION, stopDestination);
destinationSourceArgs.putParcelable(BundleKeys.SOURCE, stopSource);
destinationSourceFragment.setArguments(destinationSourceArgs);
HomeFragment homeFragment = new HomeFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.homeTopFragmentContainer, destinationSourceFragment);
transaction.replace(R.id.homeFragmentContainer, homeFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
public void startListeningForLocation(Boolean shouldRequest) {
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
private void startListeningForLocation(Boolean shouldRequest) {
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 60000, 10000, locationListener);
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
@ -154,12 +168,20 @@ public class ScheduleExplorerActivity extends AppCompatActivity
}
}
public void stopListeningForLocation() {
private void stopListeningForLocation() {
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
locationManager.removeUpdates(locationListener);
}
}
private void updateFragments(Fragment f1, Fragment f2) {
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.replace(R.id.homeTopFragmentContainer, f1);
ft.replace(R.id.homeFragmentContainer, f2);
ft.addToBackStack(null);
ft.commit();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
@ -170,4 +192,8 @@ public class ScheduleExplorerActivity extends AppCompatActivity
}
}
}
public ScheduleExplorerActivityComponent getComponent() {
return this.scheduleExplorerActivityComponent;
}
}

View File

@ -1,79 +0,0 @@
package com.eleith.calchoochoo;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
public class SearchInputFragment extends Fragment {
private SearchInputFragmentListener listener;
public interface SearchInputFragmentListener {
void onSearchInputChange(String searchText);
}
public SearchInputFragment() {
// Required empty public constructor
}
public static SearchInputFragment newInstance() {
SearchInputFragment fragment = new SearchInputFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_search_input, container, false);
EditText searchInput = (EditText) view.findViewById(R.id.searchInput);
searchInput.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
listener.onSearchInputChange(s.toString());
}
@Override
public void afterTextChanged(Editable s) {
}
});
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof SearchInputFragmentListener) {
listener = (SearchInputFragmentListener) context;
} else {
throw new RuntimeException(context.toString() + " must implement SearchInputFragmentListener");
}
}
@Override
public void onDetach() {
super.onDetach();
listener = null;
}
}

View File

@ -8,6 +8,10 @@ import android.view.ViewGroup;
import android.widget.TextView;
import com.eleith.calchoochoo.data.Stop;
import com.eleith.calchoochoo.utils.DistanceUtils;
import com.eleith.calchoochoo.utils.RxBus;
import com.eleith.calchoochoo.utils.RxMessage;
import com.eleith.calchoochoo.utils.RxMessageKeys;
import org.apache.commons.lang3.StringUtils;
@ -15,17 +19,19 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Locale;
import javax.inject.Inject;
public class SearchResultsViewAdapter extends RecyclerView.Adapter<SearchResultsViewAdapter.ViewHolder> {
private ArrayList<Stop> stops = new ArrayList<Stop>();
private Location location;
private SearchResultsViewAdapterListener listener;
private RxBus rxBus;
public interface SearchResultsViewAdapterListener {
void onSearchResultSelect(Stop stop);
public SearchResultsViewAdapter(RxBus rxBus) {
this.rxBus = rxBus;
}
public SearchResultsViewAdapter(ArrayList<Stop> stops) {
public void setStops(ArrayList<Stop> stops) {
this.stops = stops;
}
@ -40,10 +46,6 @@ public class SearchResultsViewAdapter extends RecyclerView.Adapter<SearchResults
}
}
public void setSearchResultsViewAdapterListener(SearchResultsViewAdapterListener listener) {
this.listener = listener;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
@ -53,7 +55,7 @@ public class SearchResultsViewAdapter extends RecyclerView.Adapter<SearchResults
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onSearchResultSelect(holder.mItem);
rxBus.send(new RxMessage(RxMessageKeys.SEARCH_RESULT_STOP, holder.mItem));
}
});

View File

@ -0,0 +1,15 @@
package com.eleith.calchoochoo.dagger;
import android.location.LocationManager;
import com.eleith.calchoochoo.utils.RxBus;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
// instantiate subcomponents
ScheduleExplorerActivityComponent activityComponent(ScheduleExplorerActivityModule scheduleExplorerActivityModule);
}

View File

@ -0,0 +1,33 @@
package com.eleith.calchoochoo.dagger;
import android.content.Context;
import android.location.LocationManager;
import com.eleith.calchoochoo.ChooChooApplication;
import com.eleith.calchoochoo.utils.RxBus;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class AppModule {
private ChooChooApplication application;
public AppModule(ChooChooApplication application) {
this.application = application;
}
@Provides
@Singleton
public RxBus provideRxBus() {
return new RxBus();
}
@Provides
@Singleton
public LocationManager provideLocationManager() {
return (LocationManager) application.getSystemService(Context.LOCATION_SERVICE);
}
}

View File

@ -0,0 +1,22 @@
package com.eleith.calchoochoo.dagger;
import com.eleith.calchoochoo.fragments.DepartingArrivingDialogFragment;
import com.eleith.calchoochoo.ScheduleExplorerActivity;
import com.eleith.calchoochoo.fragments.DestinationSourceFragment;
import com.eleith.calchoochoo.fragments.SearchInputFragment;
import com.eleith.calchoochoo.fragments.SearchResultsFragment;
import dagger.Subcomponent;
@ScheduleExplorerActivityScope
@Subcomponent(modules = ScheduleExplorerActivityModule.class)
public interface ScheduleExplorerActivityComponent {
// injection for activity
void inject(ScheduleExplorerActivity scheduleExplorerActivity);
// injection for fragments
void inject(SearchResultsFragment searchResultsFragment);
void inject(SearchInputFragment searchInputFragment);
void inject(DestinationSourceFragment destinationSourceFragment);
void inject(DepartingArrivingDialogFragment departingArrivingDialogFragment);
}

View File

@ -0,0 +1,31 @@
package com.eleith.calchoochoo.dagger;
import android.support.v4.app.FragmentManager;
import com.eleith.calchoochoo.ScheduleExplorerActivity;
import com.eleith.calchoochoo.SearchResultsViewAdapter;
import com.eleith.calchoochoo.utils.RxBus;
import dagger.Module;
import dagger.Provides;
@Module
public class ScheduleExplorerActivityModule {
private ScheduleExplorerActivity scheduleExplorerActivity;
public ScheduleExplorerActivityModule(ScheduleExplorerActivity scheduleExplorerActivity) {
this.scheduleExplorerActivity = scheduleExplorerActivity;
}
@ScheduleExplorerActivityScope
@Provides
public SearchResultsViewAdapter provideResultsViewAdapter(RxBus rxBus) {
return new SearchResultsViewAdapter(rxBus);
}
@ScheduleExplorerActivityScope
@Provides
public FragmentManager provideFragmentManager() {
return scheduleExplorerActivity.getSupportFragmentManager();
}
}

View File

@ -0,0 +1,12 @@
package com.eleith.calchoochoo.dagger;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.inject.Scope;
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ScheduleExplorerActivityScope {
}

View File

@ -0,0 +1,119 @@
package com.eleith.calchoochoo.fragments;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v4.util.TimeUtils;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AlertDialog;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.eleith.calchoochoo.R;
import com.eleith.calchoochoo.ScheduleExplorerActivity;
import com.eleith.calchoochoo.utils.RxBus;
import com.eleith.calchoochoo.utils.RxMessage;
import com.eleith.calchoochoo.utils.RxMessageKeys;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.w3c.dom.Text;
import java.util.Date;
import javax.inject.Inject;
import butterknife.BindView;
import butterknife.ButterKnife;
public class DepartingArrivingDialogFragment extends android.support.v4.app.DialogFragment {
@Inject RxBus rxBus;
@BindView(R.id.picker) View picker;
@BindView(R.id.timeTabs) TabLayout tabLayout;
@BindView(R.id.dateSpinner) ViewPager viewPager;
@BindView(R.id.dateSpinnerText) TextView dateSpinnerText;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((ScheduleExplorerActivity) getActivity()).getComponent().inject(this);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.fragment_departing_arriving_selector, null);
ButterKnife.bind(this, view);
viewPager.setAdapter(new CustomAdapter(getContext()));
builder.setView(view);
View cancelButton = view.findViewById(R.id.departOrArriveCancel);
cancelButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getDialog().dismiss();
}
});
View selectButton = view.findViewById(R.id.departOrArriveSelect);
selectButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
rxBus.send(new RxMessage(RxMessageKeys.TIME_SELECTED, new Date()));
getDialog().dismiss();
}
});
return builder.create();
}
public class CustomAdapter extends PagerAdapter {
private Date today;
private Date now;
private Context context;
public CustomAdapter(Context context) {
today = new Date();
now = new Date();
this.context = context;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Log.d("poop", "setting date spinner etxt");
dateSpinnerText.setText(today.toString());
container.addView(dateSpinnerText);
return dateSpinnerText;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
@Override
public int getCount() {
return 3;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
}

View File

@ -0,0 +1,97 @@
package com.eleith.calchoochoo.fragments;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.eleith.calchoochoo.R;
import com.eleith.calchoochoo.ScheduleExplorerActivity;
import com.eleith.calchoochoo.data.Stop;
import com.eleith.calchoochoo.utils.BundleKeys;
import com.eleith.calchoochoo.utils.RxBus;
import com.eleith.calchoochoo.utils.RxMessage;
import com.eleith.calchoochoo.utils.RxMessageKeys;
import java.util.Date;
import javax.inject.Inject;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import rx.functions.Action1;
public class DestinationSourceFragment extends Fragment {
private Stop stopDestination;
private Stop stopSource;
@BindView(R.id.destinationEdit) TextView destinationEdit;
@BindView(R.id.sourceEdit) TextView sourceEdit;
@BindView(R.id.timeEdit) TextView timeEdit;
@Inject RxBus rxBus;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((ScheduleExplorerActivity) getActivity()).getComponent().inject(this);
Bundle arguments = getArguments();
if (arguments != null) {
stopDestination = arguments.getParcelable(BundleKeys.DESTINATION);
stopSource = arguments.getParcelable(BundleKeys.SOURCE);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_destination_source, container, false);
ButterKnife.bind(this, view);
if (stopDestination != null) {
destinationEdit.setText(stopDestination.getName());
}
if (stopSource != null) {
sourceEdit.setText(stopSource.getName());
}
rxBus.observeEvents(RxMessage.class).subscribe(handleDestinationSourceFragmentRxMessages());
return view;
}
private Action1<RxMessage> handleDestinationSourceFragmentRxMessages() {
return new Action1<RxMessage>() {
@Override
public void call(RxMessage rxMessage) {
String type = rxMessage.getType();
if (type.equals(RxMessageKeys.TIME_SELECTED)) {
Date date = (Date) rxMessage.getMessage();
timeEdit.setText(date.toString());
}
}
};
}
@OnClick(R.id.destinationEdit)
public void destinationClick() {
rxBus.send(new RxMessage(RxMessageKeys.DESTINATION_SELECTED));
}
@OnClick(R.id.sourceEdit)
public void sourceClick() {
rxBus.send(new RxMessage(RxMessageKeys.SOURCE_SELECTED));
}
@OnClick(R.id.timeEdit)
public void timeClick() {
DepartingArrivingDialogFragment dialog = new DepartingArrivingDialogFragment();
dialog.show(getFragmentManager(), "dialog");
}
}

View File

@ -1,4 +1,4 @@
package com.eleith.calchoochoo;
package com.eleith.calchoochoo.fragments;
import android.content.Context;
import android.os.Bundle;
@ -7,29 +7,17 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.eleith.calchoochoo.R;
public class HomeFragment extends Fragment {
public HomeFragment() {
// Required empty public constructor
}
public static HomeFragment newInstance() {
HomeFragment fragment = new HomeFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_home, container, false);
}

View File

@ -0,0 +1,47 @@
package com.eleith.calchoochoo.fragments;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import com.eleith.calchoochoo.ScheduleExplorerActivity;
import com.eleith.calchoochoo.utils.RxBus;
import com.eleith.calchoochoo.R;
import com.eleith.calchoochoo.utils.RxMessage;
import com.eleith.calchoochoo.utils.RxMessageKeys;
import com.eleith.calchoochoo.utils.RxMessageString;
import javax.inject.Inject;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnTextChanged;
public class SearchInputFragment extends Fragment {
@Inject RxBus rxBus;
@BindView(R.id.searchInput) EditText searchInput;
@OnTextChanged(R.id.searchInput)
public void OnTextChange(CharSequence s) {
rxBus.send(new RxMessageString(RxMessageKeys.SEARCH_INPUT_STRING, s.toString()));
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((ScheduleExplorerActivity) getActivity()).getComponent().inject(this);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_search_input, container, false);
ButterKnife.bind(this, view);
return view;
}
}

View File

@ -1,39 +1,45 @@
package com.eleith.calchoochoo;
package com.eleith.calchoochoo.fragments;
import android.content.Context;
import android.location.Location;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.util.Pair;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.eleith.calchoochoo.R;
import com.eleith.calchoochoo.ScheduleExplorerActivity;
import com.eleith.calchoochoo.SearchResultsViewAdapter;
import com.eleith.calchoochoo.data.Stop;
import com.eleith.calchoochoo.utils.BundleKeys;
import com.eleith.calchoochoo.utils.RxBus;
import com.eleith.calchoochoo.utils.RxMessage;
import com.eleith.calchoochoo.utils.RxMessageKeys;
import com.eleith.calchoochoo.utils.RxMessagePair;
import com.eleith.calchoochoo.utils.RxMessageString;
import java.util.ArrayList;
import javax.inject.Inject;
import rx.functions.Action1;
public class SearchResultsFragment extends Fragment {
private SearchResultsFragmentListener listener;
private ArrayList<Stop> stops;
private SearchResultsViewAdapter searchResultsViewAdapter;
private RecyclerView recyclerView;
private Location location;
private String searchReason;
public interface SearchResultsFragmentListener {
void onSearchResultSelect(Stop stop, String searchReason);
}
public SearchResultsFragment() {
// Required empty public constructor
}
@Inject RxBus rxBus;
@Inject SearchResultsViewAdapter searchResultsViewAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((ScheduleExplorerActivity) getActivity()).getComponent().inject(this);
unPackBundle(savedInstanceState != null ? savedInstanceState : getArguments());
}
@ -44,14 +50,11 @@ public class SearchResultsFragment extends Fragment {
recyclerView = (RecyclerView) view.findViewById(R.id.searchResults);
if (recyclerView != null) {
searchResultsViewAdapter = new SearchResultsViewAdapter(stops, location);
searchResultsViewAdapter.setStops(stops);
searchResultsViewAdapter.setLocation(location);
searchResultsViewAdapter.setSearchResultsViewAdapterListener(new SearchResultsViewAdapter.SearchResultsViewAdapterListener() {
@Override
public void onSearchResultSelect(Stop stop) {
listener.onSearchResultSelect(stop, searchReason);
}
});
rxBus.observeEvents(RxMessage.class).subscribe(handleScheduleExplorerRxMessages());
recyclerView.setLayoutManager(new LinearLayoutManager(view.getContext()));
recyclerView.setAdapter(searchResultsViewAdapter);
}
@ -59,20 +62,19 @@ public class SearchResultsFragment extends Fragment {
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof SearchResultsFragmentListener) {
listener = (SearchResultsFragmentListener) context;
} else {
throw new RuntimeException(context.toString() + " must implement SearchResultsFragmentListener");
}
}
private Action1<RxMessage> handleScheduleExplorerRxMessages() {
return new Action1<RxMessage>() {
@Override
public void call(RxMessage rxMessage) {
String type = rxMessage.getType();
@Override
public void onDetach() {
super.onDetach();
listener = null;
if (type.equals(RxMessageKeys.SEARCH_RESULT_STOP)) {
Stop stop = (Stop) rxMessage.getMessage();
Pair<Stop, String> pair = new Pair<Stop, String>(stop, searchReason);
rxBus.send(new RxMessagePair<Stop, String>(RxMessageKeys.SEARCH_RESULT_PAIR, pair));
}
}
};
}
private void unPackBundle(Bundle bundle) {

View File

@ -1,4 +1,4 @@
package com.eleith.calchoochoo;
package com.eleith.calchoochoo.utils;
public class BundleKeys {
public static final String STOPS = "stops";

View File

@ -1,4 +1,4 @@
package com.eleith.calchoochoo;
package com.eleith.calchoochoo.utils;
public class DistanceUtils {
public static Double METERS_IN_A_MILE = 1609.34;

View File

@ -1,4 +1,4 @@
package com.eleith.calchoochoo;
package com.eleith.calchoochoo.utils;
public class Permissions {
public final static int READ_GPS = 1;

View File

@ -0,0 +1,29 @@
package com.eleith.calchoochoo.utils;
import rx.Observable;
import rx.functions.Func1;
import rx.subjects.PublishSubject;
import rx.subjects.SerializedSubject;
import rx.subjects.Subject;
//rx observer as an event bus: http://blog.kaush.co/2014/12/24/implementing-an-event-bus-with-rxjava-rxbus/
public class RxBus {
private final Subject<Object, Object> bus = new SerializedSubject<>(PublishSubject.create());
public void send(Object o) {
bus.onNext(o);
}
public Observable<Object> toObservable() {
return bus;
}
public <Event extends Object> Observable<Event> observeEvents(Class<Event> eventClass) {
return bus.ofType(eventClass);
}
public boolean hasObservers() {
return bus.hasObservers();
}
}

View File

@ -0,0 +1,35 @@
package com.eleith.calchoochoo.utils;
public class RxMessage {
private String type = "";
private Object message;
RxMessage() {
}
public RxMessage(String type, Object message) {
this.type = type;
this.message = message;
}
public RxMessage(String type) {
this.type = type;
}
public void setType(String type) {
this.type = type;
}
public void setMessage(Object message) {
this.message = message;
}
public String getType() {
return this.type;
}
public Object getMessage() {
return this.message;
}
}

View File

@ -0,0 +1,15 @@
package com.eleith.calchoochoo.utils;
import java.util.Date;
public class RxMessageDate extends RxMessage {
public RxMessageDate(String type, Date date) {
this.setType(type);
this.setMessage(date);
}
public Date getMessageDate() {
return (Date) super.getMessage();
}
}

View File

@ -0,0 +1,10 @@
package com.eleith.calchoochoo.utils;
public class RxMessageKeys {
public static final String SEARCH_INPUT_STRING = "searchInputString";
public static final String SEARCH_RESULT_PAIR = "searchResultPair";
public static final String SEARCH_RESULT_STOP = "searchResultStop";
public static final String DESTINATION_SELECTED = "destinationSelected";
public static final String SOURCE_SELECTED = "arrivalSelected";
public static final String TIME_SELECTED = "timeSelected";
}

View File

@ -0,0 +1,16 @@
package com.eleith.calchoochoo.utils;
import android.support.v4.util.Pair;
public class RxMessagePair<F, S> extends RxMessage {
public RxMessagePair(String type, Pair<F, S> message) {
this.setType(type);
this.setMessage(message);
}
@SuppressWarnings("unchecked")
public Pair<F, S> getMessagePair() {
return (Pair<F, S>) super.getMessage();
}
}

View File

@ -0,0 +1,13 @@
package com.eleith.calchoochoo.utils;
public class RxMessageString extends RxMessage {
public RxMessageString(String type, String message) {
this.setType(type);
this.setMessage(message);
}
public String getMessageString() {
return (String) super.getMessage();
}
}

View File

@ -2,34 +2,31 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:context=".DepartingArrivingDialog">
android:padding="20dp"
tools:context=".fragments.DepartingArrivingDialogFragment">
<LinearLayout
android:id="@+id/tabs"
<android.support.design.widget.TabLayout
android:id="@+id/timeTabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:layout_gravity="top">
<TextView
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Depart at"
android:textAlignment="center"/>
android:layout_height="match_parent"
android:text="Arrive By"/>
<TextView
<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Arrive by"
android:textAlignment="center"/>
</LinearLayout>
android:layout_height="match_parent"
android:text="Depart At"/>
</android.support.design.widget.TabLayout>
<LinearLayout
android:id="@+id/picker"
android:layout_below="@id/timeTabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/tabs"
android:orientation="horizontal">
<TimePicker
@ -42,21 +39,28 @@
</LinearLayout>
<LinearLayout
android:id="@+id/date"
android:id="@+id/datePicker"
android:layout_below="@id/picker"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<android.support.v4.view.ViewPager
android:id="@+id/dateSpinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</HorizontalScrollView>
<TextView
android:id="@+id/dateSpinnerText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</android.support.v4.view.ViewPager>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/date"
android:layout_below="@id/datePicker"
android:layoutDirection="rtl"
android:orientation="horizontal">

View File

@ -2,7 +2,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.eleith.calchoochoo.DestinationSourceFragment">
tools:context="com.eleith.calchoochoo.fragments.DestinationSourceFragment">
<LinearLayout
android:layout_width="match_parent"

View File

@ -2,7 +2,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.eleith.calchoochoo.HomeFragment">
tools:context="com.eleith.calchoochoo.fragments.HomeFragment">
<TextView
android:layout_width="match_parent"

View File

@ -2,7 +2,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.eleith.calchoochoo.SearchInputFragment">
tools:context="com.eleith.calchoochoo.fragments.SearchInputFragment">
<EditText
android:id="@+id/searchInput"

View File

@ -4,7 +4,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.eleith.calchoochoo.SearchResultsFragment">
tools:context="com.eleith.calchoochoo.fragments.SearchResultsFragment">
<TextView
android:layout_width="match_parent"
@ -24,7 +24,7 @@
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
app:layoutManager="LinearLayoutManager"
tools:context="com.eleith.calchoochoo.SearchResultsFragment"
tools:context="com.eleith.calchoochoo.fragments.SearchResultsFragment"
tools:listitem="@layout/fragment_search_result" />
</LinearLayout>

View File

@ -5,8 +5,8 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.0'
classpath 'com.android.tools.build:gradle:2.2.3'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
@ -15,6 +15,7 @@ buildscript {
allprojects {
repositories {
jcenter()
maven { url "https://www.jitpack.io" }
}
}