Na het refactoren krijg ik een null object reference

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • superky
  • Registratie: April 2012
  • Laatst online: 05-10 00:22
Hey ik krijg de volgende error:

code:
1
2
3
E/AndroidRuntime: java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.android.gms.maps.model.Marker com.google.android.gms.maps.GoogleMap.addMarker(com.google.android.gms.maps.model.MarkerOptions)' on a null object reference
E/AndroidRuntime:     at com.example.yomac_000.rsrpechhulp.BreakDownOnMaps.handleNewLocation(BreakDownOnMaps.java:57)
E/AndroidRuntime:     at utils.MyLocationListener.onConnected(MyLocationListener.java:52)


En dat komt door deze regel code:
code:
1
gMap.addMarker(options);


En door deze regel code:
code:
1
breakDownOnMaps.handleNewLocation(location);


Hieronder kunnen jullie mijn code zien:

MyLocationListener.java:
Link: http://pastebin.com/A0DFi68G

En hier is de code van BreakDownOnMaps.java:
Link: http://pastebin.com/9Kw9A75j

Maar eigenlijk zou ik geen null object reference als error mogen krijgen. Omdat de getMapAsync() method garandeert dat ik geen null GoogleMap object krijg. Volgens Google:
"Use getMapAsync(OnMapReadyCallback) instead. The callback method provides you with a GoogleMap instance guaranteed to be non-null and ready to be used."

Source link: https://developers.google....maps.OnMapReadyCallback)

Voordat ik het had gerefactored had ik al mijn code in BreakDownOnMaps.java. En alle code werkte toen gewoon. Dus mochten jullie willen zien hoe het er ervóór eruit zag, dan kunnen jullie dat zien via de onderstaande link:

Link: http://pastebin.com/p6c3UeSC

Ook heb ik gehoord dat de kunst van refactoren is dat je geen code gaat toevoegen. Maar dat je alleen de code gaat veranderen op de manier hoe het eruit ziet. Dus ik heb geen idee wat ik fout doe.

Alle reacties


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Refactoren heeft niks te maken met code verkorten. Refactoren is het herstructureren van je code zodat die duidelijker is, of beter onderhoudbaar, of minder foutgevoelig. Daarmee kan 'ie best langer worden.

Zet je code ook even netjes inline in je topic neer. Op deze manier is je topic waardeloos voor andere gebruikers die het in de search tegenkomen als Pastebin eenmaal je code weggehaald heeft, en zo rollen we niet op dit forum. ;)

Wat betreft je probleem: ik weet niet precies hoe dit alles hoort te werken, maar ik gok zomaar dat het location changed-event getriggerd wordt voordat je callback klaar is. Gewoon netjes defensief programmeren en checken of je map null is voordat je hem gebruikt en alles werkt vast vanzelf...

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • BoringDay
  • Registratie: Maart 2009
  • Laatst online: 13-05 21:49
"Attempt to invoke virtual method"
"on a null object reference"

Dit soort fouten kan je vinden door te debuggen (watch/breakpoint)
Als het voor refactoren wel werkte en erna niet dan is je refactoring niet goed gegaan (lijkt me logisch)

Acties:
  • 0 Henk 'm!

  • alex3305
  • Registratie: Januari 2004
  • Laatst online: 11-10 22:19
Controleer even of je Google Map instantie niet null is, misschien dat je geen permissie krijgt van het systeem oid. Daarnaast zou je hetzelfde kunnen doen voor je locatie. Daarnaast kun je met Android Studio prachtig debuggen, zoals BoringDay al aangeeft.

Verder zou ik sowieso die System.out.println() calls weghalen en vervangen door Logcat of een sjieke SLF4J Logger. Dat is makkelijker debuggen en ziet er sowieso netter uit.

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

BoringDay schreef op vrijdag 22 januari 2016 @ 09:17:
"Attempt to invoke virtual method"
"on a null object reference"

Dit soort fouten kan je vinden door te debuggen (watch/breakpoint)
Als het voor refactoren wel werkte en erna niet dan is je refactoring niet goed gegaan (lijkt me logisch)
Als ik in mijn vorige post goed geraden heb treedt het probleem mogelijk/waarschijnlijk niet op tijdens het steppen door je code omdat het een concurrency-probleempje is. Het ophalen/aanmaken van het map-object gebeurt asynchroon en het zou zomaar kunnen dat die vertraging bij een handmatige debugactie geen probleem meer is omdat je de code die ervan afhankelijk is vertraagt.

Neemt inderdaad niet weg dat er beter te debuggen valt dan de TS nu gedaan lijkt te hebben.

[ Voor 6% gewijzigd door NMe op 22-01-2016 11:34 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • superky
  • Registratie: April 2012
  • Laatst online: 05-10 00:22
NMe schreef op vrijdag 22 januari 2016 @ 01:22:
Refactoren heeft niks te maken met code verkorten. Refactoren is het herstructureren van je code zodat die duidelijker is, of beter onderhoudbaar, of minder foutgevoelig. Daarmee kan 'ie best langer worden.

Zet je code ook even netjes inline in je topic neer. Op deze manier is je topic waardeloos voor andere gebruikers die het in de search tegenkomen als Pastebin eenmaal je code weggehaald heeft, en zo rollen we niet op dit forum. ;)

