javaandroidloaderlocationlistener

switching to loader using locationListener


I'm doing a Udacity Android Basics course and am trying to change my app to use a Loader rather than AsyncTask. My app uses a locationListener to generate a custom URL that is then passed to the loader, loader calls ChargePointLoader class which initates the HTTP request and returns a list of chargePoints, which should populate the adapter once loaded.

However nothing appears on my screen. Do I have the order of my loader wrong or is the locationListener interfering with the loader? Thanks for any help

Here is a link to the old Async Project: https://github.com/Kovah101/ChargeMyCarBareBones/blob/master/app/src/main/java/com/example/android/chargemycar/MainActivity.java

Here is my Main activity

public class MainActivity extends AppCompatActivity implements LoaderCallbacks<List<ChargePoint>> {

public static final String LOG_TAG = MainActivity.class.getName();

public static double myLat;
public static double myLong;

private static  String ChargePoint_REQUEST_URL = "http://chargepoints.dft.gov.uk/api/retrieve/registry/postcode/SW15+5QS/dist/7/format/json/limit/10";

private ChargePointAdapter adapter;

private LocationManager locationManager;
private LocationListener locationListener;

private static final int CHARGEPOINT_LOADER_ID = 1;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Find a reference to the {@link ListView} in the layout
   final ListView chargePointListView = (ListView) findViewById(R.id.list);

    // Create a ChargingPointAdapter, whose data source is a list of ChargePoints, which creates listview items for each item
    adapter = new ChargePointAdapter(this, new ArrayList<ChargePoint>());

    //possible error with order of loaders or inside listener
    final LoaderManager loaderManager = getLoaderManager();

    locationManager = (LocationManager) this.getSystemService(LOCATION_SERVICE);
    locationListener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            //set lat & long variables
            myLat = location.getLatitude();
            myLong = location.getLongitude();
            String myLatString = Double.toString(myLat);
            String myLongString = Double.toString(myLong);

            //test with toast
            Context context = getApplicationContext();
            CharSequence text = " my latitude=" +myLatString +"\nmy longitude=" +myLongString ;
            int duration = Toast.LENGTH_LONG;
            Toast toast = Toast.makeText(context, text, duration);
            toast.show();

            //create request URL using live location
            ChargePoint_REQUEST_URL = "http://chargepoints.dft.gov.uk/api/retrieve/registry/lat/" +myLat + "/long/" +myLong +"/dist/10/format/json/limit/10";

            // Set the adapter on the {@link ListView}
            // so the list can be populated in the user interface
            chargePointListView.setAdapter(adapter);


            loaderManager.initLoader(CHARGEPOINT_LOADER_ID, null, MainActivity.this );

        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
        }

        @Override
        public void onProviderEnabled(String provider) {
        }

        @Override
        public void onProviderDisabled(String provider) {
        }
    };


    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, 1);
    }else{
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 500, 100, locationListener);
        //time in milliseconds
        //distance in meters
    }

    // On click take to maps
    chargePointListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            String myLatString = Double.toString(myLat);
            String myLongString = Double.toString(myLong);

            ChargePoint currentChargePoint = (ChargePoint) chargePointListView.getItemAtPosition(position);
            double destinationLatitude = currentChargePoint.getLatitude();
            double destinationLongitude = currentChargePoint.getLongitude();
            String destLatString = Double.toString(destinationLatitude);
            String destLongString = Double.toString(destinationLongitude);


            //create uri for map intent
            String url = "http://maps.google.com/maps?saddr="+myLatString+","+myLongString+"&daddr="+destLatString+","+destLongString+"&travelmode=driving";
            Intent mapIntent = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse(url));
                mapIntent.setPackage("com.google.android.apps.maps");
                if (mapIntent.resolveActivity(getPackageManager()) != null) {
                    startActivity(mapIntent);
                }
        }
    });


}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)== PackageManager.PERMISSION_GRANTED){
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 500, 25, locationListener);
            //time in ms, distance in meters
        }
    }
}

@Override
public Loader<List<ChargePoint>> onCreateLoader(int i, Bundle bundle) {
    return new ChargePointLoader(this, ChargePoint_REQUEST_URL);
}

@Override
public void onLoadFinished(Loader<List<ChargePoint>> loader, List<ChargePoint> chargePoints) {
    // Clear the adapter of previous data
    adapter.clear();
    //check for null charge point list, return early if that is the case, if there is a valid list then add to the adapter
    if (chargePoints != null && !chargePoints.isEmpty()){
        adapter.addAll(chargePoints);
    }
}

@Override
public void onLoaderReset(Loader<List<ChargePoint>> loader) {
    // TODO: Loader reset, so we can clear out our existing data.
    adapter.clear();
}

}

Solution

  • Loaders are now deprecated, use Android Architecture Components (LiveData and ViewModel) with your old AsyncTask. It works more efficiently, faster and cleaner than Loaders. It also makes your AsyncTask to be lifecycle aware. Lifecycle aware in a sense that your network request will not be made again after once no matter how many times you call onCreate() because it automatically caches downloaded data. Configuration changes won't affect your app. For more information on using AsyncTask with LiveData and ViewModel, visit https://medium.com/androiddevelopers/lifecycle-aware-data-loading-with-android-architecture-components-f95484159de4