陣列範例:PlayList

Flash Player 9 以及更新的版本,Adobe AIR 1.0 以及更新的版本

PlayList 範例會在管理歌曲清單的音樂播放清單應用程式中,示範使用陣列的技巧。這些技巧包括:

  • 建立索引陣列

  • 新增項目至索引陣列

  • 使用不同的排序選項,依照不同的屬性排序物件陣列

  • 將陣列轉換為以字元分隔的字串

若要取得此樣本的應用程式檔案,請參閱 www.adobe.com/go/learn_programmingAS3samples_flash_tw。您可以在 Samples/PlayList 檔案夾中找到 PlayList 應用程式檔案,此應用程式是由下列檔案組成:

檔案

說明

PlayList.mxml

PlayList.fla

主應用程式檔案,在 Flash 中為 FLA,在 Flex 中為 MXML。

com/example/programmingas3/playlist/PlayList.as

代表歌曲清單的類別,使用 Array 來儲存清單,並管理清單項目的排序。

com/example/programmingas3/playlist/Song.as

代表單一歌曲資訊的值物件。由 PlayList 類別所管理的項目都是 Song 實體。

com/example/programmingas3/playlist/SortProperty.as

虛擬列舉項目可供使用的值代表 Song 類別的屬性,而 Song 物件清單就是依此屬性加以排序。

PlayList 類別概觀

PlayList 類別會管理一組 Song 物件。它所具備的公用方法,能夠將歌曲新增至播放清單 (addSong() 方法),並為清單中的歌曲排序 (sortList() 方法)。另外,此類別還包含唯讀的存取子屬性 songList,可以提供對播放清單中該組實際歌曲的存取。在 PlayList 類別內部,則會使用私有 Array 變數來追蹤歌曲:

public class PlayList 
{ 
    private var _songs:Array; 
    private var _currentSort:SortProperty = null; 
    private var _needToSort:Boolean = false; 
    ... 
}

除了由 PlayList 類別用來追蹤歌曲清單的 _songs Array 變數之外,其它兩個私有變數則會追蹤清單是否需要排序 (_needToSort),以及在指定時間要以何種屬性為歌曲清單排序 (_currentSort)。

如同所有物件一樣,宣告 Array 實體只能算完成 Array 建立工作的一半而已。存取 Array 實體的屬性或方法之前,必須先加以實體化,而這是由 PlayList 類別的建構函式來進行。

    public function PlayList() 
    { 
        this._songs = new Array(); 
        // Set the initial sorting. 
        this.sortList(SortProperty.TITLE); 
    }

建構函式的第一行會將 _songs 變數實體化,以供稍後使用。除此之外,並呼叫 sortList() 方法來設定初始的排序方式屬性。

在播放清單中新增歌曲

當使用者輸入新的歌曲至應用程式時,資料項目表格中的程式碼會呼叫 PlayList 類別的 addSong() 方法。

    /** 
     * Adds a song to the playlist. 
     */ 
    public function addSong(song:Song):void 
    { 
        this._songs.push(song); 
        this._needToSort = true; 
    }

addSong() 中,會呼叫 _songs 陣列的 push() 方法,以加入傳遞至 addSong() 的 Song 物件,做為該陣列中的新元素。不管之前是否曾經套用任何排序,藉由 push() 方法,便可以將此新元素加入至陣列結尾。這表示在呼叫 push() 方法之後,歌曲清單的排序可能不再正確,因此將 _needToSort 變數設定為 true。理論上來說,您可以立即呼叫 sortList() 方法,無須追蹤清單在特定時間是否已排序。然而實際上,只有在即將擷取歌曲之前,才需要排序歌曲清單。應用程式可以藉由延遲排序作業,避免執行不必要的排序動作,並在擷取歌曲清單前,才為新加入清單的歌曲進行排序。

排序歌曲清單

由於播放清單所管理的 Song 實體是相當複雜的物件,因此應用程式的使用者可能會希望根據不同的屬性為播放清單排序,例如歌曲名稱或出版年份等。在 PlayList 應用程式中,歌曲清單的排序工作可分為三個部分:識別清單應該以何種屬性排序、指出依照該屬性排序時需要使用哪些排序選項,以及執行實際的排序作業。

用於排序的屬性

