2016-03-08 94 views
-1

我遇到了问题GoogleMap,因为它使用MapView#getMapAsync异步获取地图。获取谷歌地图异步,空指针

我遇到NullPointerException,因为#getMapAsync没有及时返回,当我的Activity将标记传递给GoogleMap对象时。

这可以做到同步或有更好的解决方案吗?它添加到片段包不会为我工作的活动可能在#commit()

GoogleMapsFragment

public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     // inflate and return the layout 
     View v = inflater.inflate(R.layout.fragment_google_map, container, 
       false); 

     ButterKnife.bind(this, v); 

     mMapView.onCreate(savedInstanceState); 

     mMapView.onResume();// needed to get the map to display immediately 

     try { 
      MapsInitializer.initialize(getActivity().getApplicationContext()); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

     Bundle bundle = getArguments(); 
     if(bundle != null){ 
      initialMarkers = bundle.getParcelableArrayList("markers"); 
     } 

     mMapView.getMapAsync(new OnMapReadyCallback() { 
      @Override 
      public void onMapReady(GoogleMap googleMap) { 

       mGoogleMap = googleMap; 

       if (mCameraPos != null) { 
        mGoogleMap.moveCamera(CameraUpdateFactory.newCameraPosition(mCameraPos)); 
        mCameraPos = null; 
       } else { 
        //Set default camera position over the United States. 
        CameraPosition cameraPosition = new CameraPosition.Builder() 
          .target(new LatLng(37.09024, -95.712891)).zoom(3).build(); 
        mGoogleMap.moveCamera(CameraUpdateFactory 
          .newCameraPosition(cameraPosition)); 

       } 

      } 
     }); 

     return v; 
    } 

活动

@OnClick(R.id.loadListOrMapButton) 
    public void onClickChangeView() { 

     FragmentManager fragmentManager = getSupportFragmentManager(); 
     FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 

     if (mLocationListViewFrag.isVisible()) { 
      if (mGoogleMapFrag == null) { 
       mGoogleMapFrag = new GoogleMapFragment(); 
       fragmentTransaction.add(R.id.fragment_container, mGoogleMapFrag);     
      } 

      bListMapButton.setText(getString(R.string.list)); 
      fragmentTransaction.hide(mLocationListViewFrag).show(mGoogleMapFrag); 

     } else { 
      bListMapButton.setText(getString(R.string.map)); 
      fragmentTransaction.hide(mGoogleMapFrag).show(mLocationListViewFrag); 
     } 

     fragmentTransaction.commit(); 
     fragmentManager.executePendingTransactions(); 
     updateDisplay(); 
    } 

UpdateDisplay

public void updateDisplay() { 
    if (mLocationListViewFrag != null && mLocationListViewFrag.isVisible()) { 
     Log.d(TAG, "Update Tax Location ListView"); 
     mLocationListViewFrag.setLocations(mLocations); 
    } else if (mGoogleMapFrag != null && mGoogleMapFrag.isVisible()) { 
     Log.d(TAG, "Update Google Maps Markers"); 
     //Convert locations to markers to display. 
     mGoogleMapFrag.clearMarkers(); 
     for (LocationObj aLocation : mLocations) { 

      mGoogleMapFrag.addMarker(new MarkerOptions().position(
        new LatLng(Double.valueOf(aLocation.getLat()), Double.valueOf(aLocation.getLng()))).title(aLocation.getName())); 
      mGoogleMapFrag.fitBounds(); 
     } 
    } 
} 
+0

我们需要看到你的代码...... –

+0

@Xoce添加代码 – Alan

回答

1

后通过片段标记您应该移动处理市场的代码rs应在OnMapReadyCallbackhttps://developers.google.com/android/reference/com/google/android/gms/maps/OnMapReadyCallback)之内,并将其传递给#getMapAsync(OnMapReadyCallback callback)。这将确保在地图可用之前不放置标记。

编辑,了解更多信息

最终你必须要解决的问题,“我该怎么办,如果有人让#onClickChangeView时得到的地图是不是做好准备叫什么名字?”从用户体验的角度来看,loadListOrMapButton甚至不应该显示,直到地图加载完成。您应该在默认情况下禁用该按钮,然后在您的OnMapReadyCallback中提供此按钮。你可以灰掉按钮(例如谷歌的“android禁用按钮”),或者你可以用View#setVisibility来隐藏/显示它。

非推荐的方法

虽然我犹豫建议它,你可以而不是只检查GoogleMap准备:从内您的OnMapReadyCallback设置一个布尔值,你的外部活动可以检查。喜欢的东西

private boolean mapIsReady = false;  

mMapView.getMapAsync(new OnMapReadyCallback() { 
     @Override 
     public void onMapReady(GoogleMap googleMap) { 
      // your normal code here 

      mapIsReady = true; 
     } 
    }); 

public boolean mapIsReady() { 
    return mapIsReady; 
} 

然后在活动

@OnClick(R.id.loadListOrMapButton) 
public void onClickChangeView() { 
    // check for null and all that jazz 

    if (mapsFragment.mapIsReady()) { 
      // updateDisplay and everything 
    } else { 
     // make a toast or something asking them to try later. 
    } 
} 
+0

hmm ..但Activity可以在回调之前的任何时候通过'GoogleMapFragment'。如果您想查看,我添加了上面的代码。 – Alan

+0

@Alan查看更新 –

+0

接受,如果正确 –

0

XML

<com.google.android.gms.maps.MapView 
     android:id="@+id/mapview" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:apiKey="@string/google_app_id" 
     android:clickable="true"> 
    </com.google.android.gms.maps.MapView> 

MainActivity.java

public class MainActivity extends AppCompatActivity implements OnMapReadyCallback { 
    LatLng sydney = new LatLng(33.8650, 151.2094); 
    MapView mapView; 
    GoogleMap map; 

     @Override 
     protected void onCreate(Bundle bundle) { 
      super.onCreate(bundle); 
      setContentView(R.layout.activity_main); 
      mapView = (MapView) findViewById(R.id.mapview); 
      mapView.getMapAsync(this); 
      MapsInitializer.initialize(this); /* initialize method should  be called when we are not sure that map will be loaded before using it. It initialises the map.*/ 

     mapView.onCreate(null); 
     mapView.onResume(); 
    } 
    @Override 
    public void onMapReady(GoogleMap googleMap) { 
     map = googleMap; 
     map.addMarker(new MarkerOptions().position(sydney).draggable(true)); 
    } 
} 
+0

我必须使用mapfragment来保存'MapView',因为我正在显示和隐藏片段。 – Alan

+0

不,您可以使用MapFragment或MapView。不是都。 –

+0

MapView像一个视图,而MapFragment充当一个片段。没有什么比您需要MapFragment来保存MapView。两者都用于显示地图。您可以使用任何布局(如LinearLayout,RelativeLayout等)来保存MapView或MapFragment。 –