From 6ccc608a1e1ab638a46f8f716ca975a42413684c Mon Sep 17 00:00:00 2001 From: Paul Hawke Date: Sun, 9 Jul 2017 16:03:06 -0500 Subject: [PATCH] Converted nearby list to recycler view and fixed a few issues pointed out by static code analysis. --- app/build.gradle | 4 + .../nrw/commons/nearby/NearbyActivity.java | 24 +--- .../nrw/commons/nearby/NearbyAdapter.java | 44 ------ .../commons/nearby/NearbyAdapterFactory.java | 24 ++++ .../nrw/commons/nearby/NearbyBaseMarker.java | 22 +-- .../nrw/commons/nearby/NearbyInfoDialog.java | 19 +-- .../commons/nearby/NearbyListFragment.java | 76 ++++------ .../nrw/commons/nearby/NearbyMapFragment.java | 11 +- .../free/nrw/commons/nearby/NearbyMarker.java | 12 +- .../free/nrw/commons/nearby/NearbyPlaces.java | 7 +- .../nrw/commons/nearby/NearbyViewHolder.java | 35 ----- .../fr/free/nrw/commons/nearby/Place.java | 6 +- .../nrw/commons/nearby/PlaceRenderer.java | 64 +++++++++ app/src/main/res/layout/fragment_nearby.xml | 2 +- .../nearby/NearbyAdapterFactoryTest.java | 135 ++++++++++++++++++ 15 files changed, 292 insertions(+), 193 deletions(-) delete mode 100644 app/src/main/java/fr/free/nrw/commons/nearby/NearbyAdapter.java create mode 100644 app/src/main/java/fr/free/nrw/commons/nearby/NearbyAdapterFactory.java delete mode 100644 app/src/main/java/fr/free/nrw/commons/nearby/NearbyViewHolder.java create mode 100644 app/src/main/java/fr/free/nrw/commons/nearby/PlaceRenderer.java create mode 100644 app/src/test/java/fr/free/nrw/commons/nearby/NearbyAdapterFactoryTest.java diff --git a/app/build.gradle b/app/build.gradle index 6aceefe73..ddd05244a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,6 +15,7 @@ dependencies { compile "com.android.support:design:${project.supportLibVersion}" compile 'com.google.code.gson:gson:2.7' compile "com.jakewharton:butterknife:$BUTTERKNIFE_VERSION" + compile 'com.github.pedrovgs:renderers:3.3.0' annotationProcessor "com.jakewharton:butterknife-compiler:$BUTTERKNIFE_VERSION" compile 'com.jakewharton.timber:timber:4.5.1' compile ('com.mapbox.mapboxsdk:mapbox-android-sdk:5.1.0@aar'){ @@ -25,6 +26,9 @@ dependencies { compile "com.google.guava:guava:${GUAVA_VERSION}" testCompile 'junit:junit:4.12' + testCompile ('org.robolectric:robolectric:3.3.2') { + exclude module: 'guava' + } androidTestCompile "com.android.support:support-annotations:${project.supportLibVersion}" androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2' diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyActivity.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyActivity.java index 731d9af87..ec7d62887 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyActivity.java @@ -30,8 +30,8 @@ import java.util.List; import butterknife.BindView; import butterknife.ButterKnife; -import fr.free.nrw.commons.R; import fr.free.nrw.commons.CommonsApplication; +import fr.free.nrw.commons.R; import fr.free.nrw.commons.location.LatLng; import fr.free.nrw.commons.location.LocationServiceManager; import fr.free.nrw.commons.theme.NavigationBaseActivity; @@ -41,8 +41,7 @@ import timber.log.Timber; public class NearbyActivity extends NavigationBaseActivity { - @BindView(R.id.progressBar) - ProgressBar progressBar; + @BindView(R.id.progressBar) ProgressBar progressBar; private boolean isMapViewActive = false; private static final int LOCATION_REQUEST = 1; @@ -133,7 +132,7 @@ public class NearbyActivity extends NavigationBaseActivity { } } - protected void checkGps() { + private void checkGps() { LocationManager manager = (LocationManager) getSystemService(LOCATION_SERVICE); if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { Timber.d("GPS is not enabled"); @@ -202,15 +201,11 @@ public class NearbyActivity extends NavigationBaseActivity { } } - protected void refreshView() { + private void refreshView() { nearbyAsyncTask = new NearbyAsyncTask(this); nearbyAsyncTask.execute(); } - public LocationServiceManager getLocationManager() { - return locationManager; - } - @Override protected void onDestroy() { super.onDestroy(); @@ -221,17 +216,12 @@ public class NearbyActivity extends NavigationBaseActivity { private class NearbyAsyncTask extends AsyncTask> { - private Context mContext; + private final Context mContext; private NearbyAsyncTask (Context context) { mContext = context; } - @Override - protected void onPreExecute() { - super.onPreExecute(); - } - @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); @@ -284,7 +274,7 @@ public class NearbyActivity extends NavigationBaseActivity { /** * Calls fragment for map view. */ - public void setMapFragment() { + private void setMapFragment() { FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); Fragment fragment = new NearbyMapFragment(); fragment.setArguments(bundle); @@ -295,7 +285,7 @@ public class NearbyActivity extends NavigationBaseActivity { /** * Calls fragment for list view. */ - public void setListFragment() { + private void setListFragment() { FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); Fragment fragment = new NearbyListFragment(); fragment.setArguments(bundle); diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyAdapter.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyAdapter.java deleted file mode 100644 index d2ad0b978..000000000 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyAdapter.java +++ /dev/null @@ -1,44 +0,0 @@ -package fr.free.nrw.commons.nearby; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; - -import fr.free.nrw.commons.R; -import timber.log.Timber; - -public class NearbyAdapter extends ArrayAdapter { - - /** Accepts activity context and list of places. - * @param context activity context - */ - public NearbyAdapter(Context context) { - super(context, R.layout.item_place); - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - // Get the data item for this position - Place place = getItem(position); - Timber.v(String.valueOf(place)); - - // Check if an existing view is being reused, otherwise inflate the view - if (convertView == null) { - convertView = LayoutInflater.from(getContext()) - .inflate(R.layout.item_place, parent, false); - } - - NearbyViewHolder viewHolder = new NearbyViewHolder(convertView); - viewHolder.bindModel(getContext(), place); - // Return the completed view to render on screen - return convertView; - } - - @Override - public long getItemId(int position) { - // TODO: use Wikidata Q-ID instead? - return position; - } -} diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyAdapterFactory.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyAdapterFactory.java new file mode 100644 index 000000000..5fffcab2a --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyAdapterFactory.java @@ -0,0 +1,24 @@ +package fr.free.nrw.commons.nearby; + +import com.pedrogomez.renderers.ListAdapteeCollection; +import com.pedrogomez.renderers.RVRendererAdapter; +import com.pedrogomez.renderers.RendererBuilder; + +import java.util.Collections; +import java.util.List; + +class NearbyAdapterFactory { + private PlaceRenderer.PlaceClickedListener listener; + + NearbyAdapterFactory(PlaceRenderer.PlaceClickedListener listener) { + this.listener = listener; + } + + public RVRendererAdapter create(List placeList) { + RendererBuilder builder = new RendererBuilder() + .bind(Place.class, new PlaceRenderer(listener)); + ListAdapteeCollection collection = new ListAdapteeCollection<>( + placeList != null ? placeList : Collections.emptyList()); + return new RVRendererAdapter<>(builder, collection); + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyBaseMarker.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyBaseMarker.java index 686b3e6ce..e0d08f8cb 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyBaseMarker.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyBaseMarker.java @@ -17,16 +17,11 @@ import fr.free.nrw.commons.utils.UriSerializer; public class NearbyBaseMarker extends BaseMarkerOptions { private Place place; - public NearbyBaseMarker() { + NearbyBaseMarker() { } - public NearbyBaseMarker place(Place place) { - this.place = place; - return getThis(); - } - - public NearbyBaseMarker(Parcel in) { + private NearbyBaseMarker(Parcel in) { Gson gson = new GsonBuilder() .registerTypeAdapter(Uri.class, new UriDeserializer()) .create(); @@ -42,6 +37,11 @@ public class NearbyBaseMarker extends BaseMarkerOptions CREATOR = new Parcelable.Creator() { public NearbyBaseMarker createFromParcel(Parcel in) { diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyInfoDialog.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyInfoDialog.java index bc51dc679..bb2d2fed9 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyInfoDialog.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyInfoDialog.java @@ -29,19 +29,12 @@ public class NearbyInfoDialog extends OverlayDialog { private final static String ARG_LONGITUDE = "longitude"; private final static String ARG_SITE_LINK = "sitelink"; - @BindView(R.id.link_preview_title) - TextView placeTitle; - @BindView(R.id.link_preview_extract) - TextView placeDescription; - - @BindView(R.id.link_preview_go_button) - TextView goToButton; - - @BindView(R.id.link_preview_overflow_button) - ImageView overflowButton; + @BindView(R.id.link_preview_title) TextView placeTitle; + @BindView(R.id.link_preview_extract) TextView placeDescription; + @BindView(R.id.link_preview_go_button) TextView goToButton; + @BindView(R.id.link_preview_overflow_button) ImageView overflowButton; private Unbinder unbinder; - private LatLng location; private Sitelinks sitelinks; @@ -64,7 +57,7 @@ public class NearbyInfoDialog extends OverlayDialog { private void getArticleLink(Bundle bundle) { this.sitelinks = bundle.getParcelable(ARG_SITE_LINK); - if (sitelinks.getWikipediaLink().equals(Uri.EMPTY)) { + if (sitelinks == null || Uri.EMPTY.equals(sitelinks.getWikipediaLink())) { goToButton.setVisibility(View.GONE); } @@ -99,7 +92,7 @@ public class NearbyInfoDialog extends OverlayDialog { || !sitelinks.getWikidataLink().equals(Uri.EMPTY); } - private PopupMenu.OnMenuItemClickListener menuListener = new PopupMenu + private final PopupMenu.OnMenuItemClickListener menuListener = new PopupMenu .OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyListFragment.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyListFragment.java index b3759f228..a8527ab46 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyListFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyListFragment.java @@ -2,37 +2,35 @@ package fr.free.nrw.commons.nearby; import android.net.Uri; import android.os.Bundle; -import android.support.v4.app.ListFragment; +import android.support.v4.app.Fragment; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ListView; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import java.lang.reflect.Type; +import java.util.Collections; import java.util.List; -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnItemClick; import fr.free.nrw.commons.R; import fr.free.nrw.commons.location.LatLng; import fr.free.nrw.commons.utils.UriDeserializer; import timber.log.Timber; -public class NearbyListFragment extends ListFragment { - private List placeList; +public class NearbyListFragment extends Fragment { + private static final Type LIST_TYPE = new TypeToken>() { + }.getType(); + private static final Type CUR_LAT_LNG_TYPE = new TypeToken() { + }.getType(); + private static final Gson gson = new GsonBuilder().registerTypeAdapter(Uri.class, new UriDeserializer()).create(); - @BindView(R.id.listView) ListView listview; - - - private NearbyAdapter adapter; - - public NearbyListFragment() { - } + private NearbyAdapterFactory adapterFactory; + private RecyclerView recyclerView; @Override public void onCreate(Bundle savedInstanceState) { @@ -41,55 +39,37 @@ public class NearbyListFragment extends ListFragment { } @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Timber.d("NearbyListFragment created"); View view = inflater.inflate(R.layout.fragment_nearby, container, false); - ButterKnife.bind(this, view); - adapter = new NearbyAdapter(getActivity()); - listview.setAdapter(adapter); + recyclerView = (RecyclerView) view.findViewById(R.id.listView); + recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + adapterFactory = new NearbyAdapterFactory(new PlaceRenderer.PlaceClickedListener() { + @Override + public void placeClicked(Place place) { + NearbyInfoDialog.showYourself(getActivity(), place); + } + }); return view; } @Override public void onViewCreated(View view, Bundle savedInstanceState) { - // Check that this is the first time view is created, // to avoid double list when screen orientation changed + List placeList = Collections.emptyList(); + Bundle bundle = this.getArguments(); - Gson gson = new GsonBuilder() - .registerTypeAdapter(Uri.class, new UriDeserializer()) - .create(); if (bundle != null) { String gsonPlaceList = bundle.getString("PlaceList"); + placeList = gson.fromJson(gsonPlaceList, LIST_TYPE); + String gsonLatLng = bundle.getString("CurLatLng"); - Type listType = new TypeToken>() {}.getType(); - placeList = gson.fromJson(gsonPlaceList, listType); - Type curLatLngType = new TypeToken() {}.getType(); - LatLng curLatLng = gson.fromJson(gsonLatLng, curLatLngType); + LatLng curLatLng = gson.fromJson(gsonLatLng, CUR_LAT_LNG_TYPE); + placeList = NearbyController.loadAttractionsFromLocationToPlaces(curLatLng, placeList); } - if (savedInstanceState == null) { - adapter.clear(); - Timber.d("Saved instance state is null, populating ListView"); - } - adapter.clear(); - adapter.addAll(placeList); - adapter.notifyDataSetChanged(); - } - - @OnItemClick(R.id.listView) - void onItemClicked(int position) { - Place place = (Place) listview.getItemAtPosition(position); - LatLng placeLatLng = place.location; - - double latitude = placeLatLng.getLatitude(); - double longitude = placeLatLng.getLongitude(); - - Timber.d("Item at position %d has coords: Lat: %f Long: %f", position, latitude, longitude); - - NearbyInfoDialog.showYourself(getActivity(), place); + recyclerView.setAdapter(adapterFactory.create(placeList)); } } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMapFragment.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMapFragment.java index 6aad0a639..54c1a565e 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMapFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMapFragment.java @@ -5,7 +5,6 @@ import android.net.Uri; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -39,7 +38,6 @@ public class NearbyMapFragment extends android.support.v4.app.Fragment { private fr.free.nrw.commons.location.LatLng curLatLng; public NearbyMapFragment() { - } @Override @@ -123,7 +121,7 @@ public class NearbyMapFragment extends android.support.v4.app.Fragment { * which represents the user's position with an accuracy * of 95%. */ - public void addCurrentLocationMarker(MapboxMap mapboxMap) { + private void addCurrentLocationMarker(MapboxMap mapboxMap) { MarkerOptions currentLocationMarker = new MarkerOptions() .position(new LatLng(curLatLng.getLatitude(), curLatLng.getLongitude())); mapboxMap.addMarker(currentLocationMarker); @@ -146,7 +144,7 @@ public class NearbyMapFragment extends android.support.v4.app.Fragment { * * @return List List of LatLng points of the circle. */ - public List createCircleArray( + private List createCircleArray( double centerLat, double centerLong, float radius, int nodes) { List circle = new ArrayList<>(); float radiusKilometer = radius / 1000; @@ -164,11 +162,6 @@ public class NearbyMapFragment extends android.support.v4.app.Fragment { return circle; } - @Override - public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - } - @Override public void onStart() { if (mapView != null) { diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMarker.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMarker.java index c65ede203..a552579c9 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMarker.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMarker.java @@ -2,8 +2,8 @@ package fr.free.nrw.commons.nearby; import com.mapbox.mapboxsdk.annotations.Marker; -public class NearbyMarker extends Marker { - private Place place; +class NearbyMarker extends Marker { + private final Place place; private NearbyBaseMarker nearbyBaseMarker; /** @@ -11,21 +11,17 @@ public class NearbyMarker extends Marker { * * @param baseMarkerOptions The builder used to construct the Marker. */ - public NearbyMarker(NearbyBaseMarker baseMarkerOptions, Place place) { + NearbyMarker(NearbyBaseMarker baseMarkerOptions, Place place) { super(baseMarkerOptions); this.place = place; this.nearbyBaseMarker = baseMarkerOptions; } - public NearbyBaseMarker getNearbyBaseMarker() { + NearbyBaseMarker getNearbyBaseMarker() { return nearbyBaseMarker; } public Place getPlace() { return place; } - - public void setNearbyBaseMarker(NearbyBaseMarker nearbyBaseMarker) { - this.nearbyBaseMarker = nearbyBaseMarker; - } } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyPlaces.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyPlaces.java index 6f64afea6..50d661ef6 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyPlaces.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyPlaces.java @@ -34,8 +34,7 @@ public class NearbyPlaces { public NearbyPlaces() { try { - String query = FileUtils.readFromResource("/assets/queries/nearby_query.rq"); - wikidataQuery = query; + wikidataQuery = FileUtils.readFromResource("/assets/queries/nearby_query.rq"); Timber.v(wikidataQuery); } catch (IOException e) { throw new RuntimeException(e); @@ -106,8 +105,8 @@ public class NearbyPlaces { String wikiDataLink = Utils.stripLocalizedString(fields[1]); String icon = fields[5]; - double latitude = 0; - double longitude = 0; + double latitude; + double longitude; Matcher matcher = Pattern.compile("Point\\(([^ ]+) ([^ ]+)\\)").matcher(point); if (!matcher.find()) { diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyViewHolder.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyViewHolder.java deleted file mode 100644 index e5cc6f547..000000000 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyViewHolder.java +++ /dev/null @@ -1,35 +0,0 @@ -package fr.free.nrw.commons.nearby; - -import android.content.Context; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; - -import butterknife.BindView; -import butterknife.ButterKnife; -import fr.free.nrw.commons.R; -import fr.free.nrw.commons.ViewHolder; - -public class NearbyViewHolder implements ViewHolder { - @BindView(R.id.tvName) TextView tvName; - @BindView(R.id.tvDesc) TextView tvDesc; - @BindView(R.id.distance) TextView distance; - @BindView(R.id.icon) ImageView icon; - - public NearbyViewHolder(View view) { - ButterKnife.bind(this, view); - } - - @Override - public void bindModel(Context context, Place place) { - // Populate the data into the template view using the data object - tvName.setText(place.name); - String descriptionText = place.getDescription().getText(); - if (descriptionText.equals("?")) { - descriptionText = context.getString(R.string.no_description_found); - } - tvDesc.setText(descriptionText); - distance.setText(place.distance); - icon.setImageResource(place.getDescription().getIcon()); - } -} diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/Place.java b/app/src/main/java/fr/free/nrw/commons/nearby/Place.java index 94c6f40be..428fcf6de 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/Place.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/Place.java @@ -14,14 +14,14 @@ public class Place { public final String name; private final Description description; - public final String longDescription; - public final Uri secondaryImageUrl; + private final String longDescription; + private final Uri secondaryImageUrl; public final LatLng location; public Bitmap image; public Bitmap secondaryImage; public String distance; - public Sitelinks siteLinks; + public final Sitelinks siteLinks; public Place(String name, Description description, String longDescription, diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/PlaceRenderer.java b/app/src/main/java/fr/free/nrw/commons/nearby/PlaceRenderer.java new file mode 100644 index 000000000..12e24f1ae --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/nearby/PlaceRenderer.java @@ -0,0 +1,64 @@ +package fr.free.nrw.commons.nearby; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.pedrogomez.renderers.Renderer; + +import butterknife.BindView; +import butterknife.ButterKnife; +import fr.free.nrw.commons.R; + +class PlaceRenderer extends Renderer { + @BindView(R.id.tvName) TextView tvName; + @BindView(R.id.tvDesc) TextView tvDesc; + @BindView(R.id.distance) TextView distance; + @BindView(R.id.icon) ImageView icon; + private final PlaceClickedListener listener; + + PlaceRenderer(PlaceClickedListener listener) { + this.listener = listener; + } + + @Override + protected View inflate(LayoutInflater layoutInflater, ViewGroup viewGroup) { + return layoutInflater.inflate(R.layout.item_place, viewGroup, false); + } + + @Override + protected void setUpView(View view) { + ButterKnife.bind(this, view); + } + + @Override + protected void hookListeners(View view) { + view.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (listener != null) { + listener.placeClicked(getContent()); + } + } + }); + } + + @Override + public void render() { + Place place = getContent(); + tvName.setText(place.name); + String descriptionText = place.getDescription().getText(); + if (descriptionText.equals("?")) { + descriptionText = getContext().getString(R.string.no_description_found); + } + tvDesc.setText(descriptionText); + distance.setText(place.distance); + icon.setImageResource(place.getDescription().getIcon()); + } + + interface PlaceClickedListener { + void placeClicked(Place place); + } +} diff --git a/app/src/main/res/layout/fragment_nearby.xml b/app/src/main/res/layout/fragment_nearby.xml index fed924f0d..ef580fe99 100644 --- a/app/src/main/res/layout/fragment_nearby.xml +++ b/app/src/main/res/layout/fragment_nearby.xml @@ -4,7 +4,7 @@ android:orientation="vertical" > - result = testObject.create(null); + assertNotNull(result); + assertEquals(0, result.getItemCount()); + } + + @Test + public void factoryHandlesEmptyListAndNullListener() { + NearbyAdapterFactory testObject = new NearbyAdapterFactory(null); + RVRendererAdapter result = testObject.create(Collections.emptyList()); + assertNotNull(result); + assertEquals(0, result.getItemCount()); + } + + @Test + public void factoryHandlesNonEmptyListAndNullListener() { + NearbyAdapterFactory testObject = new NearbyAdapterFactory(null); + RVRendererAdapter result = testObject.create(Collections.singletonList(PLACE)); + assertNotNull(result); + assertEquals(1, result.getItemCount()); + assertEquals(PLACE, result.getItem(0)); + } + + @Test + public void rendererCorrectlyBound() { + NearbyAdapterFactory testObject = new NearbyAdapterFactory(null); + RVRendererAdapter result = testObject.create(Collections.singletonList(PLACE)); + + RendererViewHolder viewHolder = result.onCreateViewHolder(new FrameLayout(RuntimeEnvironment.application), result.getItemViewType(0)); + assertNotNull(viewHolder); + result.bindViewHolder(viewHolder, 0); + + assertNotNull(viewHolder.itemView.findViewById(R.id.tvName)); + assertEquals("name", ((TextView) viewHolder.itemView.findViewById(R.id.tvName)).getText().toString()); + + assertNotNull(viewHolder.itemView.findViewById(R.id.tvDesc)); + assertEquals("airport", ((TextView) viewHolder.itemView.findViewById(R.id.tvDesc)).getText().toString()); + + assertNotNull(viewHolder.itemView.findViewById(R.id.distance)); + assertEquals("", ((TextView) viewHolder.itemView.findViewById(R.id.distance)).getText().toString()); + + assertNotNull(viewHolder.itemView.findViewById(R.id.icon)); + ShadowDrawable shadow = Shadows.shadowOf(((ImageView) viewHolder.itemView.findViewById(R.id.icon)).getDrawable()); + assertEquals(R.drawable.round_icon_airport, shadow.getCreatedFromResId()); + } + + @Test + public void rendererCorrectlyBoundForUnknownPlace() { + NearbyAdapterFactory testObject = new NearbyAdapterFactory(null); + RVRendererAdapter result = testObject.create(Collections.singletonList(UNKNOWN_PLACE)); + + RendererViewHolder viewHolder = result.onCreateViewHolder(new FrameLayout(RuntimeEnvironment.application), result.getItemViewType(0)); + assertNotNull(viewHolder); + result.bindViewHolder(viewHolder, 0); + + assertNotNull(viewHolder.itemView.findViewById(R.id.tvName)); + assertEquals("name", ((TextView) viewHolder.itemView.findViewById(R.id.tvName)).getText().toString()); + + assertNotNull(viewHolder.itemView.findViewById(R.id.tvDesc)); + assertEquals("no description found", ((TextView) viewHolder.itemView.findViewById(R.id.tvDesc)).getText().toString()); + + assertNotNull(viewHolder.itemView.findViewById(R.id.distance)); + assertEquals("", ((TextView) viewHolder.itemView.findViewById(R.id.distance)).getText().toString()); + + assertNotNull(viewHolder.itemView.findViewById(R.id.icon)); + ShadowDrawable shadow = Shadows.shadowOf(((ImageView) viewHolder.itemView.findViewById(R.id.icon)).getDrawable()); + assertEquals(R.drawable.round_icon_unknown, shadow.getCreatedFromResId()); + } + + @Test + public void clickView() { + NearbyAdapterFactory testObject = new NearbyAdapterFactory(new PlaceRenderer.PlaceClickedListener() { + @Override + public void placeClicked(Place place) { + clickedPlace = place; + } + }); + RVRendererAdapter result = testObject.create(Collections.singletonList(PLACE)); + RendererViewHolder viewHolder = result.onCreateViewHolder(new FrameLayout(RuntimeEnvironment.application), result.getItemViewType(0)); + assertNotNull(viewHolder); + result.bindViewHolder(viewHolder, 0); + + viewHolder.itemView.performClick(); + + assertEquals(PLACE, clickedPlace); + } + + @Test + public void clickViewHandlesMisconfiguredListener() { + NearbyAdapterFactory testObject = new NearbyAdapterFactory(null); + RVRendererAdapter result = testObject.create(Collections.singletonList(PLACE)); + RendererViewHolder viewHolder = result.onCreateViewHolder(new FrameLayout(RuntimeEnvironment.application), result.getItemViewType(0)); + assertNotNull(viewHolder); + result.bindViewHolder(viewHolder, 0); + + viewHolder.itemView.performClick(); + } +} \ No newline at end of file