Wat betreft je probleem: ik weet niet precies hoe dit alles hoort te werken, maar ik gok zomaar dat het location changed-event getriggerd wordt voordat je callback klaar is. Gewoon netjes defensief programmeren en checken of je map null is voordat je hem gebruikt en alles werkt vast vanzelf...
Ik had all een null check gedaan in mijn GoogleMap object in de onMapReady() method object, maar die is nooit null..

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Natuurlijk niet in je onMapReady, dat event wordt getriggerd als je map inderdaad helemaal klaar is met laden. Het probleem zit hem in je onLocationChanged. Daar gebruik je je map ook terwijl die daar helemaal niet per se ready hoeft te zijn. Je location listener draait immers al lang voordat jij je map initialiseert.

[ Voor 31% gewijzigd door NMe op 22-01-2016 12:25 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • The_Ghost16
  • Registratie: Januari 2004
  • Laatst online: 19-05 10:05
In de 'MyLocationListener' wordt een onConnected method gebruikt die met een instantie van 'BreakDownOnMaps' werkt. Die probeert dan weer een marker te zetten in de google maps. Echter is de 'setgMap' in de 'BreakDownOnMaps' nog nooit aangeroepen op dat moment (kijkend naar de 2 classes).

Acties:
  • 0 Henk 'm!

  • BoringDay
  • Registratie: Maart 2009
  • Laatst online: 13-05 21:49
@superky

Ik mis op alle fronten commentaar in je code?
Als ik kijk naar je onCreate methode daar zie ik buildApi() staan.
Nu heb ik iets van wat in vredesnaam moet ik daarmee! snap je me? (slecht begrijpbaar voor iemand die de code niet geschreven heeft)

Acties:
  • 0 Henk 'm!

  • superky
  • Registratie: April 2012
  • Laatst online: 05-10 00:22
The_Ghost16 schreef op vrijdag 22 januari 2016 @ 12:28:
In de 'MyLocationListener' wordt een onConnected method gebruikt die met een instantie van 'BreakDownOnMaps' werkt. Die probeert dan weer een marker te zetten in de google maps. Echter is de 'setgMap' in de 'BreakDownOnMaps' nog nooit aangeroepen op dat moment (kijkend naar de 2 classes).
Het klopt wat je zegt. Ik heb nu de OnMapReadyCallback interface geimplementeert in MyLocationListener.java. Omdat ik een niet null GoogleMap object nodig heb om hem mee te geven als argument voor de handleNewLocation() method.

Maar hoe kan ik de onMapReady() method aanroepen in MyLocationListener.java? Want de enige manier om dat aan te roepen is door getMapAsync() aan te roepen. Maar hiervoor moet MyLocationListener.java de FragmentActivity gaan overerven...

Acties:
  • 0 Henk 'm!

  • BoringDay
  • Registratie: Maart 2009
  • Laatst online: 13-05 21:49
onMapReady Is een event dat wordt aan geroepen door getMapAsync als die ready is.
Dat betekent dat je alleen vanaf dat moment die event kan en mag gebruiken.

Wat jij nu probeert is een oplossing te verzinnen in een event die daar niet voor bedoeld is.

Mijn advies is, zet eerst eens commentaar bij je code:
- wat moet het doen;
- waar zijn de parameters voor bedoeld;
- wat zijn de condities;

Dan herken je ook sneller of je aanpak wel correct is of misschien noodzakelijk is om te herschrijven.

Acties:
  • 0 Henk 'm!

  • The_Ghost16
  • Registratie: Januari 2004
  • Laatst online: 19-05 10:05
superky schreef op zaterdag 23 januari 2016 @ 14:21:
[...]


Het klopt wat je zegt. Ik heb nu de OnMapReadyCallback interface geimplementeert in MyLocationListener.java. Omdat ik een niet null GoogleMap object nodig heb om hem mee te geven als argument voor de handleNewLocation() method.

Maar hoe kan ik de onMapReady() method aanroepen in MyLocationListener.java? Want de enige manier om dat aan te roepen is door getMapAsync() aan te roepen. Maar hiervoor moet MyLocationListener.java de FragmentActivity gaan overerven...
Kijkend naar je code zie ik 2 mogelijke oplossingen voor je probleem.

Je kunt in de onStart() van de 'BreakDownOnMaps' de getMapAsync() alvast aanroepen zodat de map alvast ingeladen is als je hem nodig hebt. Hierdoor kun je dus vanuit de handleNewLocation() netjes een marker zetten in de map.

Ook kun je er voor kiezen om bij de aanroep van handleNewLocation() te controleren of de map al is ingeladen, zo niet dan voor je eerst de getMapAsync() uit.

Wat mij dan tevens verstandig lijkt is om in handleNewLocation() altijd te controleren of de map al geladen is. Zo niet sla je de locatie op in een array die je dan weer kunt verwerken zodra de onMapReady() wordt uitgevoerd. Dit om alsnog je markers op de map te zien.

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Je kan gewoon uit onLocationChanged (of desnoods uit handleNewLocation) breken als je nog geen map hebt. Die wordt toch elke keer opnieuw aangeroepen als je positie verandert, dus het boeit geen bal als je geen marker neerzet bij het wijzigen van je positie wanneer je toch nog geen map hebt om die marker op te zetten... Die callback zorgt vervolgens voor de rest als het goed is.

Maar nogmaals: zet eens netjes je code in code-blokken in de topicstart zodat anderen straks ook nog iets aan je topic hebben.

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.

Pagina: 1