chongzixin
chongzixin

Reputation: 1981

android: getLocation in Activity and have child fragments retrieve it

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

Answers (2)

Ignacio Rubio
Ignacio Rubio

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

Budius
Budius

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

Related Questions