1

I'm a beginner of android programming then sorry if this question could seem silly but I need to understand how to update the view from a class that it is not an activity or a fragment. I have created a class that fetch data from the Google Play services API. I need to redirect this data to the fragment. which are the common software design patterns to achieve it?

This is the code but unfortunately it doesn't work

TodayFragment

package com.salvo.weather.android.fragment;


import android.os.Bundle;
import android.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.salvo.weather.android.R;
import com.salvo.weather.android.app.VolleyCallback;
import com.salvo.weather.android.entity.CurrentWeatherEntity;
import com.salvo.weather.android.geolocation.CurrentGeolocation;

/**
 * A simple {@link Fragment} subclass.
 */
public class TodayFragment extends Fragment {

    private static final String TAG = TodayFragment.class.getSimpleName();

    private CurrentGeolocation mCurrentGeolocation;

    public TodayFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_today, container, false);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mCurrentGeolocation = CurrentGeolocation.get(getActivity());
    }

    @Override
    public void onStart() {
        super.onStart();
        mCurrentGeolocation.getmGoogleApiClient().connect();

        renderView();
    }

    @Override
    public void onPause() {
        super.onPause();
        if (mCurrentGeolocation.getmGoogleApiClient().isConnected()) {
            mCurrentGeolocation.stopLocationUpdates();
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        if (mCurrentGeolocation.getmGoogleApiClient().isConnected()) {
            mCurrentGeolocation.startLocationUpdates();
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        if (mCurrentGeolocation.getmGoogleApiClient().isConnected()) {
            mCurrentGeolocation.stopLocationUpdates();
        }
    }

    public void renderView() {
        // check if googleApiClient is connected
        if (mCurrentGeolocation.getmGoogleApiClient().isConnected()) {
            mCurrentGeolocation.getmCurrentWeatherRequest().loadData(new VolleyCallback() {
                @Override
                public void onSuccess(CurrentWeatherEntity currentWeatherEntity) {
                    Log.i(TAG, currentWeatherEntity.getmCity());
                }
            });

        }
    }
}

CurrentGeolocation

package com.salvo.weather.android.geolocation;
import android.content.Context;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.salvo.weather.android.app.VolleyCallback;
import com.salvo.weather.android.client.request.CurrentWeatherRequest;
import com.salvo.weather.android.entity.CurrentGeolocationEntity;
import com.salvo.weather.android.entity.CurrentWeatherEntity;
/**
 * Created by mazzy on 30/05/15.
 */
public class CurrentGeolocation
        implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener {
    private static final String TAG = CurrentGeolocation.class.getSimpleName();
    // SETTING CONSTANTS FOR THE LOCATION
    private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000; //ms
    private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2;
    private static CurrentGeolocation sCurrentGeolocation;
    private boolean mRequestingLocationUpdates;
    private Context mAppContext;
    private GoogleApiClient mGoogleApiClient;
    private LocationRequest mLocationRequest;
    private CurrentGeolocationEntity mCurrentGeolocationEntity;
    private CurrentWeatherRequest mCurrentWeatherRequest;
    public static CurrentGeolocation get(Context appContext) {
        if (sCurrentGeolocation == null) {
            sCurrentGeolocation = new CurrentGeolocation(appContext.getApplicationContext());
        }
        return sCurrentGeolocation;
    }
    private CurrentGeolocation(Context appContext) {
        mAppContext = appContext;
        mRequestingLocationUpdates = true;
        mCurrentGeolocationEntity = new CurrentGeolocationEntity();
        mCurrentWeatherRequest = CurrentWeatherRequest.get(appContext);
        buildGoogleApiClient();
    }
    @Override
    public void onConnected(Bundle bundle) {
        Log.i(TAG, "Connected to GoggleApiClient");
        if (mCurrentGeolocationEntity.getmLastLocation() == null) {
            mCurrentGeolocationEntity.setmLastLocation(LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient));
            mCurrentWeatherRequest.setmCurrentGeolocationEntity(mCurrentGeolocationEntity);
        }
        if (mRequestingLocationUpdates) {
            startLocationUpdates();
        }
    }
    @Override
    public void onConnectionSuspended(int i) {
        // The connection to Google Play services was lost for some reason. We call connect() to
        // attempt to re-establish the connection.
        Log.i(TAG, "Connection suspended");
        mGoogleApiClient.connect();
    }
    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        // Refer to the javadoc for ConnectionResult to see what error codes might be returned in
        // onConnectionFailed.
        Log.i(TAG, "Connection failed: error " + connectionResult.getErrorCode());
    }
    @Override
    public void onLocationChanged(Location location) {
        // update the location
        mCurrentGeolocationEntity.setmLastLocation(location);
    }
    public GoogleApiClient getmGoogleApiClient() {
        return mGoogleApiClient;
    }
    public void startLocationUpdates() {
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    }
    public void stopLocationUpdates() {
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
    }
    public CurrentWeatherRequest getmCurrentWeatherRequest() {
        return mCurrentWeatherRequest;
    }
    private synchronized void buildGoogleApiClient() {
        Log.i(TAG, "Building Google Api Client");
        mGoogleApiClient = new GoogleApiClient.Builder(mAppContext)
                .addConnectionCallbacks(this)
                .addApi(LocationServices.API)
                .build();
        createLocationRequest();
    }
    private void createLocationRequest() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }
}
Mazzy
  • 13,354
  • 43
  • 126
  • 207
  • If I am not mistaken, you want to set the data got from the parent class to your fragments associated with the parent class ? – Vikram Ezhil May 31 '15 at 20:06
  • No. Actually no association between the fragments and the class. I get data from Google Play services API and then I would to set this data in fragments – Mazzy May 31 '15 at 20:10
  • You have a class where you fetch data from google play services and to set that data into fragments you actually need an activity class in place to create fragments. From which activity class did you create your fragments? Sharing your code could help since your question is too broad to answer. – Vikram Ezhil May 31 '15 at 20:17
  • @VikramEzhil I have posted my code but it doesn't work because when it try to get the data before google play service api get data – Mazzy May 31 '15 at 21:21

