diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/adapters/PlacesAdapter.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/adapters/PlacesAdapter.java index dfc385e..926aa59 100644 --- a/app/src/main/java/pl/tpolgrabia/urbanexplorer/adapters/PlacesAdapter.java +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/adapters/PlacesAdapter.java @@ -1,6 +1,7 @@ package pl.tpolgrabia.urbanexplorer.adapters; import android.content.Context; +import android.graphics.BitmapFactory; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -22,11 +23,9 @@ import java.util.List; */ public class PlacesAdapter extends ArrayAdapter { - private final GooglePlacesResponse objects; - public PlacesAdapter(Context context, GooglePlacesResponse objects) { - super(context, R.layout.google_place_item, objects.getPlaces()); - this.objects = objects; + public PlacesAdapter(Context context, List objects) { + super(context, R.layout.google_place_item, objects); } @Override @@ -40,6 +39,10 @@ public class PlacesAdapter extends ArrayAdapter { } GooglePlaceResult item = getItem(position); + if (item.getId().equals(resultView.getTag())) { + return resultView; + } + final List photos = item.getPhotos(); String photoRef = photos != null && !photos.isEmpty() ? photos.get(0).getPhotoReference() : null; String photoUrl = photoRef == null ? null : "https://maps.googleapis.com/maps/api/place/photo?photoreference=" @@ -55,12 +58,16 @@ public class PlacesAdapter extends ArrayAdapter { placeRateWidget.setText("" + item.getRating()); ImageView placePreviewWidget = (ImageView)resultView.findViewById(R.id.place_img_preview); + placePreviewWidget.setImageBitmap(BitmapFactory.decodeResource(getContext().getResources(), R.drawable.noimage)); + ImageLoader.getInstance().displayImage( photoUrl != null ? photoUrl : item.getIcon(), placePreviewWidget, MainActivity.options); + resultView.setTag(item.getId()); + return resultView; } } diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/GooglePlacesResponse.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/GooglePlacesResponse.java index d367a94..2a8bca4 100644 --- a/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/GooglePlacesResponse.java +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/dto/GooglePlacesResponse.java @@ -10,6 +10,9 @@ import java.util.List; public class GooglePlacesResponse { private List places; + private String nextPageToken; + private String originalPageToken; + public List getPlaces() { return places; } @@ -18,10 +21,28 @@ public class GooglePlacesResponse { this.places = places; } + public String getNextPageToken() { + return nextPageToken; + } + + public void setNextPageToken(String nextPageToken) { + this.nextPageToken = nextPageToken; + } + + public void setOriginalPageToken(String originalPageToken) { + this.originalPageToken = originalPageToken; + } + + public String getOriginalPageToken() { + return originalPageToken; + } + @Override public String toString() { return "GooglePlacesResponse{" + "places=" + places + + ", nextPageToken='" + nextPageToken + '\'' + + ", originalPageToken='" + originalPageToken + '\'' + '}'; } } diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/fragments/PlacesFragment.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/fragments/PlacesFragment.java index 9e03855..1df2bd1 100644 --- a/app/src/main/java/pl/tpolgrabia/urbanexplorer/fragments/PlacesFragment.java +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/fragments/PlacesFragment.java @@ -8,13 +8,15 @@ import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.ListAdapter; import android.widget.ListView; import android.widget.TextView; -import org.apache.http.HttpStatus; +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import pl.tpolgrabia.googleutils.callback.LocationGeoCoderCallback; -import pl.tpolgrabia.googleutils.callback.PlacesCallback; +import pl.tpolgrabia.googleutils.constants.GooglePlacesConstants; import pl.tpolgrabia.googleutils.dto.GooglePlaceResult; import pl.tpolgrabia.googleutils.utils.GeocoderUtils; import pl.tpolgrabia.googleutils.utils.PlacesUtils; @@ -24,11 +26,15 @@ import pl.tpolgrabia.urbanexplorer.MainActivity; import pl.tpolgrabia.urbanexplorer.R; import pl.tpolgrabia.urbanexplorer.adapters.PlacesAdapter; import pl.tpolgrabia.urbanexplorer.dto.GooglePlacesRequest; +import pl.tpolgrabia.urbanexplorer.dto.GooglePlacesResponse; +import pl.tpolgrabia.urbanexplorer.handlers.GooglePlacesScrollListener; import pl.tpolgrabia.urbanexplorer.worker.GooglePlacesWorker; import pl.tpolgrabia.urbanexplorerutils.callbacks.StandardLocationListenerCallback; import pl.tpolgrabia.urbanexplorerutils.utils.LocationUtils; +import java.util.ArrayList; import java.util.List; +import java.util.concurrent.Semaphore; /** @@ -40,12 +46,22 @@ public class PlacesFragment extends Fragment { public static final String TAG = PlacesFragment.class.getSimpleName(); private PlacesUtils placesUtils; private GeocoderUtils geocoderUtils; - private GooglePlacesWorker worker; + private String nextPageToken; + private List places = new ArrayList<>(); + + private Semaphore semaphore = new Semaphore(1); + private boolean finished = false; public PlacesFragment() { // Required empty public constructor } + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + EventBus.getDefault().register(this); + } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, @@ -53,6 +69,9 @@ public class PlacesFragment extends Fragment { // Inflate the layout for this fragment final View inflatedView = inflater.inflate(R.layout.fragment_places, container, false); + ListView placesWidget = (ListView) inflatedView.findViewById(R.id.google_places); + placesWidget.setOnScrollListener(new GooglePlacesScrollListener(this)); + return inflatedView; } @@ -103,7 +122,6 @@ public class PlacesFragment extends Fragment { }); geocoderUtils = new GeocoderUtils(getActivity(), AppConstants.GOOGLE_API_KEY); - worker = new GooglePlacesWorker(getActivity(), this); } @@ -139,30 +157,73 @@ public class PlacesFragment extends Fragment { } private void fetchNearbyPlacesAndPresemt(Location location) { + if (!semaphore.tryAcquire()) { + // running + return; + } + GooglePlacesRequest request = new GooglePlacesRequest(); request.setLocation(location); request.setSearchRadius(AppConstants.DEF_PLACES_RADIUS); - request.setSearchItemType("museum"); - worker.execute(request); + request.setSearchItemType(GooglePlacesConstants.PLACES_SEARCH_TYPE); + new GooglePlacesWorker(getActivity(), this).execute(request); + } -// placesUtils.fetchNearbyPlaces( -// location.getLatitude(), -// location.getLongitude(), -// AppConstants.DEF_PLACES_RADIUS, -// "museum", -// null, -// new PlacesCallback() { -// @Override -// public void callback(Long statusCode, String statusMsg, List googlePlaceResult) { -// lg.debug("Fetch nearby statusCode: {}, status message: {}, google result: {}", -// statusCode, -// statusMsg, -// googlePlaceResult); -// -// ListView googlePlacesWidget = (ListView) getView().findViewById(R.id.google_places); -// PlacesAdapter adapter = new PlacesAdapter(getActivity(), googlePlaceResult); -// googlePlacesWidget.setAdapter(adapter); -// } -// }); + public void loadNextPage() { + + if (!semaphore.tryAcquire()) { + // running + return; + } + + if (finished) { + semaphore.release(); + return; + } + + lg.debug("Loading next page"); + + Location location = LocationUtils.getLastKnownLocation(getActivity()); + GooglePlacesRequest request = new GooglePlacesRequest(); + request.setLocation(location); + request.setSearchRadius(AppConstants.DEF_PLACES_RADIUS); + request.setSearchItemType(GooglePlacesConstants.PLACES_SEARCH_TYPE); + request.setPageToken(nextPageToken); + new GooglePlacesWorker(getActivity(), this).execute(request); + } + + public void setNextPageToken(String nextPageToken) { + this.nextPageToken = nextPageToken; + } + + @Subscribe + public void handleGooglePlacesResult(GooglePlacesResponse response) { + lg.debug("Handling google places results with original {} and next page token {}", + response.getOriginalPageToken(), + response.getNextPageToken()); + + ListView placesWidget = (ListView) getView().findViewById(R.id.google_places); + if (nextPageToken == null) { + places = response.getPlaces(); + PlacesAdapter adapter = new PlacesAdapter(getActivity(), places); + placesWidget.setAdapter(adapter); + } else { + places.addAll(response.getPlaces()); + PlacesAdapter adapter = (PlacesAdapter)placesWidget.getAdapter(); + adapter.addAll(places); + } + + nextPageToken = response.getNextPageToken(); + if (nextPageToken == null) { + finished = true; + } + semaphore.release(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + + EventBus.getDefault().unregister(this); } } diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/handlers/GooglePlacesScrollListener.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/handlers/GooglePlacesScrollListener.java new file mode 100644 index 0000000..0013eda --- /dev/null +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/handlers/GooglePlacesScrollListener.java @@ -0,0 +1,29 @@ +package pl.tpolgrabia.urbanexplorer.handlers; + +import android.widget.AbsListView; +import pl.tpolgrabia.urbanexplorer.fragments.PlacesFragment; + + +/** + * Created by tpolgrabia on 04.10.16. + */ +public class GooglePlacesScrollListener implements AbsListView.OnScrollListener { + private final PlacesFragment placesFragment; + + public GooglePlacesScrollListener(PlacesFragment placesFragment) { + this.placesFragment = placesFragment; + } + + @Override + public void onScrollStateChanged(AbsListView view, int scrollState) { + + } + + @Override + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + if (firstVisibleItem + visibleItemCount >= totalItemCount) { + // scrolled to the bottom, loading new page + placesFragment.loadNextPage(); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/pl/tpolgrabia/urbanexplorer/worker/GooglePlacesWorker.java b/app/src/main/java/pl/tpolgrabia/urbanexplorer/worker/GooglePlacesWorker.java index 477ba56..5536b35 100644 --- a/app/src/main/java/pl/tpolgrabia/urbanexplorer/worker/GooglePlacesWorker.java +++ b/app/src/main/java/pl/tpolgrabia/urbanexplorer/worker/GooglePlacesWorker.java @@ -6,6 +6,7 @@ import android.os.AsyncTask; import android.view.View; import android.widget.ListView; import org.apache.http.HttpStatus; +import org.greenrobot.eventbus.EventBus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import pl.tpolgrabia.googleutils.callback.PlacesCallback; @@ -53,6 +54,7 @@ public class GooglePlacesWorker extends AsyncTask placesResponse = null; @@ -67,6 +69,8 @@ public class GooglePlacesWorker extends AsyncTask googlePlacesResponses) { lg.debug("Post execute {}", googlePlacesResponses); - final View view = placesFragment.getView(); - if (view == null) { - lg.error("Fragment not attached to the view"); - return; - } +// final View view = placesFragment.getView(); +// if (view == null) { +// lg.error("Fragment not attached to the view"); +// return; +// } for (GooglePlacesResponse response : googlePlacesResponses) { - ListView places = (ListView) view.findViewById(R.id.google_places); - places.setAdapter(new PlacesAdapter(ctx, response)); + // placesFragment.setNextPageToken(response.getNextPageToken()); + // ListView places = (ListView) view.findViewById(R.id.google_places); + EventBus.getDefault().post(response); + // places.setAdapter(new PlacesAdapter(ctx, response)); } } } diff --git a/googleutils/src/main/java/pl/tpolgrabia/googleutils/constants/GooglePlacesConstants.java b/googleutils/src/main/java/pl/tpolgrabia/googleutils/constants/GooglePlacesConstants.java index 1ddf96a..8b9ea55 100644 --- a/googleutils/src/main/java/pl/tpolgrabia/googleutils/constants/GooglePlacesConstants.java +++ b/googleutils/src/main/java/pl/tpolgrabia/googleutils/constants/GooglePlacesConstants.java @@ -7,4 +7,5 @@ public class GooglePlacesConstants { public static final String GOOGLE_PLACES_BASEURL = "https://maps.googleapis.com/maps/api/place/"; public static final Long PHOTO_MAX_WIDTH = 512L; public static final String GOOGLE_MAPS_PLACES_API_BASEURL = "https://maps.googleapis.com/maps/api/place/"; + public static final String PLACES_SEARCH_TYPE = "museum"; }