Grouping cluster Google map API - android

I am using the library for one of my project (https://github.com/googlemaps/android-maps-utils)
This library let me create cluster on the google map, but I was wondering if it is possible to cluster my marker by group. For example, I want to cluster only markers that are "Friends" and cluster the others who are only "Coworker" and etc... (Maybe not the best example, but I hope that you understand)
My idea was to use multiple ClusterManager but I didn't tried it and don't really know if it is the best solution or even a good solution.

I found the solution for my problem. The better solution is to manage multiple Clustermanagers if you want to create multiple group.
By the way, all the credits for the answer goes to #Brody on the Github :
Here the link : https://github.com/googlemaps/android-maps-utils/issues/100#event-153755438

Using multiple ClusterManager is cumbersome. I think it is easier to use multiple Algorithm with a wrapper.
The wrapper should choose the correct algorithm according to the item properties. The only requirement is that all items must have a common parent class (Item in the example below).
public class MultiAlgorithm<T extends ClusterItem> implements Algorithm<T> {
private final Algorithm<T> friendsAlgorithm;
private final Algorithm<T> coworkerAlgorithm;
public MultiAlgorithm() {
friendsAlgorithm = new NonHierarchicalDistanceBasedAlgorithm<>();
coworkerAlgorithm = new NonHierarchicalDistanceBasedAlgorithm<>();
}
private Algorithm<T> getAlgorithm(T item) {
// TODO Return the correct algorithm based on 'item' properties
}
#Override
public void addItem(T item) {
getAlgorithm(item).addItem(item);
}
#Override
public void addItems(Collection<T> collection) {
for (T item : collection) {
getAlgorithm(item).addItem(item);
}
}
#Override
public void clearItems() {
friendsAlgorithm.clearItems();
coworkerAlgorithm.clearItems();
}
#Override
public void removeItem(T item) {
getAlgorithm(item).removeItem(item);
}
#SuppressWarnings("unchecked")
#Override
public Set<? extends Cluster<T>> getClusters(double zoom) {
// Use a non-typed Set to prevent some generic issue on the result.addAll() method
Set result = new HashSet<>(friendsAlgorithm.getClusters(zoom));
result.addAll(coworkerAlgorithm.getClusters(zoom));
return result;
}
#Override
public Collection<T> getItems() {
Collection<T> result = new ArrayList<>(friendsAlgorithm.);
result.addAll(coworkerAlgorithm.getItems());
return result;
}
}
Usage: clusterManager.setAlgorithm(new MultiAlgorithm<Item>());

Related

Calling Sequence of Functions From a List at Run Time

I'm making an app to play short pieces of short songs with a specific order based on the user destitution. So to do some thing like that i need to call functions that play the song several times but with different parameters.
So how can i making a list of functions at run time and execute it?
Assuming that the functions follow a sequence (the success of one function, relays the next one in the list), I would suggest creating a callback interface whose methods return booleans.
Ensure the methods return a boolean when executed, hence
create the ArrayList, make sure the last element in the list is a false regardless.
public void myFunctions(ArrayList<Boolean> functions, CallBackMethods mm){
for (int i = 0; i<functions.size(); i++){
mm = new FunctionChecker(functions.get(i));
while(mm.onSuccess()){
Log.d(TAG,"Function Ran");
}
}
}
the method above will run all the functions in the arraylist given they individually execute.
below is a class that implements the interface;
public class FunctionChecker implements CallBackMethods{
private boolean methodFlag;
public FunctionChecker(boolean methodFlag) {
this.methodFlag = methodFlag;
}
#Override
public boolean onSuccess() {
return methodFlag?methodFlag:onFail();
}
#Override
public boolean onFail() {
return false;
}
}
and here is the interface;
public interface CallBackMethods {
boolean onSuccess();
boolean onFail();
}
it is a constraining work around but i hope it helps

Communicating between components in Android

So I have an Activity. The Activity hosts a ViewPager with tabs, each tab holding a Fragment in it. The Fragments themselves have a RecyclerView each. I need to communicate changes from the RecyclerView's adapter to the activity.
Currently, I am using the listener pattern and communicating using interface between each of the components. i.e I have an interface between the RecyclerView's adapter and the Fragment holding it. Then an interface from the Fragment to the ViewPager's FragmentStatePagerAdapter which is creating all the Fragments. And 1 more interface between the ViewPager's adapter and the Activity hosting the ViewPager. I feel that there are too many interfaces for all the components because of how they are structured.
Currently I am not facing issues as such but I think the listener pattern is acting like an anti-pattern due to all the nested components. Instead of creating independent components I think the hierarchy will make it difficult for making code changes in future.
Am I doing it correctly or is there a better way to do it? Is this a case where I should use an Event Bus or Observer Pattern (If yes can you point me to some examples where someone overcame a similar problems using it)?
NOTE : If it matters, I need it to maintain a global object in the activity, something like a shopping cart where I can add or remove items and these items are present in RecyclerView's adapter from where I can add it to the cart and also increment or decrement the count for a particular item. The ViewPager and Tabs help segregate these items in various categories.
Edit 1 : Some code trying out #LucaNicoletti's approach -
I have skipped one level that is the level with the ViewPager's FragmentStatePagerAdapter. I guess that should not matter and stripped of some other code to keep it small.
MainActivity:
public class MainActivity extends AppCompatActivity implements View.OnClickListener, FoodAdapter.OnFoodItemCountChangeListener {
#Override
public void onFoodItemDecreased(FoodItemModel foodItemModel, int count) {
Log.d("Test", "Dec");
}
#Override
public void onFoodItemIncreased(FoodItemModel foodItemModel, int count) {
Log.d("Test", "Inc");
}
// Other methods here
}
Fragment hosting the Adapter:
public class FoodCategoryListFragment extends Fragment implements FoodAdapter.OnFoodItemCountChangeListener {
// Other boring variables like recyclerview and layout managers
FoodAdapter foodAdapter;
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Other boring intializations for recyclerview and stuff
// I set the click listener here directly on the adapter instance
// I don't have this adapter instance in my activity
foodAdapter.setOnFoodItemClickListener(this);
rvFoodList.setAdapter(foodAdapter);
}
}
The adapter class at the lowest level:
public class FoodAdapter extends RecyclerView.Adapter<FoodAdapter.FoodViewHolder> {
private OnFoodItemCountChangeListener onFoodItemCountChangeListener;
private List<FoodItemModel> foodItems;
// The interface
public interface OnFoodItemCountChangeListener {
void onFoodItemIncreased(FoodItemModel foodItemModel, int count);
void onFoodItemDecreased(FoodItemModel foodItemModel, int count);
}
// This is called from the fragment since I don't have the adapter instance
// in my activty
public void setOnFoodItemClickListener(OnFoodItemCountChangeListener onFoodItemCountChangeListener) {
this.onFoodItemCountChangeListener = onFoodItemCountChangeListener;
}
// Other boring adapter stuff here
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.bMinus:
onFoodItemCountChangeListener.onFoodItemDecreased(foodItems.get(getAdapterPosition()),
Integer.parseInt(etCounter.getText().toString()));
}
break;
case R.id.bPlus:
onFoodItemCountChangeListener.onFoodItemIncreased(foodItems.get(getAdapterPosition()),
Integer.parseInt(etCounter.getText().toString()));
}
break;
}
}
}
my comments were:
what you should/could do it's to have a global data repo which holds the shopping cart and listeners associated with changes to it. Like a singleton, like ShoppingCart.getInstance().addListener(this); and ShoppingCart.getInstance().addItem(new Item(id));
and
Yes. That's what I'm suggesting. Do not forget that this Singleton can never ever holds Context or Activity because u don't want to leak memory, so always call removeListener. On my opinion it would reduce dependency as all your view controllers only interact with the data model
and I'll add some code to exemplify as a proper answer.
Below is a very crude, typed by heart code, but it should give an idea. All the UI elements are only tied to the data, and not to each other.
Similar stuff could be implemented with libraries that provide observable pattern out of the box for data-only objects.
public class ShoppingCart {
private ShoppingCart single;
private static void init(){
.. init single if not null
}
private List<Item> items = new ArrayList<>();
public int numberOfItems;
public long totalPrice;
private static void addItem(Item item){
init()
single.items.add(item);
single.numberOfItems++;
single.totalPrice+=item.price;
dispatchChange();
}
private static void removeItem(Item item){
init();
single.numberOfItems--;
single.totalPrice-=item.price;
dispatchChange();
single.items.remove(item);
}
private void dispatchChange(){
// TODO: write real loop here
for(single.listeners) listener.onCartChanged(single.cart);
}
public interface Listener {
void onCartChanged(ShoppingCart cart);
}
private List<Listener> listeners = new ArrayList<>();
// TODO: addListener and removeListener code
public static class Item {
String id;
String name;
long price;
}
}
To communicate between components (Activity, Fragment) you have to use an event bus.
In android, you could choose between:
RxJava
Otto
Green Robot EventBus
A blog to explain this.

