2015-11-08 164 views
0

我有一個以通常方式實現的Google Map,調用MapFragment的getMapAsync(),然後等待onMapReady()被調用來提供GoogleMap實例。這一切都可以正常工作,直到我添加代碼以等待onMapReady()被調用,以確保GoogleMap實例在繼續之前可用。等待onMapReady()被調用

getMapAsync()返回和onMapReady()被調用(有意義 - 否則它不需要是異步的)之間有一小段時間。儘管在我的非正式測試中,延遲時間往往不到半秒,但我想處理延遲時間可能較長的情況。

考慮到這個目標,我添加了一個簡單的等待循環來阻塞名爲「map_ready」的變量。 map_ready最初爲false,並通過onMapReady()將其設置爲true。 waitForGoogleMap()方法只是簡單地循環,定期測試變量並僅在變量變爲真時才返回。這是代碼大綱。

static boolean map_ready = false; 

    private void init_gmap_fragment(Activity a) { 
     [...] 
     MapFragment f_new = new MapFragment(); 
     [...] 
     f_new.getMapAsync(this); 
     waitForGoogleMap(); 
    } 

    synchronized private void waitForGoogleMap() { 
     while (!map_ready) { 
      Log.d(LOGTAG, "Waiting for GoogleMap..."); 
      try { 
       wait(1000); 
      } catch (Exception e) { Log.d(LOGTAG, "Exception!"); } 
     } 
    } 

    public void onMapReady(GoogleMap gmap) { 
     try { 
      this.gmap = gmap; 
      map_ready = true; 
     } 
     [...] 
    } 

如上圖所示打印出「等待GoogleMap的......」一遍又一遍的代碼 - 它看起來運行waitForGoogleMap()阻止onMapReady()從不斷被調用。如果我將waitForGoogleMap()的調用註釋掉,它運行得很好。

我在做什麼錯?


UPDATE /澄清:我覺得我現在面臨的核心問題是,我要聽預計同一個線程監聽器上發生的事件。在這種情況下,waitForGoogleMap()正在等待事件「onMapReady()called」,並且兩者都位於主線程中。

我假設像onMapReady()這樣的回調是通過創建一個工作線程來完成的,該工作線程完成必要的工作,然後調用主線程的Handler來將回調(例如onMapReady())添加到主線程的MessageQueue。另外,當我從主線程調用wait()時,主線程的looper會利用這個機會從隊列中取出另一個項目。

但顯然我錯了:-)。

底線:如何禁止,直到onMapReady()執行?


感謝, 巴里

附:以上是我的代碼的簡化版本。實現OnMapReadyCallback(以及onMapReady()回調)的contains類實際上是一個單例。該實例是使用Instance()方法創建的,並且該實例隨後通過單獨的getInstance()方法獲取。一旦這個工作正常,我會在getInstance()方法中調用waitForGoogleMap()。這種方式應用程序不會阻止,直到它絕對需要。

回答

1

我在做什麼錯?

waitForGoogleMap()是在同一線程上運行onMapReady()應該被要求,所以onMapReady()不能稱之爲直到waitForGoogleMap()回報。

擺脫waitForGoogleMap()。開始工作,需要GoogleMaponMapReady()。如果需要的話,使用一個活動巴士來獲得「嘿,地圖已經準備好了!」事件轉移到其他組件。

+0

謝謝你的回答。當然,我已經在onMapReady()中做了必要的工作 - 沒有問題。但是,想象一下onMapReady()回調在一兩分鐘內不會發生的情況。主要的UI線程將在getMapAsync()調用之後繼續,並將迅速運行到依賴於應該在onMapReady()中初始化的內容的代碼中。當發生這種情況時,我想阻塞,直到實際調用onMapReady()。雖然在主線程上調用onMapReady(),但我認爲getMapAsync()啓動的工作將位於工作線程上。那是不正確的? –

+0

@BarryHolroyd:「很快就會遇到依賴於應該在onMapReady()中初始化的東西的代碼 - 」那麼你的應用程序就會遇到基本的架構問題。 「我想阻止,直到onMapReady()被實際稱爲」 - 這將成功凍結你的UI並在大約5秒鐘內觸發一個ANR。它也會讓用戶想知道爲什麼你的應用程序是越野車。 「那是不正確的?」 - 在主應用程序線程上調用'getMapAsync()'。除非另有說明,否則非常多**,主應用程序線程會調用所有**。 – CommonsWare

+0

@BarryHolroyd:在地圖準備就緒之前,如果有些東西不允許用戶執行,請不要在'onMapReady()'內啓用這些選項。在此期間使用進度指示器等,允許用戶訪問您的應用程序的其他部分,而不需要地圖。 – CommonsWare