问题描述
如何通过计算每个项目与位置和用户之间的距离,来按用户位置最多(一个点)的顺序显示列表(RecyclerView)? 如您在代码中所见,浏览json时,我会计算距离,但是每次用户更改位置时,列表都会使用相同的数据递增
请注意:如果用户的位置发生变化,必须怎么做才能更新列表?
这是我的代码:
private List<MarkerObj> markerObjList;
private void getStation() {
progressBar.setVisibility(View.VISIBLE);
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET,API_XOIL.STATIONS_LIST,null,new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
markerObjList = new ArrayList<>();
for (int i=0; i<response.length(); i++) {
try {
JSONObject jsonObject = response.getJSONObject(i);
MarkerObj markerObj = new MarkerObj(
jsonObject.getInt("id"),jsonObject.getString("libele"),jsonObject.getString("reference"),jsonObject.getString("latitude"),jsonObject.getString("longitude"),jsonObject.getString("images"),jsonObject.getString("alimentation"),jsonObject.getString("wifi"),jsonObject.getString("fastfood"),jsonObject.getString("lavage"),jsonObject.getString("entretien"));
/*markerObjList.add(markerObj);
Nosstations.AdapterListeStations adapterListeStations = new Nosstations.AdapterListeStations(getApplicationContext(),markerObjList);
recyclerView.setLayoutManager(new linearlayoutmanager(getApplicationContext()));
recyclerView.setAdapter(adapterListeStations);
recyclerView.addItemdecoration(new DividerItemdecoration(getApplicationContext(),linearlayoutmanager.VERTICAL));
recyclerView.setHasFixedSize(true);
adapterListeStations.notifyDataSetChanged();*/
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
int finalI = i;
LocationListener locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
double latView = location.getLatitude();
double lonView = location.getLongitude();
try {
Location loc1 = new Location(markerObj.getName());
loc1.setLatitude(Double.parseDouble(markerObj.getLat()));
loc1.setLongitude(Double.parseDouble(markerObj.getLon()));
Location loc2 = new Location("");
loc2.setLatitude(latView);
loc2.setLongitude(lonView);
float distanceInMeters = loc1.distanceto(loc2);
String distanceView = String.valueOf(distanceInMeters);
MarkerObj markerObj1 = new MarkerObj(
markerObj.getId(),markerObj.getName(),markerObj.getRef(),markerObj.getLat(),markerObj.getLon(),markerObj.getimages(),markerObj.getAlimentation(),markerObj.getWifi(),markerObj.getFastfood(),markerObj.getLavage(),markerObj.getEntretien(),distanceView);
markerObjList.add(markerObj1);
Nosstations.AdapterListeStations adapterListeStations = new Nosstations.AdapterListeStations(getApplicationContext(),markerObjList);
recyclerView.setLayoutManager(new linearlayoutmanager(getApplicationContext()));
recyclerView.setAdapter(adapterListeStations);
recyclerView.addItemdecoration(new DividerItemdecoration(getApplicationContext(),linearlayoutmanager.VERTICAL));
recyclerView.setHasFixedSize(true);
adapterListeStations.notifyDataSetChanged();
progressBar.setVisibility(View.GONE);
}
catch (Exception e){
e.printstacktrace();
Log.e("error",e.toString());
}
}
@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(getApplicationContext(),Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(getApplicationContext(),Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
return;
}
assert locationManager != null;
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,30000,locationListener);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,locationListener);
locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (JSONException e) {
e.printstacktrace();
}
}
}
},new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
if (error instanceof NetworkError) {
progressBar.setVisibility(View.GONE);
getofflineMarker();
Toast.makeText(getApplicationContext(),getString(R.string.volley_network_error),Toast.LENGTH_LONG).show();
}
else if (error instanceof ServerError) {
progressBar.setVisibility(View.GONE);
getofflineMarker();
Toast.makeText(getApplicationContext(),getString(R.string.volley_server_error),Toast.LENGTH_LONG).show();
}
else if (error instanceof AuthFailureError) {
progressBar.setVisibility(View.GONE);
getofflineMarker();
Toast.makeText(getApplicationContext(),getString(R.string.volley_authfail),Toast.LENGTH_LONG).show();
}
else if (error instanceof ParseError) {
progressBar.setVisibility(View.GONE);
getofflineMarker();
Toast.makeText(getApplicationContext(),getString(R.string.volley_parse_error),Toast.LENGTH_LONG).show();
}
else if (error instanceof TimeoutError) {
progressBar.setVisibility(View.GONE);
getofflineMarker();
Toast.makeText(getApplicationContext(),getString(R.string.volley_time_out_error),Toast.LENGTH_LONG).show();
}
}
});
VolleySingleton.getInstance(getApplicationContext()).addToRequestQueue(jsonArrayRequest);
}
解决方法
您需要分开markerObjList和位置更改侦听器的填充。在“ onResponse”方法中,仅填充markerObject列表。
使用单独的方法(例如视图的onCreate)创建位置更改侦听器,并在触发位置侦听器时,重新计算所有标记对象的距离,根据更新的距离对列表进行排序,并将排序后的列表设置为适配器。代码看起来像这样
onCreate()
{
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
int finalI = i;
LocationListener locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
double latView = location.getLatitude();
double lonView = location.getLongitude();
try {
ArrayList<> newMarkerObjList = new ArrayList<>();
int i = 0;
// recalcualte distances of all marker and add them in new list
for( i =0; i < markerObjList.size()){
MarkerObj markerObj = markerObjList[i]
Location loc1 = new Location(markerObj.getName());
loc1.setLatitude(Double.parseDouble(markerObj.getLat()));
loc1.setLongitude(Double.parseDouble(markerObj.getLon()));
Location loc2 = new Location("");
loc2.setLatitude(latView);
loc2.setLongitude(lonView);
float distanceInMeters = loc1.distanceTo(loc2);
String distanceView = String.valueOf(distanceInMeters);
MarkerObj markerObj1 = new MarkerObj(
markerObj.getId(),markerObj.getName(),markerObj.getRef(),markerObj.getLat(),markerObj.getLon(),markerObj.getImages(),markerObj.getAlimentation(),markerObj.getWifi(),markerObj.getFastfood(),markerObj.getLavage(),markerObj.getEntretien(),distanceInMeters,distanceView);
newMarkerObjList.add(markerObj1);
}
// create a predicate for sorting based on 'distanceInMeters';
Collections.sort( newMarkerObjList);
markerObjList = newMarkerObjList;
// and set this new list to the adapter;
NosStations.AdapterListeStations adapterListeStations = new NosStations.AdapterListeStations(getApplicationContext(),markerObjList);
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
recyclerView.setAdapter(adapterListeStations);
recyclerView.addItemDecoration(new DividerItemDecoration(getApplicationContext(),LinearLayoutManager.VERTICAL));
recyclerView.setHasFixedSize(true);
adapterListeStations.notifyDataSetChanged();
progressBar.setVisibility(View.GONE);
}
catch (Exception e){
e.printStackTrace();
Log.e("error",e.toString());
}
}
@Override
public void onStatusChanged(String provider,int status,Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
};
}
为数组中的每个元素添加当前位置侦听器,并在同一列表中添加更新的标记对象,因此导致列表中标记重复,并增加了标记列表的大小