2011-11-30 61 views
0

因此,我一直在研究一個應用程序,該應用程序具有包含多個不同輸入和輸出的Plan模型,並且該應用程序的佈局具有用於輸入和標籤的滑塊控件輸出。當輸入發生變化時,它會更新模型,然後運行計算,然後更新視圖。起初我並不認爲這個架構有什麼問題,但即使是簡單的計算似乎也運行得非常慢,阻塞了UI線程。當然,我也有更新的東西有點複雜的方式:使用SeekBar更新Android佈局中的計算值

  1. 滑塊(在一個ViewGroup子類)更新它的價值和將消息發送到一個委託(它實現特定於該子類的ViewGroup接口)。
  2. 委託(包含模型和控制子視圖)告訴Plan實例設置一個新值,這會觸發計劃重新計算其輸出。
  3. 計劃完成計算後,它會向代理髮送另一條消息,然後告知其輸出視圖以使用新值進行更新。

我已經將此架構建模爲我開發的iOS應用程序,這似乎並沒有像運行計算時那樣大的問題。

現在,我知道Android與iOS顯着不同,所以我想知道我是否會完全錯誤。有沒有辦法告訴這些視圖觀看計劃模型的變化,然後獲取它應該顯示的值?

我在這裏看到的另一個主要問題是滑塊輸入。如果我將模型更新計算放入一個線程中,則每次滑塊更改時都會創建一個新線程。這些線程(正如我所看到的)或多或少都會按隨機順序完成,當您應該看到增量更改時,以這種方式更新視圖的方式也沒什麼意義。是否有一種線程計算的好方法可以通過seekbar進行修改?

+0

爲了真正瞭解是什麼導致了性能問題,我建議在Eclipse中使用DDMS中的分配跟蹤器:http://developer.android.com/guide/developing/debugging/ddms.html。關於我的頭頂,聽起來像你需要使用具有遊戲循環的SurfaceView來更新視圖。 – Vigrond

回答

1

你看過ObserverObservable? 也許您的觀察模型可以使用Runnable執行更新,然後通知觀察者。

+0

這看起來確實是對我的委託模式的改進,但我不確定它是否可以解決使用滑塊實時更新模型的問題。問題是移動滑塊時會發生或多或少的連續變化,因此將計算代碼推入線程會產生任意數量的新線程,這些新線程將以幾乎隨機的順序或多或少地進行更新。可觀察的+1,但性能問題在滑塊上似乎仍然存在問題。更新了問題以強調滑塊問題。 –

+1

因爲我從來沒有見過甚至更新UI線程中的值的問題,您是否嘗試過檢查需要多長時間計劃重新計算其值?有了這個架構,這將是您更新UI所需的最短時間(最佳案例)。 之後,唯一想到儘可能接近實時地更新UI的其他事情是在另一個線程上使用隊列,這樣您就不會產生新線程,並且更新會按順序進行。即使在這種情況下,它永遠不會比上面花更少的時間。 – gianpi

+0

爲了這個項目的目的,你是對的,除非我實現某種排隊產卵/剔除算法,這種情況不會因爲更新方法的執行時間而改善。 Observer/observable絕對是對代表設計的一種改進。事實證明,我的更新方法中有一個函數調用會導致巨大的性能損失,從而減慢UI響應速度,並且移除所有內容都可以順利移動,所以我只是要重新修改我的更新方法,希望所有人都會平滑過來。 –

0

這只是我的頭頂部的一個想法:

而不是剛剛開始從滑塊每次更新一個新的線程,你可以實現某種Queue

您需要一個運行Thread的程序,該程序包含Queue

public class QueueThread extends Thread { 
    private boolean running; 
    private ArrayDeque<Runnable> queue; 
    private Thread current; 

    public QueueThread() { 
    running = true; 
    queue = new ArrayDeque<Runnable>(); 
    current = new Thread(); 
    } 

    @Override 
    public void run() { 
    while(running) { 
     if(!queue.isEmpty() && !current.isAlive()) { //We only want to start a new thread if there is one or more in the queue AND the old task is not runnning. 
     current = new Thread(queue.pollFirst()); 
     current.start(); 
     } 
     else 
     try { 
      Thread.sleep(200); //We need a sleep in order to not hammer the CPU. 
     } 
     catch(InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
    } 

    public void stopThread() { 
    running = false; 
    } 

    public void add(Runnable task) { 
    queue.addLast(task); //Here is where we add a task to the queue. The slider (or whoever posts the updates) must have a reference to this thread object. 
    } 
} 

這樣做會允許每次更新在下一次啓動前完成。我不確定它的表現如何。我沒有測試過它或任何東西。這只是一個想法。