1 Answers1

4

You must create a Listener.

TodayFragment

package com.salvo.weather.android.fragment;


import android.os.Bundle;
import android.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.salvo.weather.android.R;
import com.salvo.weather.android.app.VolleyCallback;
import com.salvo.weather.android.entity.CurrentWeatherEntity;
import com.salvo.weather.android.geolocation.CurrentGeolocation;

/**
 * A simple {@link Fragment} subclass.
 */
public class TodayFragment extends Fragment implements CurrentGeoloaction.OnUpdateListener {

    private static final String TAG = TodayFragment.class.getSimpleName();

    private CurrentGeolocation mCurrentGeolocation;

    public TodayFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_today, container, false);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mCurrentGeolocation = CurrentGeolocation.get(getActivity());
        mCurrentGeolocation.setOnUpdateListener(this);
    }

    @Override
    public void onStart() {
        super.onStart();
        mCurrentGeolocation.getmGoogleApiClient().connect();

        renderView();
    }

    @Override
    public void onPause() {
        super.onPause();
        if (mCurrentGeolocation.getmGoogleApiClient().isConnected()) {
            mCurrentGeolocation.stopLocationUpdates();
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        if (mCurrentGeolocation.getmGoogleApiClient().isConnected()) {
            mCurrentGeolocation.startLocationUpdates();
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        if (mCurrentGeolocation.getmGoogleApiClient().isConnected()) {
            mCurrentGeolocation.stopLocationUpdates();
        }
    }

    @Override
    public void onUpdate() {
        renderView();
    }

    public void renderView() {
        // check if googleApiClient is connected
        if (mCurrentGeolocation.getmGoogleApiClient().isConnected()) {
            mCurrentGeolocation.getmCurrentWeatherRequest().loadData(new VolleyCallback() {
                @Override
                public void onSuccess(CurrentWeatherEntity currentWeatherEntity) {
                    Log.i(TAG, currentWeatherEntity.getmCity());
                }
            });

        }
    }
}

CurrentGeolocation

package com.salvo.weather.android.geolocation;
import android.content.Context;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.salvo.weather.android.app.VolleyCallback;
import com.salvo.weather.android.client.request.CurrentWeatherRequest;
import com.salvo.weather.android.entity.CurrentGeolocationEntity;
import com.salvo.weather.android.entity.CurrentWeatherEntity;
/**
 * Created by mazzy on 30/05/15.
 */
public class CurrentGeolocation
        implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener {
    private static final String TAG = CurrentGeolocation.class.getSimpleName();
    // SETTING CONSTANTS FOR THE LOCATION
    private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000; //ms
    private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2;
    private static CurrentGeolocation sCurrentGeolocation;
    private boolean mRequestingLocationUpdates;
    private Context mAppContext;
    private GoogleApiClient mGoogleApiClient;
    private LocationRequest mLocationRequest;
    private CurrentGeolocationEntity mCurrentGeolocationEntity;
    private CurrentWeatherRequest mCurrentWeatherRequest;
    private OnUpdateListener mOnUpdateListener;

    public interface OnUpdateListener {
        public void onUpdate();
    }

    public void setOnUpdateListener(Fragment todayFragment) {
        this.mOnUpdateListener = (OnUpdateListener) todayFragment;
    }

    public static CurrentGeolocation get(Context appContext) {
        if (sCurrentGeolocation == null) {
            sCurrentGeolocation = new CurrentGeolocation(appContext.getApplicationContext());
        }
        return sCurrentGeolocation;
    }
    private CurrentGeolocation(Context appContext) {
        mAppContext = appContext;
        mRequestingLocationUpdates = true;
        mCurrentGeolocationEntity = new CurrentGeolocationEntity();
        mCurrentWeatherRequest = CurrentWeatherRequest.get(appContext);
        buildGoogleApiClient();
    }
    @Override
    public void onConnected(Bundle bundle) {
        Log.i(TAG, "Connected to GoggleApiClient");
        if (mCurrentGeolocationEntity.getmLastLocation() == null) {
            mCurrentGeolocationEntity.setmLastLocation(LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient));
            mCurrentWeatherRequest.setmCurrentGeolocationEntity(mCurrentGeolocationEntity);
        }
        if (mRequestingLocationUpdates) {
            startLocationUpdates();
            mOnUpdateListener.onUpdate();
        }
    }
    @Override
    public void onConnectionSuspended(int i) {
        // The connection to Google Play services was lost for some reason. We call connect() to
        // attempt to re-establish the connection.
        Log.i(TAG, "Connection suspended");
        mGoogleApiClient.connect();
    }
    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        // Refer to the javadoc for ConnectionResult to see what error codes might be returned in
        // onConnectionFailed.
        Log.i(TAG, "Connection failed: error " + connectionResult.getErrorCode());
    }
    @Override
    public void onLocationChanged(Location location) {
        // update the location
        mCurrentGeolocationEntity.setmLastLocation(location);
    }
    public GoogleApiClient getmGoogleApiClient() {
        return mGoogleApiClient;
    }
    public void startLocationUpdates() {
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    }
    public void stopLocationUpdates() {
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
    }
    public CurrentWeatherRequest getmCurrentWeatherRequest() {
        return mCurrentWeatherRequest;
    }
    private synchronized void buildGoogleApiClient() {
        Log.i(TAG, "Building Google Api Client");
        mGoogleApiClient = new GoogleApiClient.Builder(mAppContext)
                .addConnectionCallbacks(this)
                .addApi(LocationServices.API)
                .build();
        createLocationRequest();
    }
    private void createLocationRequest() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }
}
RediOne1
  • 10,389
  • 6
  • 25
  • 46
  • Thank you. This is right what the following answer says http://stackoverflow.com/questions/27844512/google-play-services-or-android-location-services – Mazzy May 31 '15 at 21:16
  • Which data do you want to redirect to TodayFragment? – RediOne1 May 31 '15 at 21:47
  • the workflow is the following: the application starts, gets data from the google play services api and then store this data to the `mCurrentGeolocationEntity` pass it to the `mCurrentWeatherRequest` instance and then call the function `renderView` to get data from the server – Mazzy May 31 '15 at 21:52
  • Anyway you gave me a good idea. I will post the result if it will work – Mazzy May 31 '15 at 22:25
  • Do you want call renderView, after `startLocationUpdates`? – RediOne1 May 31 '15 at 22:32
  • Yes exactly something like that. In this renderView is executed – Mazzy May 31 '15 at 22:32
  • In my code it isn't executed because google api is not connected yet – Mazzy May 31 '15 at 22:33
  • I think yes, listeners are commonly used, that way – RediOne1 Jun 01 '15 at 10:24
  • What currently I don't understand is loadData should be executed inside an async task or not? – Mazzy Jun 01 '15 at 12:27