2017-09-03 78 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) 
     } 
    } 
} 
相關問題