2017-09-03 79 views
0

好日子,getLatitude和getLongitude引发NullPointerException异常

请你解释一下我为什么getLongitude和getLatitude返回一个NullPointerException?

事实是这个问题已经解决了,但有一件事情是我的论文协调员可能会问的。情况是我必须得到用户当前的坐标(经度和纬度)。我决定使用FusedLocationClient.getLastLocation()来获得坐标。

mFusedLocationClient = getFusedLocationProviderClient(this); 

//app already crashes once the line below is executed 

mFusedLocationClient.getLastLocation().addOnSuccessListener(this, new OnSuccessListener<Location>() { 
      @Override 
      public void onSuccess(Location location) { 
       if(location != null){ 
        //myLocation is an instance variable of this class 
        myLocation = location; 
       }else{ 
        Toast.makeText(PlaceCategoriesActivity.this, "Location fetch failed!", Toast.LENGTH_SHORT).show(); 
       } 
      } 
     }); 

     latitude = myLocation.getLatitude(); //this line throws NullPointerException 
     longitude = myLocation.getLongitude(); 

的应用程序似乎编译细但随后崩溃,在通过上myLocation.getLatiude()和myLocation.getLongititude()将一个断点调试检查,事实证明,这种方法调用一个空指针异常,这对我来说很奇怪,因为myLocation已经引用了addOnSuccessListener的onSuccess方法所带来的位置对象。

 mFusedLocationClient = getFusedLocationProviderClient(this); 

     mFusedLocationClient.getLastLocation().addOnSuccessListener(this, new OnSuccessListener<Location>() { 
      @Override 
      public void onSuccess(Location location) { 
       if(location != null){ 
        myLocation = location; 

        //moved the 2 lines of code and it now works 
        latitude = myLocation.getLatitude(); 
        longitude = myLocation.getLongitude(); 
       }else{ 
        Toast.makeText(PlaceCategoriesActivity.this, "Location fetch failed!", Toast.LENGTH_SHORT).show(); 
       } 
      } 
     }); 

     //Toast returns a value of 0 on latitude and 0 on longitude 
     Toast.makeText(this, "Lat: " + latitude + "Long: + " + longitude, Toast.LENGTH_SHORT).show(); 

有趣的是,经度和纬度显示在面包和:

我已经通过移动代码的最后两行和侦听器内投入这样的问题解决了既有的0

回答

3

这对我来说是奇怪的,因为myLocation已经引用了通过的addOnSuccessListener

的的onSuccess方法所带来的位置对象让我们来简化你的第一个代码:

mFusedLocationClient = getFusedLocationProviderClient(this); 

     latitude = myLocation.getLatitude(); //this line throws NullPointerException 
     longitude = myLocation.getLongitude(); 

这里,myLocation尚未分配一个值。如果您尚未在前面的行中为myLocation赋值,myLocation将为null,您将得到NullPointerException

现在,让我们恢复了一些行的代码片段:

mFusedLocationClient = getFusedLocationProviderClient(this); 

//app already crashes once the line below is executed 

mFusedLocationClient.getLastLocation().addOnSuccessListener(this, new OnSuccessListener<Location>() { 
      @Override 
      public void onSuccess(Location location) { 
      } 
     }); 

     latitude = myLocation.getLatitude(); //this line throws NullPointerException 
     longitude = myLocation.getLongitude(); 

最后一个字addOnSuccessListener()是“听众”。这表明你正在注册一个事件监听器。通常—虽然不总是—这样一个监听器只在将来的事件中被调用。在稍后的某个时间,onSuccess()很可能不会被调用。但是,您的程序会继续运行,然后您尝试拨打myLocation上的getLatitude()。由于我们还没有做任何事情来为myLocation分配一个值,因此它将是null,并且您将以NullPointerException崩溃。

因此,虽然您的第一个代码段确实为myLocation赋值,但您作为程序员必须假定,直到将来某个时候(例如,当我们获得新的定位修复时)它才会这样做。在onSuccess()已为其分配值之前,请勿尝试使用myLocation

+0

非常感谢您的详细解释 –

1

一个值,你不应该addOnSuccessListener之后添加这些行:因为你必须要等到

latitude = myLocation.getLatitude(); //this line throws NullPointerException 
longitude = myLocation.getLongitude(); 
成功获得 LastLocation

将这些行移动到onSuccess方法!


对于nullPointerException的原因,是因为myLocation尚未初始化!

+0

非常感谢你的回复:d –

1

你只需要显示的位置,当你得到它,而不是之前。这就是说,只需将显示代码放入监听器即可。

mFusedLocationClient = getFusedLocationProviderClient(this); 

// Register a listener, that will be called when the location will be available 
mFusedLocationClient.getLastLocation().addOnSuccessListener(this, new OnSuccessListener<Location>() { 
    @Override 
    public void onSuccess(Location location) { 
     if (location != null) { 
      // We have a location! 
      myLocation = location; 
      // So print it now 
      latitude = myLocation.getLatitude(); 
      longitude = myLocation.getLongitude(); 
      Toast.makeText(PlaceCategoriesActivity.this, "Lat: " + latitude + "Long: + " + longitude, Toast.LENGTH_SHORT).show(); 
     } else { 
      Toast.makeText(PlaceCategoriesActivity.this, "Location fetch failed!", Toast.LENGTH_SHORT).show(); 
     } 
    } 
}); 

// Loading, as we wait for listener to be called 
Toast.makeText(this, "Loading...", Toast.LENGTH_SHORT).show(); 
+0

的是您在代码的最后一行添加的注释帮助我理解我在节目中的错误,非常感谢你很多 –

1

例子:

class LocationApi : Service(), GoogleApiClient.ConnectionCallbacks, 
     GoogleApiClient.OnConnectionFailedListener, LocationListener { 

    private var myGoogleApiClient: GoogleApiClient? = null 
    private val myLocationRequest = LocationRequest.create() 

    override fun onBind(intent: Intent?): IBinder? { 
     return null 
    } 

    override fun onCreate() { 
     super.onCreate() 
     myGoogleApiClient = GoogleApiClient.Builder(this) 
       .addApi(LocationServices.API) 
       .addOnConnectionFailedListener(this) 
       .addConnectionCallbacks(this) 
       .build() 
    } 

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { 
     myGoogleApiClient?.connect() 
     return super.onStartCommand(intent, flags, startId) 
    } 

    override fun onDestroy() { 
     myGoogleApiClient?.disconnect() 

     if (myGoogleApiClient != null && myGoogleApiClient?.isConnected!!) { 
      LocationServices.getFusedLocationProviderClient(this).removeLocationUpdates(locationCallBack) 
     } 

     super.onDestroy() 
    } 

    override fun onConnected(bundle: Bundle?) { 
     //here u can define your interval and priority 

     // request locations, check permissions ok 
     if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { 

      LocationServices.getFusedLocationProviderClient(this).requestLocationUpdates(myLocationRequest, locationCallBack, Looper.myLooper()) 
     } 
    } 

    override fun onConnectionSuspended(p0: Int) { 
    } 

    override fun onConnectionFailed(p0: ConnectionResult) { 
    } 

    override fun onLocationChanged(location: Location?) { 
     //saving location on DB 
     LocationInteractor(location) 
    } 

    private val locationCallBack = object : LocationCallback() { 
     override fun onLocationResult(location: LocationResult) { 
      super.onLocationResult(location) 
      onLocationChanged(location.lastLocation) 
     } 
    } 
} 
相关问题