Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 開發入門 >> Android初級之重構程序

Android初級之重構程序

編輯:開發入門

偉大的創意少之又少,多數時候只是一些小改進。小的改進也是好的。 
什麼是重構 
可以運作的程序跟可以維護的程序之間,還有一道難以言說的鴻溝。

一個程序設計之初,是用來解決特定問題。就像在前面章節的學習中,我們也已經寫好了一個可以運作的 BMI 程序。但是對程序設計來說,當我們寫越多程序,我們會希望可以從這些程序之中,找到一個更廣泛適用的法則,讓每個程序都清晰易讀,從而變得更好修改與維護。

讓程序清晰易讀有什麼好處呢?當一段程序被寫出來,之後我們所要做的事,就是修改它與維護它。一旦程序越長越復雜,溷亂到無法維護的境界時,就只好砍掉重練。 所以若我們能透過某些方式,例如重新組織或部分改寫程序碼,好讓程序容易維護,那麽我們就可以為自己省下許多時間,以從容迎接新的挑戰。

我們回過頭來看看前面所寫的 Android 程序。android 平台的開發者已經先依照 MVC 模式,為我們將顯示界面所用的 XML 描述檔、顯示資源所用的 XML 描述檔從程序碼中區隔開來。將與程序流程無關的部份分開來組織,讓程序流程更清楚,相對易於維護。

而在主要程序碼(Bmi.Java) 方面,雖然程序碼量很少,還算好讀,但整體上並不那麽令人滿意。例如,假使我們要在這段程序碼中再多加上按鍵、適用於多種螢幕顯示模式、或是再加入選單等等內容,很快地程序碼就開始變得復雜,變得不容易閱讀,也開始越來越不容易維護。

因此,在繼續新的主題之前,我們先來重構這個 BMI 應用程序。在重構的過程中,也許我們能學到的東西,比學任何新主題還重要呢 。

MVC 
我們打算重構 BMI 程序的部份 java 程序碼。既然我們已經照著 android 平台的作法,套用 MVC 模式在我們的程序組織上,那麽,我們不妨也試著套用同樣的 MVC 模式在 Bmi.Java 程序碼上。 
如何套用 MVC 模式到 Bmi.Java 程序碼上呢? 
原來的程序片段是這樣的 
代碼 : 
1  @Override

2  public void onCreate(Bundle icicle) {

3      super.onCreate(icicle);

4      setContentVIEw(R.layout.main);

5           

6      //Listen for button clicks

7      Button button = (Button) findVIEwById(R.id.submit);

8      button.setOnClickListener(calcBMI);

9  }

 

上面的程序片段中,包含了所有 android 程序共用的標准內容, 整個程序的大致架構在前面章節中已經講解過,現在我們從中取出我們感興趣的部分來討論:

代碼: 
Button button = (Button) findVIEwById(R.id.submit);

button.setOnClickListener(calcBMI);

在第7 行我們看到一段程序碼來宣告按鈕物件,與針對該按鈕物件作動作的程序碼。 button.setOnClickListener 程序碼的意義是指定一個函式,來負責處理" 按下" 這個" 按鈕" 後的動作。

我們可以想像,在同一個畫面中,多加入一些按鈕與欄位後,"onCreate" 這段程序將變得臃腫,我們來試著先對此稍作修改:

首先,我們可以套用 MVC 模式,將宣告界面元件( 按鈕、數字欄位) 、指定負責函式等動作抽取出來,將 onCreate 函式改寫如下

代碼: 
@Override

public void onCreate(Bundle icicle) {

super.onCreate(icicle);

setContentVIEw(R.layout.main);

findVIEws();

setListensers();

}

接著我們將宣告界面元件的部份寫成一個獨立的"findVIEws" 函式:

private Button calcbutton;

private EditText fIEldheight;

private EditText fIEldweight;

 

private void findVIEws()

{

calcbutton = (Button) findVIEwById(R.id.submit);

fieldheight = (EditText) findVIEwById(R.id.height);

fieldweight = (EditText) findVIEwById(R.id.weight);

}

順便將原本很沒個性的按鈕識別參數"button" 改名成"calcbutton" ,以後在程序中一看到"calcbutton" ,就知道是一個按下後將開始處理計算工作的按鈕。

