2013-02-07 53 views
0

在我的Android應用程序中,我需要知道MapView縮放過程何時完成。沒有內置的解決方案,所以我有想法重寫dispatchDraw。Android:併發確實表現順序

只要Map縮放(以及在Map上滾動,但這並不重要),就會調用dispatchDraw,我的想法是不斷檢查dispatchDraw是否通過覆蓋名爲dispatchDrawInvoked的變量來調用。當第一次調用MapView上的縮放時(這意味着縮放過程開始時),我開始一個新的線程,該線程每秒連續設置dispatchDrawInvoked爲false。這個想法是,dispatchDraw方法在這秒鐘內用很多次覆蓋dispatchDrawInvoked,當第二個結束並且dispatchDraw仍然爲true時,這意味着縮放還沒有完成。在大多數情況下,縮放完成,並且dispatchDraw在循環第二次運行後保持爲假,因此最少需要2秒。當循環識別出縮放過程完成時,我將縮放變量設置爲true以向信號發送(對於需要知道的上級類別)縮放已完成。

到目前爲止這麼好。問題是,這整個實現不表現併發。它的行爲是順序的,MapView卡住了2秒鐘。爲什麼是這樣,請看我的代碼:

public class ZoomListeningMapView extends MapView { 
    private final static String TAG = ZoomListeningMapView.class.getSimpleName(); 

    private final static int DEFAULT_ZOOM_LEVEL = 14; 
    private int lastZoomLevel = DEFAULT_ZOOM_LEVEL; 
    private volatile boolean zooming = false; 
    private volatile boolean dispatchDrawInvoked = false; 

    public ZoomListeningMapView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public ZoomListeningMapView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 

    public ZoomListeningMapView(Context context, String apiKey) { 
     super(context, apiKey); 
    } 

    public boolean isZooming() { 
     return zooming; 
    } 

    public static int getDefaultZoomLevel() { 
     return DEFAULT_ZOOM_LEVEL; 
    } 

    @Override 
    protected void dispatchDraw(Canvas canvas) { 
     super.dispatchDraw(canvas); 

     dispatchDrawInvoked = true; 

     Log.i(TAG, "setting dispatchDrawInvoked to true"); 
     Log.i(TAG, "zooming:" + zooming); 

     if (getZoomLevel() != lastZoomLevel) { 
      lastZoomLevel = getZoomLevel(); 

      Log.i(TAG, "zoom level changed"); 

      zooming = true; 

      Log.i(TAG, "zooming:" + zooming); 

      new Thread(new ZoomRunnable()).start(); 
     } 
    } 

    private class ZoomRunnable implements Runnable { 

     private final String TAG = ZoomRunnable.class.getSimpleName(); 

     @Override 
     public void run() { 
      try { 
       while (zooming) { 
        dispatchDrawInvoked = false; 

        Log.i(TAG, "setting dispatchDrawInvoked to false"); 

        Thread.sleep(1000); 

        if (dispatchDrawInvoked == false) { 
         zooming = false; 

         Log.i(TAG, "dispatchDrawInvoked is still false, so Map zooming is finished."); 
        } 
       } 
      } 
      catch (InterruptedException e) { 
       Log.e(TAG, "InterruptedException: " + e.getMessage()); 

       return; 
      } 
     } 
    } 
} 

這是總是相同的日誌。這表明,沒有併發問題:

Log

回答

4

一個Runnable不負責創建和線程執行的照顧,它只是提供了開始當一個線程將執行run()方法。所以你只是同步調用run()方法。您需要實際使用將啓動另一個線程的內容。

new Thread(new MapThread()).start()

會照顧你打算什麼,但是因爲它實際上只是一個可運行的,你應該重新命名MapThread,我建議熟悉HandlersHandlerThreads如果你打算上發佈了大量可運行的和不想爲每一個人製作一個線索。

+0

謝謝,這個工程(在我不得不對run方法做一些修改之後)。我將MapThread更名爲ZoomRunnable。 – Bevor