在下面的代码中,我可以在地图上创建标记。每当我尝试使用runnable运行它时,都会出现错误,指出googleMap的错误为:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.journaldev.MapsInAction/com.journaldev.MapsInAction.MainActivity}: 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
代码如下:
import android.graphics.Point;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.Projection;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {
SupportMapFragment mapFragment;
private GoogleMap googleMap;
double latitude=12.9716;
double longitude=77.5946;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mapFragment.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(GoogleMap googleMap) {
googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
googleMap.addMarker(new MarkerOptions()
.position(new LatLng(latitude, longitude))
.title("Bus Location")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)));
googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(latitude, longitude), 15));
}
});
}
});
periodicUpdate.run();
}
Handler handler = new Handler();
private Runnable periodicUpdate = new Runnable() {
@Override
public void run() {
handler.postDelayed(periodicUpdate, 10*1000 - SystemClock.elapsedRealtime()%1000);
latitude+=0.01;
longitude+=0.01;
MarkerOptions a = new MarkerOptions()
.position(new LatLng(50,6));
Marker m = googleMap.addMarker(a);
m.setPosition(new LatLng(50,5));
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onMapReady(GoogleMap googleMap)
{
googleMap.addMarker(new MarkerOptions()
.position(new LatLng(latitude, longitude))
.title("Bus Location")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)));
googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(latitude, longitude), 15));
}
}
如何确保代码也每10秒更新一次标记?如果删除了Runnable代码,则该代码可与所示标记完美配合。使用Runnable代码,它会因上面的错误而崩溃。
答案 0 :(得分:2)
getMapAsync异步初始化Map。
因此,当您第一次在Runnable中调用googleMap.addMarker()时,它会崩溃,因为Map尚未初始化,并且googleMap为null。
解决此问题的最简单方法是将periodicUpdate.run();
移至onMapReady()
回调
另外,您也不要忘记在onPause()
答案 1 :(得分:0)
您的代码有几个问题。
最初,它崩溃是因为您在periodicUpdate.run();
中尝试通过在未初始化的全局Marker m = googleMap.addMarker(a);
对象上调用addMarker()
来创建标记(private GoogleMap googleMap;
)。如果将private GoogleMap googleMap;
重命名为private GoogleMap mGoogleMap;
并在mGoogleMap
中通过onMapReady(GoogleMap googleMap)
初始化mGoogleMap = googleMap
中的addMarker()
会比调用Marker mGoogleMap = googleMap.addMarker(a);
更好:{{ 1}}。
另外,您应该摆脱两个onMapReady()
方法。并且您应该在periodicUpdate.run();
内部开始调用onMapReady()
,因为在其他情况下,可以在创建Marker m = mGoogleMap.addMarker(a);
之前调用mGoogleMap
。并且您应该将Marker m
声明为全局(private Marker mMarker
),以便在创建更新的标记之前将其删除。似乎您没有更新标记的LatLng ...所以,有很多工作...
答案 2 :(得分:0)
您要在可运行的地图初始化之前放置标记。这就是为什么它导致空指针异常并导致应用程序崩溃的原因。进行空指针检查将解决此错误。试试这个:
@Override
public void run() {
handler.postDelayed(periodicUpdate, 10 * 1000 - SystemClock.elapsedRealtime() % 1000);
latitude += 0.01;
longitude += 0.01;
MarkerOptions a = new MarkerOptions()
.position(new LatLng(50, 6));
if (googleMap != null) {
Marker m = googleMap.addMarker(a);
}
m.setPosition(new LatLng(50, 5));
}
答案 3 :(得分:0)
您尚未初始化变量googleMap
。并且在使用googleMap
之前,您必须确保Google Map已准备就绪。因此,请遵循以下代码:
private Runnable periodicUpdate = new Runnable() {
@Override
public void run() {
handler.postDelayed(periodicUpdate, 10*1000 - SystemClock.elapsedRealtime()%1000);
if(googleMap){
latitude+=0.01;
longitude+=0.01;
MarkerOptions a = new MarkerOptions()
.position(new LatLng(50,6));
Marker m = googleMap.addMarker(a);
m.setPosition(new LatLng(50,5));
}
}
};
@Override
public void onMapReady(GoogleMap googleMap)
{
this.googleMap = googleMap;
googleMap.addMarker(new MarkerOptions()
.position(new LatLng(latitude, longitude))
.title("Bus Location")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)));
googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(latitude, longitude), 15));
}