2012-10-10 33 views
6

Tôi sử dụng các chức năng cho canvas như drawCircle và drawPoint trong android. Điều này hoạt động tốt.Vẽ trên canvas có độ trễ - "make onDraw() làm chậm"

Nhưng vấn đề hiện tại là vẽ các mục khác nhau này với độ trễ, vì vậy nó trông giống như một hình động.

Tôi nên sử dụng loại cơ chế nào? Đã thử với async nhưng tôi không thích cách đó.

Tôi có nên sử dụng một số loại bộ hẹn giờ chỉ vẽ một khoảng thời gian hoặc có cách thông minh khác để thực hiện việc này không?

Trả lời

3

tôi sử dụng chiến lược này, đầu tiên tôi tuyên bố một Handler và Runnable như vậy:

private final Observable mObservable = new Observable(); 
    private final static int TIME_STEP_MS = 5; 
    private final Handler mHandler = new Handler(); 
    private final Runnable mTimeManager = new Runnable() 
    { 
     public void run() 
     { 
      mObservable.notifyObservers(TIME_STEP_MS); 
      mHandler.postDelayed(mTimeManager, TIME_STEP_MS); 
     } 
    }; 

Sau đó, khi tôi muốn bắt đầu quản lý thời gian của tôi, tôi chỉ cần gọi mTimeManager.run() và nó sẽ bắt đầu thông báo cho tôi Observer s (được thêm trước) định kỳ.

Nếu bạn cần cho một số lý do ngừng đồng hồ đếm hoặc một cái gì đó bạn chỉ cần làm điều đó:

mHandler.removeCallbacks(mTimeManager); 

[EDIT - hoàn More code]

Ok hơn chúng ta hãy làm cho nó rõ ràng hơn, đầu tiên tôi làm một đối tượng tùy chỉnh có thể quan sát được như vậy [tùy chọn]:

private final Observable mObservable = new Observable() 
    { 
     public void notifyObservers() 
     { 
      setChanged(); 
      super.notifyObservers(); 
     }; 

     @Override 
     public void notifyObservers(Object data) 
     { 
      setChanged(); 
      super.notifyObservers(data); 
     }; 
    }; 

lý do là vì tôi không thể gọi setChan ged() bên ngoài lớp quan sát được - nó được bảo vệ, nếu nó không thay đổi, nó không thông báo cho bất kỳ người quan sát nào.

Các khai báo khác giữ nguyên như trước, bây giờ tôi cần bắt đầu TimeManager ở đâu đó, ứng dụng của tôi là LiveWallpaper và tôi làm mọi thứ hiển thị thành lớp mở rộng Thread nhưng bạn không nhất thiết phải tôi đã thực hiện một phương pháp gọi là resumeDrawing(), chương trình này được gọi là ngay sau khi super.start(); tại @Override của tôi về public synchronized void start() từ Thread lớp, phương pháp này trông như thế:

public void resumeDrawing() 
    { 
     if (!mTimeManagerRunning) // just a boolean field in my class 
     { 
      System.err.println("Resuming renderer."); // just for debug 
      mTimeManager.run(); 
      mTimeManagerRunning = true; 
     } 
     else 
     { 
      System.err.println("Renderer already running."); // just for debug 
     } 
    } 

và nó kép:

public void pauseDrawing() 
    { 
     if (mTimeManagerRunning) 
     { 
      System.err.println("Pausing renderer."); 
      mHandler.removeCallbacks(mTimeManager); 
      mTimeManagerRunning = false; 
     } 
     else 
     { 
      System.err.println("Renderer already paused."); 
     } 
    } 

Ok, bây giờ chúng ta có thể bắt đầu và ngừng quản lý thời gian, nhưng ai đang lắng nghe? Không ai!vì vậy hãy add'em: Trên constructor của Renderer tôi thêm một số Observer s đến đối tượng mObservable của tôi, một trong những là Renderer bản thân, vì vậy renderer của tôi kéo dài Thread và thực hiện Observer:

@Override // from Observer interface 
    public void update(Observable arg0, Object arg1) 
    { 
     mElapsedMsRedraw += (Integer) arg1; 

     if (mElapsedMsRedraw >= mDrawingMsPerFrame) 
     { 
      mElapsedMsRedraw = 0; 
      drawEm(); // refresh the canvas and stuff 
     } 
    } 

để thêm các nhà quan sát bạn chỉ cần làm mObservable.addObserver(THE_OBJECT - Implements Observer)

bạn có thể thấy rằng tôi không hiển thị lại nội dung của mình mỗi khi tôi được thông báo, đó là vì tôi sử dụng TimeManager này cho các suy nghĩ khác ngoài việc làm mới Canvas như cập nhật vị trí của đối tượng tôi muốn để vẽ chỉ trong nội bộ. Vì vậy, những gì bạn cần để làm chậm bản vẽ là thay đổi cách đối tượng của bạn thay đổi nội bộ trong khi thời gian trôi qua, tôi có nghĩa là vòng tròn và điểm của bạn, hoặc bạn có thể cơ hội bước thời gian của bạn, tôi khuyên bạn nên đầu tiên.

Có rõ ràng hơn không? Tôi hy vọng nó sẽ giúp.

+0

thx, nhưng bạn có thể đăng một ví dụ hoàn chỉnh hơn không? Đang hiển thị việc triển khai. – FooBar

+0

Chắc chắn, tôi đang làm việc bây giờ đó là đoạn mã tôi có thể nhớ. Tôi sẽ rời đi trong 20 phút để ASAP tôi sẽ cung cấp cho bạn một mã hoàn chỉnh hơn. – HericDenis

+0

Ok @FooBar bây giờ tôi về nhà, tôi sẽ giúp bạn (: – HericDenis

1

Tôi sẽ sử dụng bộ hẹn giờ hoặc tạo Hoạt ảnh. Bạn có thể tạo Ảnh động sẽ thực hiện tất cả mọi thứ bao gồm thay đổi độ trong suốt theo thời gian.

Đây là Android Documentation Tài Animation

0

tôi tin rằng có thể có những cách tinh vi để làm điều này, nhưng đối với nhu cầu của tôi tôi đã sử dụng một phương pháp đơn giản mà có rất nhiều ưu điểm: đầu tiên tôi tạo hồ sơ tọa độ (và bất kỳ dữ liệu khác cần thiết) cho mỗi điểm của bản vẽ - thay vì vẽ các điểm ngay tại chỗ - và sau đó tạo lại chúng bằng bộ hẹn giờ (trình xử lý Android, tốt nhất là). Điều này cũng cung cấp rất nhiều khả năng trong khi vẽ thực tế: tạm dừng, đi nhanh hơn/chậm hơn, lùi lại, ... Tôi không biết liệu phương pháp này có thể được sử dụng cho các bản vẽ phức tạp hay không, nhưng việc vẽ hình dạng, đường cong là tốt bề mặt, v.v.

Các vấn đề liên quan