2016-03-08 62 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。 –