Song 物件會追蹤數個屬性,包括歌曲名稱、作者、出版年份、檔案名稱、以及使用者所選取的歌曲類型。其中只有前三個項目才適用於排序。為方便開發人員使用,此範例包含 SortProperty 類別,此類別可做為列舉項目,而它的值則代表可用來進行排序的屬性。

    public static const TITLE:SortProperty = new SortProperty("title"); 
    public static const ARTIST:SortProperty = new SortProperty("artist"); 
    public static const YEAR:SortProperty = new SortProperty("year");

SortProperty 類別包含 TITLEARTISTYEAR 常數,每個常數都會儲存一個 String (內含相關聯之 Song 類別屬性的實際名稱,可用於排序)。在程式碼的其它部分,每當指定排序屬性時,就會使用列舉項目的成員來進行。例如,在 PlayList 建構函式中,最初是藉由呼叫 sortList() 方法為清單排序,如下所示:

        // Set the initial sorting. 
        this.sortList(SortProperty.TITLE);

由於用於排序的屬性已指定為 SortProperty.TITLE,因此歌曲會依照其標題加以排序。

依照屬性排序並指定排序選項

歌曲清單實際的排序工作是由 PlayList 類別在 sortList() 方法中執行,如下所示:

    /** 
     * Sorts the list of songs according to the specified property. 
     */ 
    public function sortList(sortProperty:SortProperty):void 
    { 
        ... 
        var sortOptions:uint; 
        switch (sortProperty) 
        { 
            case SortProperty.TITLE: 
                sortOptions = Array.CASEINSENSITIVE; 
                break; 
            case SortProperty.ARTIST: 
                sortOptions = Array.CASEINSENSITIVE; 
                break; 
            case SortProperty.YEAR: 
                sortOptions = Array.NUMERIC; 
                break; 
        } 
         
        // Perform the actual sorting of the data. 
        this._songs.sortOn(sortProperty.propertyName, sortOptions); 
             
        // Save the current sort property. 
        this._currentSort = sortProperty; 
 
        // Record that the list is sorted. 
        this._needToSort = false; 
    }

依標題或藝人排序時,可以按照字母順序排序,但是依年份排序時,以數值排序是最合邏輯的方式。switch 陳述式可依據 sortProperty 參數所指定的值,用來定義適當的排序選項,而此排序選項則是儲存於變數 sortOptions 中。這裡又再次使用命名的列舉項目成員,而非硬式編碼值來區別屬性。

排序屬性和排序選項決定好之後,_songs 陣列就會藉由呼叫其 sortOn() 方法實際進行排序,並將這兩個值傳遞為參數。目前的排序屬性會記錄下來,以證明歌曲清單已完成排序。

將陣列元素合併成以字元分隔的字串

除了使用陣列來維護 PlayList 類別中的歌曲清單外,此範例中陣列也會用於 Song 類別,以協助管理特定歌曲所屬的類型清單。請考慮以下來自 Song 類別定義的程式碼片段:

private var _genres:String; 
 
public function Song(title:String, artist:String, year:uint, filename:String, genres:Array) 
{ 
    ... 
    // Genres are passed in as an array 
    // but stored as a semicolon-separated string. 
    this._genres = genres.join(";"); 
}

在建立新的 Song 實體時,用來指定歌曲所屬類型的 genres 參數會定義為 Array 實體。這樣可以方便將多個類型分組成可傳遞至建構函式的單一變數。然而在內部,Song 類別會將這些類型保留於私有 _genres 變數中,做為以分號區隔的 String 實體。Array 參數會藉由呼叫其 join() 方法,並以常值字串值 ";" 做為指定的分隔符號,以便轉換為以分號區隔的字串。

藉由相同的字符,genres 存取子允許將類型設定或擷取為 Array:

    public function get genres():Array 
    { 
        // Genres are stored as a semicolon-separated String, 
        // so they need to be transformed into an Array to pass them back out. 
        return this._genres.split(";"); 
    } 
    public function set genres(value:Array):void 
    { 
        // Genres are passed in as an array, 
        // but stored as a semicolon-separated string. 
        this._genres = value.join(";"); 
    }

genresset 存取子的表現方式和建構函式相同,它會採用 Array,並呼叫 join() 方法,將 Array 轉換為以分號區隔的 String。get 存取子則執行反向作業:呼叫 _genres 變數的 split() 方法,使用指定的分隔符號 (即之前的常值字串值 ";"),將 String 分割為值陣列。