同樣地,我們也將指定特定動作( 按按鈕) 的負責函式獨立出來:

代碼: 
//Listen for button clicks

private void setListensers() {

calcbutton.setOnClickListener(calcBMI);

}

 

如此一來,我們就將程序邏輯與界面元件的宣告分離開來,達成我們重構的目的。

 

完整程序如下:

代碼: 
package com.demo.android.bmi;

import Java.text.DecimalFormat;

import android.app.Activity;

import android.os.Bundle;

import android.view.VIEw;

import android.widget.Button;

import android.widget.EditText;

import android.widget.TextVIEw;

 

public class Bmi extends Activity {

/** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle icicle) {

        super.onCreate(icicle);

         setContentVIEw(R.layout.main);

         findVIEws();

        setListensers();

    }

 

private Button button_calc;

private EditText fIEld_height;

private EditText fIEld_weight;

private TextView vIEw_result;

private TextView vIEw_suggest;

 

private void findVIEws()

{

        button_calc = (Button) findVIEwById(R.id.submit);

        field_height = (EditText) findVIEwById(R.id.height);

        field_weight = (EditText) findVIEwById(R.id.weight);

        view_result = (TextView) findVIEwById(R.id.result);

        view_suggest = (TextView) findVIEwById(R.id.suggest);

}

//Listen for button clicks

    private void setListensers() {

        button_calc.setOnClickListener(calcBMI);

}

private Button.OnClickListener calcBMI = new Button.OnClickListener()

{

        public void onClick(VIEw v)

        {

            DecimalFormat nf = new DecimalFormat("0.0");

            double height = Double.parseDouble(fIEld_height.getText().toString())/100;

            double weight = Double.parseDouble(fIEld_weight.getText().toString());

            double BMI = weight / (height * height);

           

            //Present result

            vIEw_result.setText(getText(R.string.bmi_result) + nf.format(BMI));


            //Give health advice

            if(BMI>25){

                vIEw_suggest.setText(R.string.advice_heavy);

            }else if(BMI<20){

                vIEw_suggest.setText(R.string.advice_light);

            }else{

                vIEw_suggest.setText(R.string.advice_average);

            }

        }

};

}

同樣是"calcBMI" 函式,在完整程序中,改將"calcBMI" 函式從原本的"OnClickListener" 宣告成 "Button.OnClickListener" 。這個改變有什麼差別呢?

   閱讀原本的程序碼,在匯入(import) 的部分可以看到,"OnClickListener" 是來自於"android.view.VIEw.OnClickListener" 函式:

代碼: 
    import android.view.VIEw.OnClickListener;

改成"Button.OnClickListener" 後,"Button.OnClickListener" 就變成來自 於"android.widget.Button" 中的"OnClickListener" 函式,在查閱程序時,整個"Button" 與"OnClickListener" 之間的關係變得更清晰。

另外,我們偷偷將"OnClickListener" 中其他會存取到的界面元件識別參數,也補進 findVIEws 宣告中:

代碼: 
private void findVIEws()

{

button_calc = (Button) findVIEwById(R.id.submit);

    field_height = (EditText) findVIEwById(R.id.height);

    field_weight = (EditText) findVIEwById(R.id.weight);

    view_result = (TextView) findVIEwById(R.id.result);

    view_suggest = (TextView) findVIEwById(R.id.suggest);

}

 

同時,我們也把識別參數的命名方法做了統一:按鈕的識別參數前加上 "button_" 前綴,可輸入欄位的識別參數前加上"field_" 前綴,用作顯示的識別參數前則加上"vIEw_" 前綴。將變數名稱的命名方法統一有 什麼好處呢?好處在於以後不管是在命名新變數,或是閱讀程序碼時,都能以更快速度命名或理解變數的意義,讓程序變得更好讀。

我們也把原本在程序中直接寫進的字串

代碼: 
TextView result = (TextView) findVIEwById(R.id.result);
result.setText("Your BMI is "+nf.format(BMI));

 

改寫成

代碼: 
//Present result

vIEw_result.setText(getText(R.string.bmi_result) + nf.format(BMI));

並將"TextView view_result" 宣告改放到 findVIEws 中一次處理好。

現在,整個程序流程是不是清爽了許多呢?

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved