Google 定位服务在我使用 Retrofit 时返回空位置
Google location services returning a null location when I use Retrofit
我有一个片段,我想在其中获取当前坐标,然后使用 Retrofit 向 Zomato Api 发出请求,但我当前的位置 return 为空。我试图删除与我的 api 调用和应用 return 我正确的经纬度相关的代码。我做错了什么?下面是我的 Java class.
我的片段
public class RestaurantsList extends Fragment {
private RestaurantAdapter mAdapter;
private RecyclerView mRecyclerView;
protected static List<Restaurant_> restaurantsList;
private Context context;
protected static OnRestaurantClickedListener listener;
private FirebaseAuth mAuth;
private static final int REQUEST_FINE_LOCATION=100;
private LocationRequest mLocationRequest;
private LocationCallback mLocationCallback;
private FusedLocationProviderClient mFusedLocationClient;
private Location myLocation;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = getContext();
mAuth = FirebaseAuth.getInstance();
restaurantsList= new ArrayList<>(50);
getLastLocation();
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(getActivity());
mFusedLocationClient.getLastLocation().addOnSuccessListener(getActivity(), new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
if (location != null) {
myLocation=location;
Toast.makeText( getActivity(),"Latitude: "+location.getLatitude()+" Longitude: "+location.getLongitude(), Toast.LENGTH_SHORT).show();
}
}
}).addOnFailureListener(getActivity(), new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText( getActivity(),"It wasn´t possible to determine your location", Toast.LENGTH_SHORT).show();
}
});
getApi().getNearbyRestaurants(myLocation.getLatitude(),myLocation.getLongitude(),20,10000,"rating","desc","75be9f9e2239fe637bf9cb1b46979d91")
.enqueue(new Callback<ApiResponse>() {
@Override
public void onResponse(Call<ApiResponse> call, Response<ApiResponse> response) {
List<Restaurant> restaurants=response.body().getRestaurants();
mAdapter = new RestaurantAdapter(context, restaurantsList);
mRecyclerView.setAdapter(mAdapter);
RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(context, DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(itemDecoration);
for (int i = 0; i < restaurants.size(); i++) {
restaurantsList.add(restaurants.get(i).getRestaurant());
mAdapter.notifyItemInserted(i);
}
}
@Override
public void onFailure(Call<ApiResponse> call, Throwable t) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage("Couldn´t find any nearby restaurants");
AlertDialog mDialog = builder.create();
mDialog.show();
}
});
}
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View mContentView = inflater.inflate(R.layout.restaurants_list, container,false);
mRecyclerView = mContentView.findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(mContentView.getContext()));
return mContentView;
}
@Override
public void onResume() {
super.onResume();
}
@Override public void onAttach(Activity activity) {
super.onAttach(activity);
try{
listener= (OnRestaurantClickedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnButtonClicked");
}
}
private Retrofit getRetrofit(){
return new Retrofit.Builder()
.baseUrl("https://developers.zomato.com/api/v2.1/")
.addConverterFactory(GsonConverterFactory.create())
.build();
}
private ZomatoApi getApi(){
return getRetrofit().create(ZomatoApi.class);
}
private void getLastLocation(){
if (ActivityCompat.checkSelfPermission(getContext(),
Manifest.permission.ACCESS_FINE_LOCATION )!= PackageManager.PERMISSION_GRANTED) {
requestPermissions();
return;
}
}
private void requestPermissions(){
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_FINE_LOCATION);
}
}
新代码
public class RestaurantsList extends Fragment {
private RestaurantAdapter mAdapter;
private RecyclerView mRecyclerView;
protected static List<Restaurant_> restaurantsList;
private Context context;
protected static OnRestaurantClickedListener listener;
private FirebaseAuth mAuth;
private static final int REQUEST_FINE_LOCATION=100;
private LocationRequest mLocationRequest;
private LocationCallback mLocationCallback;
private FusedLocationProviderClient mFusedLocationClient;
private static final String TAG = "LOCATION";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = getContext();
mAuth = FirebaseAuth.getInstance();
restaurantsList= new ArrayList<>(50);
getLastLocation();
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(getActivity());
}
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View mContentView = inflater.inflate(R.layout.restaurants_list, container,false);
mRecyclerView = mContentView.findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(mContentView.getContext()));
return mContentView;
}
@Override
public void onResume() {
super.onResume();
}
@Override public void onAttach(Activity activity) {
super.onAttach(activity);
try{
listener= (OnRestaurantClickedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnButtonClicked");
}
}
private Retrofit getRetrofit(){
return new Retrofit.Builder()
.baseUrl("https://developers.zomato.com/api/v2.1/")
.addConverterFactory(GsonConverterFactory.create())
.build();
}
private ZomatoApi getApi(){
return getRetrofit().create(ZomatoApi.class);
}
private void getLastLocation(){
if (ActivityCompat.checkSelfPermission(getContext(),
Manifest.permission.ACCESS_FINE_LOCATION )!= PackageManager.PERMISSION_GRANTED) {
requestPermissions();
return;
}
}
private void requestPermissions(){
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_FINE_LOCATION);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == REQUEST_FINE_LOCATION) {
if (grantResults.length <= 0) {
// If user interaction was interrupted, the permission request is cancelled and you
// receive empty arrays.
Log.i(TAG, "User interaction was cancelled.");
} else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted.
getRestaurants();
}
}
}
private void getRestaurants(){
mFusedLocationClient.getLastLocation().addOnSuccessListener(getActivity(), new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
if (location != null) {
getApi().getNearbyRestaurants(location.getLatitude(),location.getLongitude(),20,10000,"rating","desc","75be9f9e2239fe637bf9cb1b46979d91")
.enqueue(new Callback<ApiResponse>() {
@Override
public void onResponse(Call<ApiResponse> call, Response<ApiResponse> response) {
List<Restaurant> restaurants=response.body().getRestaurants();
mAdapter = new RestaurantAdapter(context, restaurantsList);
mRecyclerView.setAdapter(mAdapter);
RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(context, DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(itemDecoration);
for (int i = 0; i < restaurants.size(); i++) {
restaurantsList.add(restaurants.get(i).getRestaurant());
mAdapter.notifyItemInserted(i);
}
}
@Override
public void onFailure(Call<ApiResponse> call, Throwable t) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage("Couldn´t find any nearby restaurants");
AlertDialog mDialog = builder.create();
mDialog.show();
}
});
}
}
}).addOnFailureListener(getActivity(), new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText( getActivity(),"It wasn´t possible to determine your location", Toast.LENGTH_LONG).show();
}
});
}
}
您正在执行两个异步任务,它们都将在未来的某个时间点完成(获取位置并进行 Zomato API 调用)。但是你在这里同时做它们。即使位置代码在 API 调用代码之上,它实际上并没有在执行 API 调用之前等待位置。
您需要做的是将 Zomato API 调用移到它自己的方法中。然后从 FusedLocationProvider 的 onSuccess(Location)
回调方法中调用此方法。这样,您就可以在尝试使用该位置之前等待该位置出现。
我有一个片段,我想在其中获取当前坐标,然后使用 Retrofit 向 Zomato Api 发出请求,但我当前的位置 return 为空。我试图删除与我的 api 调用和应用 return 我正确的经纬度相关的代码。我做错了什么?下面是我的 Java class.
我的片段
public class RestaurantsList extends Fragment {
private RestaurantAdapter mAdapter;
private RecyclerView mRecyclerView;
protected static List<Restaurant_> restaurantsList;
private Context context;
protected static OnRestaurantClickedListener listener;
private FirebaseAuth mAuth;
private static final int REQUEST_FINE_LOCATION=100;
private LocationRequest mLocationRequest;
private LocationCallback mLocationCallback;
private FusedLocationProviderClient mFusedLocationClient;
private Location myLocation;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = getContext();
mAuth = FirebaseAuth.getInstance();
restaurantsList= new ArrayList<>(50);
getLastLocation();
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(getActivity());
mFusedLocationClient.getLastLocation().addOnSuccessListener(getActivity(), new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
if (location != null) {
myLocation=location;
Toast.makeText( getActivity(),"Latitude: "+location.getLatitude()+" Longitude: "+location.getLongitude(), Toast.LENGTH_SHORT).show();
}
}
}).addOnFailureListener(getActivity(), new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText( getActivity(),"It wasn´t possible to determine your location", Toast.LENGTH_SHORT).show();
}
});
getApi().getNearbyRestaurants(myLocation.getLatitude(),myLocation.getLongitude(),20,10000,"rating","desc","75be9f9e2239fe637bf9cb1b46979d91")
.enqueue(new Callback<ApiResponse>() {
@Override
public void onResponse(Call<ApiResponse> call, Response<ApiResponse> response) {
List<Restaurant> restaurants=response.body().getRestaurants();
mAdapter = new RestaurantAdapter(context, restaurantsList);
mRecyclerView.setAdapter(mAdapter);
RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(context, DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(itemDecoration);
for (int i = 0; i < restaurants.size(); i++) {
restaurantsList.add(restaurants.get(i).getRestaurant());
mAdapter.notifyItemInserted(i);
}
}
@Override
public void onFailure(Call<ApiResponse> call, Throwable t) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage("Couldn´t find any nearby restaurants");
AlertDialog mDialog = builder.create();
mDialog.show();
}
});
}
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View mContentView = inflater.inflate(R.layout.restaurants_list, container,false);
mRecyclerView = mContentView.findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(mContentView.getContext()));
return mContentView;
}
@Override
public void onResume() {
super.onResume();
}
@Override public void onAttach(Activity activity) {
super.onAttach(activity);
try{
listener= (OnRestaurantClickedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnButtonClicked");
}
}
private Retrofit getRetrofit(){
return new Retrofit.Builder()
.baseUrl("https://developers.zomato.com/api/v2.1/")
.addConverterFactory(GsonConverterFactory.create())
.build();
}
private ZomatoApi getApi(){
return getRetrofit().create(ZomatoApi.class);
}
private void getLastLocation(){
if (ActivityCompat.checkSelfPermission(getContext(),
Manifest.permission.ACCESS_FINE_LOCATION )!= PackageManager.PERMISSION_GRANTED) {
requestPermissions();
return;
}
}
private void requestPermissions(){
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_FINE_LOCATION);
}
}
新代码
public class RestaurantsList extends Fragment {
private RestaurantAdapter mAdapter;
private RecyclerView mRecyclerView;
protected static List<Restaurant_> restaurantsList;
private Context context;
protected static OnRestaurantClickedListener listener;
private FirebaseAuth mAuth;
private static final int REQUEST_FINE_LOCATION=100;
private LocationRequest mLocationRequest;
private LocationCallback mLocationCallback;
private FusedLocationProviderClient mFusedLocationClient;
private static final String TAG = "LOCATION";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = getContext();
mAuth = FirebaseAuth.getInstance();
restaurantsList= new ArrayList<>(50);
getLastLocation();
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(getActivity());
}
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View mContentView = inflater.inflate(R.layout.restaurants_list, container,false);
mRecyclerView = mContentView.findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(mContentView.getContext()));
return mContentView;
}
@Override
public void onResume() {
super.onResume();
}
@Override public void onAttach(Activity activity) {
super.onAttach(activity);
try{
listener= (OnRestaurantClickedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnButtonClicked");
}
}
private Retrofit getRetrofit(){
return new Retrofit.Builder()
.baseUrl("https://developers.zomato.com/api/v2.1/")
.addConverterFactory(GsonConverterFactory.create())
.build();
}
private ZomatoApi getApi(){
return getRetrofit().create(ZomatoApi.class);
}
private void getLastLocation(){
if (ActivityCompat.checkSelfPermission(getContext(),
Manifest.permission.ACCESS_FINE_LOCATION )!= PackageManager.PERMISSION_GRANTED) {
requestPermissions();
return;
}
}
private void requestPermissions(){
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_FINE_LOCATION);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == REQUEST_FINE_LOCATION) {
if (grantResults.length <= 0) {
// If user interaction was interrupted, the permission request is cancelled and you
// receive empty arrays.
Log.i(TAG, "User interaction was cancelled.");
} else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted.
getRestaurants();
}
}
}
private void getRestaurants(){
mFusedLocationClient.getLastLocation().addOnSuccessListener(getActivity(), new OnSuccessListener<Location>() {
@Override
public void onSuccess(Location location) {
if (location != null) {
getApi().getNearbyRestaurants(location.getLatitude(),location.getLongitude(),20,10000,"rating","desc","75be9f9e2239fe637bf9cb1b46979d91")
.enqueue(new Callback<ApiResponse>() {
@Override
public void onResponse(Call<ApiResponse> call, Response<ApiResponse> response) {
List<Restaurant> restaurants=response.body().getRestaurants();
mAdapter = new RestaurantAdapter(context, restaurantsList);
mRecyclerView.setAdapter(mAdapter);
RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(context, DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(itemDecoration);
for (int i = 0; i < restaurants.size(); i++) {
restaurantsList.add(restaurants.get(i).getRestaurant());
mAdapter.notifyItemInserted(i);
}
}
@Override
public void onFailure(Call<ApiResponse> call, Throwable t) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage("Couldn´t find any nearby restaurants");
AlertDialog mDialog = builder.create();
mDialog.show();
}
});
}
}
}).addOnFailureListener(getActivity(), new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText( getActivity(),"It wasn´t possible to determine your location", Toast.LENGTH_LONG).show();
}
});
}
}
您正在执行两个异步任务,它们都将在未来的某个时间点完成(获取位置并进行 Zomato API 调用)。但是你在这里同时做它们。即使位置代码在 API 调用代码之上,它实际上并没有在执行 API 调用之前等待位置。
您需要做的是将 Zomato API 调用移到它自己的方法中。然后从 FusedLocationProvider 的 onSuccess(Location)
回调方法中调用此方法。这样,您就可以在尝试使用该位置之前等待该位置出现。