数组示例:播放列表

Flash Player 9 和更高版本,Adobe AIR 1.0 和更高版本

此 PlayList 示例在管理歌曲列表的音乐播放列表应用程序环境中展示了使用数组的多种技巧。这些方法包括:

  • 创建索引数组

  • 向索引数组中添加项

  • 使用不同的排序选项按照不同的属性对对象数组排序

  • 将数组转换为以字符分隔的字符串

若要获取此范例的应用程序文件,请参阅 www.adobe.com/go/learn_programmingAS3samples_flash_cn。可以在 Samples/PlayList 文件夹中找到 PlayList 应用程序文件。该应用程序包含以下文件:

文件

说明

PlayList.mxml

PlayList.fla

Flash 或 Flex 中的主应用程序文件(分别为 FLA 和 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() 方法,而无需跟踪是否要在给定时间对列表进行排序。实际上,不需要立即对歌曲列表排序,除非要对其进行检索。通过延迟排序操作,应用程序不会执行不必要的排序,例如,在将几首歌曲添加到列表中且不需要立即对其进行检索时。

对歌曲列表排序

由于由 PlayList 管理的 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 三个常量,其中的每个常量都存储一个字符串,该字符串中包含可用于排序的相关 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 变量中。这里,再次使用命名的枚举成员而非硬编码值来区分不同属性。

确定排序属性和排序选项之后,将通过调用 sortOn() 方法并将上述两个值作为参数传递来完成对 _songs 数组的排序。对歌曲列表进行排序之后,记录当前排序属性。

将数组元素组合为以字符分隔的字符串

在本示例中,数组除了用于在 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 实例形式来保存流派。通过调用 join() 方法(使用文本字符串值 ";" 作为指定分隔符),Array 参数将转换为以分号分隔的字符串。

通过使用相同的标记,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() 方法以将其转换为以分号分隔的 String。get 存取器执行相反的操作:调用 _genres 变量的 split() 方法,使用指定分隔符(采用与前面相同的文本字符串值 ";")将 String 拆分为值数组。