Create boolean listener

In Android, how do I take an action whenever a variable changes?
So I want to implement a listener for an object I created. What I want it to do is execute a block of code when its value changes from false to true.
As I am following this thread, I can't understand where the person wants us to implement the last block of code containing the logic for the listener.
Could someone, hopefully, guide me in the right direction?
(This question is being asked here as I don't have enough rep. points)
That last bit of example code triggers the listener, so it basically needs to be run whenever the "event" occurs. In this case the "event" is whenever (wherever in the code) the value of the variable changes.
If you have a setter and that is the only place the value changes, that is where you'd put it. If you are changing the value in multiple places throughout your code, I would make a new private method (call it signalChanged), put your code there, and then call it immediately after the variable assignment in the cases you want the listener to fire.
Here's an example (some code borrowed from linked answer, haven't checked that it compiles).
public class MyObj
{
public MyObj(int value)
{
setValue(value);
}
private int myValue;
public int getValue() { return myValue; }
public void setValue( int value )
{
if (value != myValue)
{
myValue = value;
signalChanged();
}
}
public interface VariableChangeListener
{
public void onVariableChanged(Object... variableThatHasChanged);
}
private VariableChangeListener variableChangeListener;
public void setVariableChangeListener(VariableChangeListener variableChangeListener)
{
this.variableChangeListener = variableChangeListener;
}
private void signalChanged()
{
if (variableChangeListener != null)
variableChangeListener.onVariableChanged(myValue);
}
}
you have to create a callback interface
here is a good about custom listener tutorial
here is a sample
public class MyObj {
VariableChanger onVariableChanged ;
public void setOnVariableChanged(VariableChanger onVariableChanged) {
this.onVariableChanged = onVariableChanged;
}
void log(){
boolean changed = false;
onVariableChanged.onVariableChanged();
//this will call it
}
interface VariableChanger{
void onVariableChanged();
}
}
class logic {
MyObj mo = new MyObj();
void main(){
mo.setOnVariableChanged(new MyObj.VariableChanger() {
#Override
public void onVariableChanged() {
//do your action
}
});
}
}
In Android, like any language, most developper uses logic comparisons to check values (if, else, switch, =, !=, >, <, etc) or Event (signal)
What kind of listener do you want to implement?

