如何在Google地图中更新标记?

时间:2018-11-09 10:21:01

标签: android google-maps nullpointerexception

在下面的代码中,我可以在地图上创建标记。每当我尝试使用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代码,它会因上面的错误而崩溃。

4 个答案:

答案 0 :(得分:2)

getMapAsync异步初始化Map。 因此,当您第一次在Runnable中调用googleMap.addMarker()时,它会崩溃,因为Map尚未初始化,并且googleMap为null。 解决此问题的最简单方法是将periodicUpdate.run();移至onMapReady()回调 另外,您也不要忘记在onPause()

中清除Runnable

答案 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));

}