当我使用 Retrofit 时,Google 位置服务返回一个空位置

Posted

技术标签:

【中文标题】当我使用 Retrofit 时,Google 位置服务返回一个空位置【英文标题】:Google location services returning a null location when I use Retrofit 【发布时间】:2020-12-18 22:05:38 【问题描述】:

我有一个片段,我想在其中获取当前坐标,然后使用 Retrofit 向 Zomato Api 发出请求,但我当前的位置返回 null。我试图删除与我的 api 调用相关的代码,应用程序返回我正确的纬度和经度。我在做什么错?下面是我的 Java 类。

我的片段

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();
            
        );
    




【问题讨论】:

【参考方案1】:

您正在执行两个异步任务,这两个任务都将在未来某个时间点完成(获取位置和进行 Zomato API 调用)。但是你在这里同时做它们。即使位置代码在 API 调用代码之上,它实际上并没有在执行 API 调用之前等待位置。

您需要做的是将 Zomato API 调用移至其自己的方法。然后从 FusedLocationProvider 的onSuccess(Location) 回调方法中调用该方法。这样,您在尝试使用该位置之前等待该位置进入。

【讨论】:

我已经解决了?但是我有一个小错误。如果是第一次使用该应用程序,它会显示 onFailure toast,然后向我显示授权对话框,导致响应为空。关于如何解决这个问题的任何提示? 您的意思是位置权限对话框? 请求Location运行时权限有很多步骤,特别是如果你想正确地做到这一点:github.com/android/location-samples/blob/master/BasicLocation/… 是的。如果是第一次,它首先显示 toast,然后才显示权限对话框。如果不是,应用程序运行正常 查看上面链接中的代码。您必须将其视为另一个回调。所以你请求Location权限,然后你可以从onRequestPermissionsResult()方法实际获取Location,然后从FusedLocationProvider的onSuccess(Location)回调方法你最终可以调用Zomato API。

以上是关于当我使用 Retrofit 时,Google 位置服务返回一个空位置的主要内容,如果未能解决你的问题,请参考以下文章

当我使用proguard并启用minify和shrinkresources时,Retrofit body request是空白的

使用 google locationManager 获取 0.0 位置

将 proguard 与 retrofit2 和 rxjava 一起使用时出错

使用 JSON 在 Google Maps API 中设置位置并保存最后一个已知位置

如何使用Traccar API获得实时位置?

当 RxJava 发生不同事件时如何得到通知?