Is it the proper way to use an event bus?

I am planning to add Otto event bus to decouple my communications. One of the things I want use event bus for is to communicate between a button click handler and the activity.
The idea is that the button click (from my custom view) would generate a text submission event which would notify the activity. The activity would then decide what to do with it. If the activity deems it proper, it would send the text to a service for upload or whatever.
Is this a proper way to use an event bus?
Also, what are some good practices when using event buses?
I still think this question should be closed as not proper for the StackOverflow model.
But for anyone looking on how on can organize user events around a Bus, that's kinda of how we've done on the place I work.
Remember, that type of structure only makes sense if you're creating a big project where achieving a high level of separation makes the life of a team of developers easier. For small, quick projects or test apps that's too much effort.
PS.: all the code below is typed 100% by heart without checking any real code, so there will be typos and small errors, but should be enough to get an idea of the approach. I also didn't write any annotation like #override, too lazy for it.
First: Activity overrides getSystemService to supply a Bus via Context and register/unregister event handlers as needed.
public MyActivity extends AppCompatActivity {
private static final String BUS_SERVICE = "bus_service";
private List<EventHandler> eventHandlers = new ArrayList();
private Bus bus = new Bus();
public void onCreate(Bundle savedState){
super.onCreate(savedState);
.... layout creation, etc, etc, etc
if(isLoggedIn()) {
eventHandlers.add(new LoggedUserNavigationHandler());
eventHandlers.add(new RestPostRequestHandler());
} else{
eventHandlers.add(new GuestUserNavigation());
}
eventHandlers.add(new AnalyticsTrackingHandler());
if(DEBUG) {
// log all events in debug mode
eventHandlers.add(new EventHandler(){
#Subscribe
public void onEvent(Object o){
Log.d(TAG, "Event: " + o.toString);
}
});
}
}
}
public Object getSystemService(String name){
if(BUS_SERVICE.equals(name)) return bus;
else return super.getSystemService(name);
}
public void onStart(){
super.onStart();
for(int i=0, size=eventHandlers.size(); i<size; i++) {
eventHandlers.get(i).activity = this; // pass reference, might be usefull
bus.register(eventHandlers.get(i));
}
}
public void onStop(){
for(int i=0, size=eventHandlers.size(); i<size; i++) {
bus.unregister(eventHandlers.get(i));
eventHandlers.get(i).activity = null;
}
super.onStop();
}
}
Then: You have all the RecyclerView.ViewHolder (or custom widget) to be the click listener and dispatch appropriate events. For example in a ViewHolder for a photo item.
public class PhotoHolder extends ViewHolder implements OnClickListener {
TextView user;
ImageButton like;
ImageView photo;
Photo data; // assume this was set during `bindViewHolder`
public PhotoHolder(View itemView) {
super(itemView);
user = (TextView) itemView.findViewById(...
like = (ImageButton) itemView.findViewById(...
photo = (ImageView) itemView.findViewById(...
user.setOnClickListener(this);
like.setOnClickListener(this);
photo.setOnClickListener(this);
}
public void onClick(View view){
switch(view.getId()){
case R.id.user:
((Bus)view.getSystemService(BUS_SERVICE))
.post(new Event.PhotoEvent.UserTap(data);
break;
case R.id.like:
((Bus)view.getSystemService(BUS_SERVICE))
.post(new Event.PhotoEvent.LikeUnlike(data);
break;
case R.id.photo:
((Bus)view.getSystemService(BUS_SERVICE))
.post(new Event.PhotoEvent.PhotoTap(data);
break;
}
}
}
and the last of course: is to create those events objects and add all the events to your appropriate handlers.
// add all the app events under this class, or maybe create a `Event` package and then all the events in that package
public final class Event {
public static class PhotoEvent {
public final Photo data;
public Photo(Photo data){
this.data=data;
}
public static class UserTap extends PhotoEvent{
// copy matching constructor
}
public static class LikeUnlike extends PhotoEvent{
// copy matching constructor
}
public static class PhotoTap extends PhotoEvent{
// copy matching constructor
}
}
}
finally, handling events
public class RestPostRequestHandler {
#Subscribe
public void onPhotoLikeUnlike(Event.Photo.LikeUnlike event){
// make your POST request here
}
}
a handler for navigating:
public class LoggedUserNavigationHandler extends EventHandler{
#Subscribe
public void on(Event.Photo.UserTap event){
Intent i = new Intent( ... create here intent for the "user profile"
// activity reference was passed during onStart
activity.startActivity(i);
}
}
a handler for analitics:
public class AnalyticsTrack {
#Subscribe
public void on(Event.Photo.UserTap event){
// send event "user tap" ?
}
}
I agree with some of the comments that it's possible to create a huge, weird spaghetti code when having "tap" events going through the bus. But if from the start a good structured approach is defined and all the developers follow it, you can achieve a project that is easy to follow and with a very clear separation of responsibilities.

Where to write logical code for my model?

I've got a ListActivity with about 100 events. (These events are also displayed on a map in another activity.)
So I've my MyListActivity, which handles the list and a MyListAdapter to populate the list that deals with MyEvent-Objects. As model I have a MyEvent-model-Class and a MyEventStorage-Class.
Now have written a method to return an image for an event based on its ID. It does some decisions which image to load, where it gets the image from, loads it and resamples it.
Where should I put this method in best practice?
I don't want to copy it in every activity where it is needed but just in one place.
I'd like to have it in my MyEvent-Class, so I can call myEvent.getImage(); but it somehow feels wrong to put this method inside the model class with all the getters and setters. Is it wrong?
Should I write a helper class containing this method? As a static method? Would this still provide a good performance?
Or maybe create an additional MyImageGetter-object for every MyEvent-object?
Or expand the MyEvent-model with an image-variable and getters/setter and create an extra class that puts the proper image in the model? How would I call that method?
Another solution?
MyEvent.java:
public class MyEvent {
private int id;
private int category;
private String eventname;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
// other getters and setters
}
MyEventStorage.java:
private static MyEventStorage instance = null;
private List<MyEvent> store;
private MyEventStorage() {
store = new ArrayList<MyEvent>();
}
// get the storage containing the events
public static MyEventStorage getInstance() {
if (instance == null) {
instance = new MyEventStorage();
}
return instance;
}
public List<MyEvent> getStore() {
return store;
}
public void setStore(List<MyEvent> store) {
this.store = store;
}
// Add a Event to the store
public void addEvent(MyEvent myEvent) {
store.add(myEvent);
}
// Remove a Event from the store
public void removeEvent(MyEvent myEvent) {
store.remove(myEvent);
}
}
The method I want to integrate:
Image getImageById(int id) {
// decide which image to load based on the events id
// decide where to load the image from
// check if image available
// load image if available else load placeholder image
// resample image
return image;
}
Thank you advance!
I think your last bullet point is spot on.
If the Image is in fact a property of MyEvent, it makes sense to add an instance variable to that class. You shouldn't include the logic for retrieving an event's image from a datasource in the model, but rather use a static utility method to load this property.
Your getImageById method looks like it has to do a decent amount of work to retrieve the image from wherever it is stored. I think it would make the most sense to create a utility class (along the lines of ImageRetriever) like you mentioned in order to perform the actual retrieval of the image. This prevents you from having to copy the method to multiple places. Performance should not be a concern either, as you'll never have to instantiate this class.
The code could look something like this:
public class MyEvent {
private int id;
private int category;
private String eventname;
private Image image;
public MyEvent(int id...) {
// initialize instance vars
setImageFromRetriever();
}
public void setImage(Image image) {
this.image = image;
}
public void setImageFromRetriever() {
// optional null check if you don't want to reload images
setImage(ImageRetriever.getImageById(this.id));
}
}

Categories

Resources