首先MapFragment下载诊所的数据(名称,描述,地图上的坐标等),然后尝试为其添加标记。当片段尝试尝试时,应用程序会抛出一个异常,即该行不在主线程中。
E/AndroidRuntime: FATAL EXCEPTION: Thread-12
Process: com.happs.medrate, PID: 4332
com.google.maps.api.android.lib6.common.apiexception.c: Not on the main thread
at com.google.maps.api.android.lib6.common.m.b(:com.google.android.gms.dynamite_mapsdynamite@19831046@19.8.31 (040306-0):22)
at com.google.maps.api.android.lib6.common.r.a(:com.google.android.gms.dynamite_mapsdynamite@19831046@19.8.31 (040306-0):5)
at com.google.maps.api.android.lib6.impl.bm.a(:com.google.android.gms.dynamite_mapsdynamite@19831046@19.8.31 (040306-0):60)
at com.google.android.gms.maps.internal.j.a(:com.google.android.gms.dynamite_mapsdynamite@19831046@19.8.31 (040306-0):308)
at ck.onTransact(:com.google.android.gms.dynamite_mapsdynamite@19831046@19.8.31 (040306-0):5)
at android.os.Binder.transact(Binder.java:612)
at com.google.android.gms.internal.maps.zza.zza(Unknown Source:10)
at com.google.android.gms.maps.internal.zzg.addMarker(Unknown Source:54)
at com.google.android.gms.maps.GoogleMap.addMarker(Unknown Source:48)
at com.happs.medrate.view.main.MapFragment.onResult(MapFragment.java:87)
at com.happs.medrate.view.main.MapFragment.lambda$zKz5SBiVflok9pIuOSBON5AS6Uk(Unknown Source:0)
at com.happs.medrate.view.main.-$$Lambda$MapFragment$zKz5SBiVflok9pIuOSBON5AS6Uk.onResult(Unknown Source:4)
at com.happs.medrate.model.clinicsdata.GetClinicsData$GetDataThread.run(GetClinicsData.java:61)
有代码(仅方法):
//onResult is for GetClinicsData class (it is a Thread class)
private void onResult(Clinic clinic, @Nullable Exception e){
this.clinic = new Clinic(clinic.getName(), clinic.getAddress(), clinic.getDescription(), clinic.getGeoPoint());
MarkerOptions markerOptions = new MarkerOptions();
LatLng coordinates = new LatLng(clinic.getGeoPoint().getLatitude(), clinic.getGeoPoint().getLongitude());
markerOptions.position(coordinates);
map.addMarker(markerOptions);
}
@Override
public void onMapReady(GoogleMap googleMap) {
map = googleMap;
if (ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION)) {
} else {
// No explanation needed; request the permission
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
}
} else {
map.setMyLocationEnabled(true);
MyLocationListener.setUpLocationListener(getContext(), getActivity());
}
}
我已经尝试过在onMapReady中创建“添加标记”部分,但是该片段首先使用onMapReady方法准备了地图,然后才下载诊所的数据,因此当尝试添加标记时,它会抛出“ NullPointerException”,因为它尚未获得诊所的数据。我不知道该怎么办...
答案 0 :(得分:1)
听起来像ds.Absolute_vorticity_isobaric.metpy.time.values
是在完成一些异步工作之后被调用的,并且这项工作是在除main / ui线程之外的某些线程上完成的。标记只能添加到主线程上的映射中,因此您需要找到一种在适当的线程上执行代码的方法。
如果您可以控制ds.Absolute_vorticity_isobaric.metpy.vertical.values
的调用者,那可能是切换线程的最佳位置:
onResult()
如果不这样做,则可以在onResult()
内部进行线程切换:
getActivity().runOnUiThread(this::onResult);
如果出于某种原因不想使用onResult()
,则可以使用private void onResult(Clinic clinic, @Nullable Exception e){
this.clinic = new Clinic(clinic.getName(), clinic.getAddress(), clinic.getDescription(), clinic.getGeoPoint());
MarkerOptions markerOptions = new MarkerOptions();
LatLng coordinates = new LatLng(clinic.getGeoPoint().getLatitude(), clinic.getGeoPoint().getLongitude());
markerOptions.position(coordinates);
getActivity().runOnUiThread(() -> {
map.addMarker(markerOptions);
});
}
获得相同的结果:
runOnUiThread()
答案 1 :(得分:0)
onResult()
的{{1}}方法内的代码在后台线程上执行,然后在该方法内调用
MainFragment
这行代码应从main / UI线程执行,但会在后台线程上执行,这就是您的应用抛出异常的原因。
解决方案1:在主线程上的map.addMarker(markerOptions);
方法内执行代码。
onResult()
解决方案2:仅在主线程上执行代码行// This handler used to send an executable block of code to main thread.
private Handler mainHandler = new Handler(Looper.getMainLooper());
private void onResult(final Clinic clinic, @Nullable Exception e) {
mainHandler.post(new Runnable() {
@Override
public void run() {
// These lines of code will be executed on main thread.
MapFragment.this.clinic = new Clinic(clinic.getName(), clinic.getAddress(), clinic.getDescription(), clinic.getGeoPoint());
MarkerOptions markerOptions = new MarkerOptions();
LatLng coordinates = new LatLng(clinic.getGeoPoint().getLatitude(), clinic.getGeoPoint().getLongitude());
markerOptions.position(coordinates);
map.addMarker(markerOptions);
}
});
}
。
map.addMarker(markerOptions)
答案 2 :(得分:0)
使用runOnUiThread
runOnUiThread(new Runnable() {
@Override
public void run() {
MapView mMapView = (MapView) dialog.findViewById(R.id.mapView);
MapsInitializer.initialize(context);
mMapView.onCreate(dialog.onSaveInstanceState());
mMapView.onResume();
mMapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(final GoogleMap googleMap) {
LatLng myLocation=new LatLng(Double.parseDouble(lat), Double.parseDouble(lon));
googleMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
googleMap.addMarker(new MarkerOptions().position(myLocation).title("My location").icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)));
float zoomLevel = (float) 16.0; //This goes up to 21
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(myLocation, zoomLevel));
googleMap.getUiSettings().setZoomControlsEnabled(true);
}
});
}
});