Reputation: 1981
I have a FragmentActivity with a LocateMe
feature on the ActionBar and it hosts 4 fragments. Each fragment is a ListView
that basically sorts the results in my list differently (e.g. based on ratings, price, distance etc.)
my question is, how do I write my code such that the Location management (e.g. retrieval, updating) is done in the FragmentActivity, whereas the fragment just takes this location to perform any data calls on create or sorts the list when the LocateMe
button is pressed.
it definitely feels wrong if I have LocationManager in each fragment to deal with locations, except I dont know how to do the right thing.
thank you all. :)
Upvotes: 0
Views: 1217
Reputation: 1354
I'd like to suggest an improvement to the Budius answer.
Instead of create these interfaces you could use the Observer Pattern that is already implemented in Java and is available with Android.
public class MyFragment extends Fragment implements Observer {
@Override
public void onResume() {
super.onResume();
myLocationServices.addObserver(this);
}
@Override
public void onPause() {
super.onPause();
myLocationServices.deleteObserver(this);
}
@Override
public void update(Observable observable, Object data) {
// do stuff with your data
}
}
I have created a separated class to encapsulate the data (I have used Location Client that's part of Google Play SDK and was introduced in Google IO 2013 but you could use the classic LocationManager implementation. I'm still learning :P):
public class MyLocationServices extends Observable implements
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener, LocationListener {
@Override
public void onLocationChanged(Location location) {
Location mBestReading;
//Obtain the location. Do the staff
//And notify the observers
setChanged();
notifyObservers(mBestReading);
}
}
Upvotes: 1
Reputation: 39836
the 'cleanest' way IMHO is via interfaces and registering listeners
create two interfaces:
public interface LocationListener{
public void onLocationAvailable(/* whatever data you want to pass */ );
}
public interface LocationListenersRegistry{
public void addLocationListener(LocationListener listener);
public void removeLocationListener(LocationListener listener);
}
then you make your activity implement LocationListenersRegistry
and your fragments implement LocationListener
on your activity you'll have an private ArrayList<LocationListener>
that you'll add and remove listeners as per add/remove methods. Every time your activity receives new data, it should process it and then pass to all the listeners on the array.
on the fragments you should onPause
and onResume
register and unregister themselves from the activity, something like that:
onResume(){
super.onResume();
((LocationListenersRegistry)getActivity()).addLocationListener(this);
}
onPause(){
super.onPause();
((LocationListenersRegistry)getActivity()).removeLocationListener(this);
}
edit:
your activity implements the LocationListenersRegistry and then will have this code:
public class MyActivity extends Activity implements LocationListenersRegistry {
private ArrayList<LocationListener> listeners = new ArrayList<LocationListener>();
public void addLocationListener(LocationListener listener){
listeners.add(listener);
}
public void removeLocationListener(LocationListener listener){
listeners.remove(listener);
}
and then whenever the user clicks the menu button:
for(LocationListener l:listeners)
l.onLocationAvailable(/* pass here the data for the fragment */);
and your fragments will be implementing the LocationListener
public class MyFragment extends Fragments implements LocationListener{
public void onLocationAvailable( /* receive here the data */){
// do stuff with your data
}
Upvotes: 2