当我尝试在第log("11111111", longitude);
行打印经度值时,它运行良好,并向我显示了值。 但是,当我尝试在log.e(22222222", longitude);
打印它时,我得到了一个NullPointerException
.
我知道我得到了空指针异常导致log.e("2222222",经度(在addOnCompleteListner之前调用。 但是我应该怎么做才能等待addOnCompleteListner完成,然后访问值
这是我的代码:
package com.example.karem.currentlocation;
import android.Manifest;
import android.app.Application;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
class GetMyCoordinate extends Application {
Context context;
GetMyCoordinate(Context context) {
this.context = context;
}
private Boolean mLocationPermissionsGranted = false;
private FusedLocationProviderClient mFusedLocationProviderClient;
String longitude;
String getDeviceLocation() {
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context);
try {
final Task location = mFusedLocationProviderClient.getLastLocation();
location.addOnCompleteListener(new OnCompleteListener() {
@Override
public void onComplete(@NonNull Task task) {
if (task.isSuccessful()) {
Location currentLocation = (Location) task.getResult();
longitude = String.valueOf(currentLocation.getLongitude());
Log.e("1111111111", longitude);
}
}
});
Log.e("22222222", longitude);
} catch (SecurityException e) {
}
return longitude;
}
}
问题不在于你认为的那样。longitude
变量在两个地方都在范围内(不是"勺子"!(。
实际问题是在语句中:
log.e(22222222", longitude);
您正在longitude
初始化变量之前访问它。 初始化是在调用onComplete
方法时完成的。 当location
提到的Task
完成时,就会发生这种情况。
(应该还有另一个线索。 如果您查看日志,您可能会看到"22222222"日志消息出现在"11111111"日志消息之前。
侦听器函数本质上是异步的,因此您定义或分配的任何内容在异步函数范围内都是有效的。因此,如果您尝试在其范围之外访问它,则会获得该范围内的值。正如您刚刚声明的"经度"一样,它的值为 Null,因此您会收到空指针异常。如果您将其初始化为某个值,例如"x",那么您将从 Log 语句打印 x,其中 2222222 作为第一个参数。
希望它能消除你的疑问
问题实际上出在线程切换中,而不是上面提到的斯蒂芬 C超出范围的情况。发生的情况是,当您的代码进入 try{} 块时,您已将控件转移到您的(FusedLocationProviderClient 并添加了侦听器(,直到从后台线程响应您的位置。调用方线程无法等待它。因此,它实际上继续打印log.e("22222222",经度((当响应尚未到达时(,这就是出现空值情况的原因。
这个问题的解决方案可以通过接口轻松实现。
1 - 首先定义接口
public interface ILocationReceived {
onLocationRecieved(String longitude);
}
2 - 将该接口传递给方法
public void getDeviceLocation(ILocationRecieved locationRecieved) {
}
3 - 在你中异步方法传递接收的位置
locationRecieved.onLocationRecieved(longitude);
4 - 在实现该方法时,只需接收经度。
new GetMyCoordinate().getDeviceLocation( longitude ->
// here you get your longitude from the async method.
// use it as you need
print (longitude)
(;
注意:在没有任何 ide 的情况下编写了此内容,因此可能包含一些语法错误。