模拟器中Google Maps Polyline绘制崩溃,报空指针异常求助
解决Google Maps Polyline绘制的NullPointerException崩溃问题
看了你的错误日志和代码,问题很明确:当你拖动颜色滑块(SeekBar)时,polyline对象还没被创建(也就是还没点击过绘制按钮),这时候调用polyline.setColor()就会触发空指针异常。
下面我们一步步排查并修复问题:
问题根源分析
从错误栈能看到,崩溃发生在MainActivity.java:149的polyline.setColor(Color.rgb(red,green,blue))这一行。此时polyline是null——因为只有点击btDraw按钮后,polyline才会被赋值为gMap.addPolyline()的返回值,而如果用户先拖动颜色滑块,这个对象还不存在。
另外你的代码还有个小问题:setWidth()方法里每次都会重新给seekWidth设置监听,这会导致重复绑定,可能引发不必要的逻辑重复。
修复方案
1. 先处理空指针,同时优化颜色设置逻辑
我们可以做两件事:
- 在
onProgressChanged里不仅判断polyline是否为空,还可以把颜色值同步保存到polylineOptions里,这样后续绘制新的Polyline时也能直接用上当前设置的颜色 - 给
polylineOptions初始化默认颜色,避免绘制时Polyline是默认黑色
2. 优化SeekBar宽度监听的绑定
把seekWidth的监听移到onCreate里,不要在setWidth()里重复绑定,避免重复监听触发。
修改后的完整代码
import com.google.android.gms.maps.model.Polyline; import com.google.android.gms.maps.model.PolylineOptions; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity implements OnMapReadyCallback, SeekBar.OnSeekBarChangeListener { //初始化变量 GoogleMap gMap; SeekBar seekWidth, seekBlue, seekGreen, seekRed; Button btClear, btDraw; Polyline polyline = null; List<LatLng> latLngList = new ArrayList<>(); List<Marker> markerList = new ArrayList<>(); PolylineOptions polylineOptions = null; int red = 0, green= 0, blue=0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //绑定控件 seekWidth = findViewById(R.id.seek_width); seekRed = findViewById(R.id.seek_red); seekGreen = findViewById(R.id.seek_green); seekBlue = findViewById(R.id.seek_blue); btDraw=findViewById(R.id.bt_draw); btClear=findViewById(R.id.bt_clear); //初始化SupportMapFragment SupportMapFragment supportMapFragment = (SupportMapFragment)getSupportFragmentManager() .findFragmentById(R.id.google_map); supportMapFragment.getMapAsync(this); // 把seekWidth的监听移到这里,避免重复绑定 seekWidth.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { int width = seekWidth.getProgress(); if (polyline != null) { polyline.setWidth(width); } // 同步更新polylineOptions的宽度 if(polylineOptions != null){ polylineOptions.width(width); } } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); btDraw.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //在地图上绘制Polyline if (polyline!=null) polyline.remove(); if(polylineOptions!=null){ // 确保polylineOptions带上当前设置的颜色 polylineOptions.color(Color.rgb(red, green, blue)); polyline = gMap.addPolyline(polylineOptions); // 绘制后同步宽度 polyline.setWidth(seekWidth.getProgress()); } } }); btClear.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //清空所有内容 if (polyline!=null) polyline.remove(); for(Marker marker: markerList) marker.remove(); latLngList.clear(); markerList.clear(); seekWidth.setProgress(3); seekBlue.setProgress(0); seekGreen.setProgress(0); seekRed.setProgress(0); // 重置颜色值和polylineOptions red = 0; green = 0; blue = 0; polylineOptions = null; polyline = null; } }); seekRed.setOnSeekBarChangeListener(this); seekGreen.setOnSeekBarChangeListener(this); seekBlue.setOnSeekBarChangeListener(this); } public void onMapReady(GoogleMap googleMap) { gMap= googleMap; gMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() { @Override public void onMapClick(LatLng latLng) { //创建MarkerOptions MarkerOptions markerOptions = new MarkerOptions().position(latLng); //创建Marker Marker marker = gMap.addMarker(markerOptions); //添加坐标与Marker到列表 latLngList.add(latLng); markerList.add(marker); // 初始化或更新polylineOptions,带上当前的颜色和宽度 polylineOptions = new PolylineOptions() .addAll(latLngList) .clickable(true) .color(Color.rgb(red, green, blue)) .width(seekWidth.getProgress()); } }); } @Override public void onProgressChanged(SeekBar seekBar, int i, boolean b) { switch (seekBar.getId()){ case R.id.seek_red: red = i; break; case R.id.seek_green: green = i; break; case R.id.seek_blue: blue= i; break; } // 如果polyline已存在,直接修改颜色 if(polyline !=null){ polyline.setColor(Color.rgb(red,green,blue)); } // 同步更新polylineOptions的颜色,后续绘制时生效 if(polylineOptions != null){ polylineOptions.color(Color.rgb(red, green, blue)); } } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }
关键修改点说明
- 把
seekWidth的监听移到onCreate中,避免每次调用setWidth()重复绑定 - 在
onProgressChanged中,不仅修改已存在的polyline颜色,还同步更新polylineOptions的颜色,这样后续点击绘制时会直接用当前设置的颜色 - 在
onMapClick创建polylineOptions时,直接带上当前的颜色和宽度参数 - 点击
btDraw时,确保polylineOptions带上最新的颜色 - 点击
btClear时,重置polyline、polylineOptions和颜色变量,避免残留状态
这样修改后,不管用户先拖动滑块还是先绘制Polyline,都不会再触发空指针异常了。
内容的提问来源于stack exchange,提问作者user12456799
相关产品推荐
相关产品推荐

