Android Studio方法执行顺序问题致应用崩溃求助
问题解答:AsyncTask/线程无法解决你的崩溃问题,核心要调整异步流程
你的崩溃根源有两个:
fetchLastLocation(含权限请求、定位获取)是异步操作,但你在onCreate里同时触发了地图初始化getMapAsync,导致地图回调onMapReady先执行时,currentLocation还未赋值,直接调用getLatitude()引发空指针。- 未开启设备定位时,
getLastKnownLocation返回null,onMapReady里没有空判断就直接调用定位方法,导致崩溃。
AsyncTask或线程完全没必要,也解决不了问题——因为问题本质是异步任务的执行顺序依赖,不是线程执行效率的问题。下面是直接有效的修复方案:
关键修复步骤
1. 让地图初始化依赖定位准备完成
移除onCreate中直接调用的getMapAsync,只在成功获取到定位(或确认定位权限、GPS状态后)再初始化地图:
修改onCreate方法:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); client = LocationServices.getFusedLocationProviderClient(this); LManager = (LocationManager) getSystemService(LOCATION_SERVICE); // 先不初始化地图,等待定位准备就绪 fetchLastLocation(); }
新增单独的地图初始化方法,并修改fetchLastLocation:
private void fetchLastLocation() { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_CODE); CheckGps(); return; } // 先确认GPS状态 CheckGps(); Task<Location> task = client.getLastLocation(); task.addOnSuccessListener(new OnSuccessListener<Location>() { @Override public void onSuccess(Location location) { if (location != null) { currentLocation = location; initMap(); // 拿到有效定位后初始化地图 } else { // 尝试获取最后已知位置 currentLocation = getLastKnownLocation(); if(currentLocation != null){ initMap(); } else { Toast.makeText(MainActivity.this, "无法获取定位,请检查GPS是否开启", Toast.LENGTH_LONG).show(); } } } }); } // 单独的地图初始化方法 private void initMap(){ suppMapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.maps); suppMapFragment.getMapAsync(this); }
2. 在onMapReady中强制做空安全判断
即使定位逻辑出现意外,也要避免空指针崩溃:
@Override public void onMapReady(@NonNull GoogleMap googleMap) { this.mMap = googleMap; googleMap.getUiSettings().setMyLocationButtonEnabled(true); // 权限判断修正:之前的逻辑写反了,应该是有权限时才开启我的位置 if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { googleMap.setMyLocationEnabled(true); } // 空安全判断:没有定位时直接返回并提示 if(currentLocation == null){ Toast.makeText(this, "定位未就绪,请稍后重试", Toast.LENGTH_SHORT).show(); return; } LatLng latLng = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude()); MarkerOptions markerOptions = new MarkerOptions().position(latLng).title("你在这里!"); googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 12)); googleMap.addMarker(markerOptions); }
3. 优化权限回调后的逻辑
确保用户授予权限后,重新触发定位获取和地图初始化:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case REQUEST_CODE: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { fetchLastLocation(); // 权限授予后重新获取定位,自动触发地图初始化 } else { Toast.makeText(this, "需要定位权限才能显示你的位置", Toast.LENGTH_SHORT).show(); } break; } }
为什么AsyncTask/线程没用?
fetchLastLocation本身就是基于Google Play Services的异步任务,用线程或AsyncTask包裹它,只是多了一层线程切换,无法改变“地图初始化和定位获取并行执行”的问题。只有让地图初始化的触发依赖定位任务的完成回调,才能从根本上避免时序问题导致的崩溃。
内容的提问来源于stack exchange,提问作者user21605117
相关产品推荐
相关产品推荐

