Android app設計須知

1、一些概念

模式的定義:

每個模式都描述了一個在我們的環境中不斷出現的問題,然後描述了該問題的解決方案的核心。通過這種方式,你可以無數次地使用那些已有的解決方案,無需在重複相同的工作。

什麼是設計模式?

設計模式是在某種特別的情況下,針對某種問題的某種典型、通用的解決方法。

我們是需要適當瞭解並學習一些設計模式,在程序開發過程中,總是會涉及到一些框架設計,模塊設計之類的東西,如果能很好理解並運行設計模式,你所設計的模塊或框架將會要穩定得多,因爲這些設計模式它們都是通用的解決方案,是經過實踐經驗了的。

比如說,在程序裏,可能會有通知模塊,A模塊的數據發生變化,B模塊需要得到通知,對於這樣的需要,你可能會想到用"廣播","消息"或者"回調"的方式來解決,的確,剛纔我所說的那三種也能解決,但是,這三種都是存在一些缺點,比如說廣播,用Intent來傳輸數據很困難,對於"消息",無法很好的跟蹤,對於"回調",有可能你A與B模塊根本不可相互訪問。此時,如果你會用觀察者模式的問題,這種問題可以很輕鬆解決。

當然,這裏是需要具體問題具體分析的,我主要的意思就是說,要適當利用模式,我們不能爲了用模式而去用模式,我們是要用模式來解決我們實際的問題。

概念完整性

關於概念完整性,在《人月神話》一書在有大量的闡述,這裏,我把我的理解寫出來,與大家分享。

1)概念完整性是系統設計中最重要的考慮因素。當你的系統規模越大,這一點體現得越明顯。

2)爲了獲取概念的完整性,設計必須由一個人或者具有共識的小型團隊來完成。這一點很好理解,關於設計,可以讓所有的人蔘與,但是決定權在少數人手裏,如果大家都想參與設計,這是根本沒有辦法保證系統設計是統一完整的。

3)要獲得概念上的完整性,就必須有人控制這些概念,類似於貴族的專制統治。這裏,對於團隊中的項目經理或架構師必須對項目有絕對的權威,不然,這個項目裏面的就無法統一號令。

4)概念完整性表現有:

    - 開發過程中,需求、設計、編碼的一致性
    - 整個程序具有統一的風格,比如對話框樣式,按鈕風格,色調等UI元素
    - 整個程序具體統一的結構,比如不同模塊訪問網絡,它們的調用方式一致,例如異步訪問都用回調方式通知結果,相同的功能應該提取成共通模塊。
    - 開發人員能很好的執行需求人員和設計人員的意圖。
    - 有完整的文檔,需求文檔,設計文檔,測試文檔,處理流程的文檔等。

如何保持概念完整性

    - 在制度上給予保證,產品的負責人必須建立技術上的絕對權威
    - 技術負責人員(SE,SL)必須嚴格執行項目的需求,設計,必須深入到編碼細節
    - 在不同階段,保持與所有人員的持續溝通,鼓勵開發人員提意見。
    - 讓開發人員參與設計,但不決定設計
    - 通過持續的反饋和溝通來實現模塊重用

2、設計之前應該做什麼

2.1 共通類的設計

2.1.1 Widget設計

  • TextView
  • EditText
  • Button
  • Title bar
  • Tool bar
  • ...

      爲什麼要提供這些共通控件?

  • 統一字體大小,如App字體不隨系統字體變化而變化
  • 統一UI式樣,如Button, EditText具有相同的背景等
  • 複用代碼

2.1.2 Adapter Items

  • 根據式樣,提取需要在AdapterView中顯示的Item
  • 簡單的複合佈局
  • 自繪製,從而提高滑動性能
    - ListView中放Gallery時,提高上下滑動性能
    - 儘量優化繪製

       數據驅動

  • Adapter Items提供核心的方法
    - setData(Object data)
    - getData();
  • Adapter#getView實現更加簡單
    - 實現簡單
    - 不會因爲UI變化而變化

下面代碼示例了Adapter#getView()方法的實現,它返回BookView,BookView提供方法來接收數據,至於BookView的顯示,則根據設置的數據來顯示,這就是數據驅動UI。

  1. @Override  
  2. public View getView(int position, View convertView, ViewGroup parent) {  
  3.   
  4.     if (null == convertView) {  
  5.         convertView = new BookView(getContext());  
  6.         convertView.setLayoutParameter(new AbsListView.LayoutParameter(150150));  
  7.     }  
  8.   
  9.     Book book = m_bookList.get(position);  
  10.     BookView bookView = (BookView)convertView;  
  11.     bookView.setBook(book);  
  12.   
  13.     return convertView;  
  14. }  

2.1.3 Dialog

  • 擴展於Dialog類
  • 提供Dialog關閉的事件
  • Dialog的高度隨內容的變化而變化
  • 可以設置按鈕的文字,可見性,字體等方法
  • 設置按鈕點擊事件的listener
  • 要考慮對話框的三個屬性:Title, Content area, Action buttons

