我有一個以通常方式實現的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()。這種方式應用程序不會阻止,直到它絕對需要。
謝謝你的回答。當然,我已經在onMapReady()中做了必要的工作 - 沒有問題。但是,想象一下onMapReady()回調在一兩分鐘內不會發生的情況。主要的UI線程將在getMapAsync()調用之後繼續,並將迅速運行到依賴於應該在onMapReady()中初始化的內容的代碼中。當發生這種情況時,我想阻塞,直到實際調用onMapReady()。雖然在主線程上調用onMapReady(),但我認爲getMapAsync()啓動的工作將位於工作線程上。那是不正確的? –
@BarryHolroyd:「很快就會遇到依賴於應該在onMapReady()中初始化的東西的代碼 - 」那麼你的應用程序就會遇到基本的架構問題。 「我想阻止,直到onMapReady()被實際稱爲」 - 這將成功凍結你的UI並在大約5秒鐘內觸發一個ANR。它也會讓用戶想知道爲什麼你的應用程序是越野車。 「那是不正確的?」 - 在主應用程序線程上調用'getMapAsync()'。除非另有說明,否則非常多**,主應用程序線程會調用所有**。 – CommonsWare
@BarryHolroyd:在地圖準備就緒之前,如果有些東西不允許用戶執行,請不要在'onMapReady()'內啓用這些選項。在此期間使用進度指示器等,允許用戶訪問您的應用程序的其他部分,而不需要地圖。 – CommonsWare