我正在上一本Udacity Android基础课程,并试图更改我的应用程序以使用Loader而不是AsyncTask。我的应用程序使用locationListener生成一个自定义URL,然后将其传递给加载程序,加载程序调用ChargePointLoader类,该类将初始化HTTP请求并返回chargePoints列表,加载后应填充适配器。
但是我的屏幕上什么也没有出现。我的加载器顺序是否错误,或者locationListener干扰了加载器?感谢您的帮助
这是我的主要活动
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();
}
}
答案 0 :(得分:0)
现在不建议使用加载程序,将Android体系结构组件(LiveData和ViewModel)与旧的AsyncTask结合使用。它比装载机更有效,更快,更清洁。这也使您的AsyncTask具有生命周期意识。从某种意义上说具有生命周期意识,无论您调用onCreate()多少次,都不会在一次之后再次提出网络请求,因为它会自动缓存下载的数据。配置更改不会影响您的应用。有关将AsyncTask与LiveData和ViewModel结合使用的更多信息,请访问https://medium.com/androiddevelopers/lifecycle-aware-data-loading-with-android-architecture-components-f95484159de4