2.1.4 Utility

  • Log
  • DateFormat
  • Bitmap
  • Notification
  • Shared Preference
  • Environment
  • Device
  • ...

2.2 Task管理

線程只是一種機制,保證我們要完成的任務不運行在UI線程(也就是說不阻塞UI),完成的任務纔是我們關注的核心,因此,我們可以通過設計,把線程封裝,讓使用者根本感覺不到是線程,他只用關心他要做的事情就行了。
這裏,我們可以設計一種"異步鏈式調用"的框架,把線程進行了封裝。使用都只需要這樣用: 

  1. new TaskManager()  
  2. .next(task1)  
  3. .next(task2)  
  4. .next(task3).  
  5. .execute();  

這裏,task1, task2, task3是順序執行的,舉個例子:我們要訪問網絡,取得一個圖片,使用這個TaskManager我們需要3個task,

task1:顯示一個ProgressDialog。

task2:訪問網絡,創建bitmap。

task3:關閉對話框,顯示bitmap。

這一點,可以參考CoreLib工程中的task.TaskManager類。

關於TaskManager,有以下幾點需要注意:

  • 封裝了線程
  • 讓調用者只關注自己的業務處理
  • 保證順序鏈式地執行某一個任務
  • 上一個任務的輸出,作爲下一個任務的輸入
  • 能暫停、恢復任何一個任務 

2.3 緩存設計

  • 把內存佔用量大的對象存放在緩存中,如bitmap
  • 利用了LruCache類來實現
  • 利用了AsyncTask類來加載bitmap
  • 不用再手動釋放bitmap內存,該操作有風險
  • 不用再關心AbsListView的scroll狀態

關於緩存的更多詳細細節,請參考[ 請參考CoreLib工程中的cache包 ]。

這樣做,有什麼好處, 不用再手動釋放bitmap內在,該操作有風險,因爲該bitmap是否有View引用,如果當一個View在試圖繪製一個已經回收的bitmap,這裏會拋出異常。

2.4 線程管理

無消息循環的線程:

  1. new Thread(nullnew Runnable() {  
  2.     public void run() {  
  3.         // Do you works.  
  4.     }  
  5.   
  6. }, "Thread_name_xxx").start();  

什麼情況下使用這種線程:

  • 做完一件事情就結束,這件事發生頻率不高,比如從SD card中讀取圖片數據
  • 不需要複用線程

在使用線程,最好給線程加上名字,這樣利用高度與跟蹤。

  有消息循環的線程:

這樣的線程擁有消息循環,當消息隊列中沒有消息時,這個線程會被掛起。我們要做一件事情時,只需要給它發送一個消息就行了。

這種情況通常是爲了複用線程,不用頻繁創建線程,比如音樂播放器程序,專門啓動一個有消息循環的線程來獲得音樂的專輯圖片。

我們通常還要創建一個與這個線程的消息循環(Looper)相關聯的Handler,由它來處理消息,注意,這做的事情是運行在後臺線程的。

3,程序框架如何設計

Android程序的結構

  • UI層
    • 數據展示與管理
    • 用戶交互
    • 繪製
    • Adapter
  • 業務邏輯層
    • 持久化數據(內存中,相當於全局數據)
    • 數據加式(數據層的數據有時候需要進行加工成UI層需要的數據)
    • 數據變化的通知機制
  • 數據層
    • 數據訪問(DB,文件,網絡等)
    • 緩存(圖片,文件等)
    • 配置文件(shared perference)

下面,我試着畫了一個Android程序的結構,如果有不好的地方,歡迎指正。


    

4,一些基本原則

下面列出一些通常的原則,我們應當在開發過程中遵循,歡迎補充與指正。 

4.1 提供initialize()方法

在Activity.onCreate()或者View的構造方法中調用,在以後看代碼時,人們通常首先會去找initialize()這樣的方法。

4.2 封裝點擊事件

把View的點擊事件,提成方法,這樣在listener處只是一個方法調用者,一般的事件封裝爲:onXXXClick(View v)。

4.3 設計一個BaseActivity類

讓所有的Activity都繼承自BaseActivity類,這樣,我們可以做很多有用的事情

  • 定義共通屬性
  • 顯示共通對話框(Progress dialog)
  • 取得top activity
  • 可以手動管理啓動的activity

4.4 設計Application類

  • 存全局數據,比top activity, application context。

4.5 異常處理

  • 報告功能是處理異常的精髓
  • 在finally塊中執行清理操作
  • 不要用try-catch-finally來判斷業務邏輯
  • 考慮設計自定義的異常類

4.6 標註的使用

  • 重寫的方法一定要加@Override
  • 不使用的方法,不要刪除,可以標記爲@Deprecated,這個做法在維護型的項目中特別有用。

4.7 註冊與反註冊

  • 局部廣播
  • 各種listener
  • Service等

4.8 封裝Bitmap操作

我們應當把Bitmap操作封裝起來,比如從文件加載,保存,網絡下載,動態計算sample size等。有了封裝後,我們可以對其集中優化。

4.9 繪製處理

一定要注意繪製方面的東西,不要在onDraw()/onTouchEvent()中創建新對象。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章