adobe air 工程师_使用Adobe AIR构建Yahoo音乐混搭

adobe air 工程师

When Yahoo released the Yahoo Music application programming interface (API), I was immediately all over it! What could be cooler than playing with a data source containing musicians, bands, album listings, and videos? In this article, we’ll build an Adobe AIR application that takes advantage of this rich source of data.

当Yahoo发布Yahoo Music应用程序编程接口(API)时 ,我立刻就无所不用其极了! 与使用包含音乐家,乐队,专辑列表和视频的数据源进行播放相比,还有什么会比这更酷? 在本文中,我们将构建一个利用此丰富数据源的Adobe AIR应用程序。

The trick was getting hold of a list of my favorite artists. I could have used a search field, but that seemed kind of old school. Then it dawned on me that my local iTunes library contained all of the artists that I like; better yet, Adobe AIR would allow me to access that iTunes library, so I could take my web programming skills and use them to build a fun desktop app. So, I decided to create a mashup of my iTunes library and the Yahoo Music API.

诀窍在于掌握我最喜欢的艺术家的名单。 我本可以使用搜索字段,但这似乎有点老套。 然后我突然意识到我的本地iTunes库包含了我喜欢的所有艺术家。 更好的是,Adobe AIR允许我访问该iTunes库,因此我可以利用自己的Web编程技能,并使用它们来构建有趣的桌面应用程序。 因此,我决定为iTunes库和Yahoo Music API创建一个混搭。

Along the way, I learned a lot about the AIR File API and AIR’s SQLite database support, which I used to maintain a list of every Yahoo video retrieved between invocations of the app. I also learned a great deal about how to launch native sub-windows in AIR – especially managing progress bars. As you’ll soon see, these progress bars are necessary because the process of scanning iTunes and then requesting videos of each artist from Yahoo is time-consuming.

在此过程中,我了解了很多有关AIR File API和AIRSQLite数据库支持的信息,这些信息用于维护应用程序调用之间检索到的每个Yahoo视频的列表。 我还学到了很多有关如何在AIR中启动本机子窗口的知识,尤其是管理进度栏。 如您将很快看到的那样,这些进度条是必需的,因为扫描iTunes然后从Yahoo请求每个艺术家的视频的过程非常耗时。

Pay attention – there will be a quiz at the end! The first 100 people to complete the quiz will win a copy of my book, Getting Started With Flex 3, delivered to their front door for FREE, thanks to Adobe. You can also download the book in PDF format for free for a limited time.

请注意-最后会有测验 前100名完成测验的人将赢得我的书《 Flex 3入门》 ,这本书是免费的,这要归功于Adobe。 您也可以限定时间内免费下载PDF格式的图书

开设店铺 (Setting up Shop)

Let’s dig right in and I’ll walk you through how I built this application. Previous Adobe AIR tutorials here on SitePoint have made use of HTML, CSS and JavaScript. However, you can also create AIR applications using Adobe Flex – and that’s what we’ll be doing here. Download the code archive for this application (.zip, 2.2 MB) if you’d like to have all the code listings readily accessible.

让我们深入研究,我将引导您逐步了解如何构建此应用程序。 SitePoint上的以前的Adobe AIR教程都使用HTML,CSS和JavaScript。 但是,您也可以使用Adobe Flex创建AIR应用程序-这就是我们在这里要做的。 如果您想方便地访问所有代码清单,请下载此应用程序代码存档 (.zip,2.2 MB)

Our first step is to set up Adobe Flex Builder 3. You can install a trial edition at no cost, or if you prefer, you can run the examples in this article by downloading the Flex software development kit (SDK) and the Air SDK. However, I’d definitely recommend downloading the Flex Builder integrated development environment (IDE), as it makes building both Flex and AIR applications a lot easier.

我们的第一步是设置Adobe Flex Builder3。您可以免费安装试用版 ,也可以根据需要通过下载Flex软件开发工具包(SDK)Air SDK来运行本文中的示例。 但是,我绝对建议下载Flex Builder集成开发环境(IDE),因为它使构建Flex和AIR应用程序变得更加容易。

For this article, I’ll present the video timelines application in two parts. In the first part we’ll cover the iTunes reader that accesses the list of artists from the iTunes music catalog XML file. The second part will cover how to build an application that looks up the artists from Yahoo.

对于本文,我将分两部分介绍视频时间轴应用程序。 在第一部分中,我们将介绍用于从iTunes音乐目录XML文件访问艺术家列表的iTunes阅读器。 第二部分将介绍如何构建一个从Yahoo查找艺术家的应用程序。

Note: This code does not currently work on Linux systems. Although AIR runs on Linux, iTunes currently does not.

注意:该代码当前在Linux系统上不起作用。 尽管AIR在Linux上运行,但iTunes当前不运行。

访问iTunes XML数据库 (Accessing the iTunes XML Database)

Apple’s iTunes media player stores its complete list of songs in an XML file under the Documents directory on a Mac (My Documents on Windows). Retrieving this list of artists is as simple as opening the XML file and locating the right tags. Because this process can take a fair bit of time to perform, I’ve broken it down into two steps. The first part of the process involves opening the file and reading in all the artist tags from every track. In the second step, we’ll build the list of artists along with the tracks associated with each artist; this is done in small chunks with the aid of a timer.

苹果的iTunes媒体播放器将其完整的歌曲列表存储在Mac上“文档”目录(Windows上的“我的文档”)下的XML文件中。 检索艺术家列表很简单,只需打开XML文件并找到正确的标签即可。 因为执行此过程可能需要花费一些时间,所以我将其分为两个步骤。 该过程的第一部分涉及打开文件并读取每个曲目中的所有演出者标签。 在第二步中,我们将建立艺术家列表以及与每个艺术家相关的曲目。 这是借助计时器以小块完成的。

As the code below shows, all of this is carried out in the Artists Singleton object. A Singleton is an object that has only one instance in the application; you access that instance by using the static instance method. I chose to make our Artists object a Singleton, because we’ll only want to have one music library open at a time in this application. The Artists Singleton object is shown below:

如下代码所示,所有这些操作都是在Artists Singleton对象中完成的。 Singleton是在应用程序中只有一个实例的对象。 您可以使用静态instance方法访问该实例。 我选择使Artists对象成为Singleton,因为我们只希望在此应用程序中一次打开一个音乐库。 Artists单身对象如下所示:

File: Artists.as 
package com.videomashup
{
 import flash.events.Event;
 import flash.events.EventDispatcher;
 import flash.events.TimerEvent;
 import flash.filesystem.File;
 import flash.filesystem.FileMode;
 import flash.filesystem.FileStream;
 import flash.utils.ByteArray;
 import flash.utils.Timer;
 public class Artists extends EventDispatcher
 {
   private static var _artistsInstance:Artists = new Artists();
   public static function get instance() : Artists {
     return _artistsInstance;
   }
   private var _artists:Object = {};
   private var _dicts:Array = [];
   private var _dictsProcessed:uint = 0;
   private var _dictsTotal:uint = 0;
   private var _timer:Timer = null;
   private var _artistCount:uint = 0;
   public function get artists() : Array {  
     var out:Array = [];
     for( var k:String in _artists )
       out.push( k );
     return out.sort();
   }
   public function get count() : uint {
     return _artistCount;
   }
   public function get bytesLoaded() : uint {
     return _dictsProcessed;
   }
   public function get bytesTotal() : uint {
     return _dictsTotal;
   }
   public function Artists()
   {
     super();
   }
   public function startReader() : void {
     var xmlFile:File = new File( File.userDirectory.nativePath+'/Music/iTunes/iTunes Music Library.xml' );
     var bytes:ByteArray = new ByteArray();
     var fileStream:FileStream = new FileStream();
     fileStream.open( xmlFile, FileMode.READ );
     var doc:XML = XML(fileStream.readUTFBytes(fileStream.bytesAvailable));
     fileStream.close();
     for each( var dict:XML in doc..dict.(key[2]=='Artist') )
       _dicts.push( dict );
     _dictsTotal = _dicts.length;
     _timer = new Timer( 100 );
     _timer.addEventListener(TimerEvent.TIMER,onTimer);
     _timer.start();      
   }
   private function onTimer( event:Event ) : void {
     if ( _dicts.length > 0 ) {
       for( var i:int = 0; i < 50; i++ ) {
         var dict:XML = _dicts.pop() as XML;
         if ( dict == null || _dicts.length == 0 ) {
           dispatchEvent( new ArtistEvent( ArtistEvent.ITUNES_ANALYSIS_COMPLETE ) );
           return;
         }
         _dictsProcessed++;
         var art:XML = dict.string[2];
         if ( art != null ) {
           var artName:String = String( art );
           if ( _artists[ artName ] == null ) {
             _artists[ artName ] = { name:artName, count: 1 };
             _artistCount++;
           } else
             _artists[ artName ].count += 1;
         }
       }
       dispatchEvent( new ArtistEvent( ArtistEvent.ARTIST_LIST_CHANGE ) );
     }
   }
 }
}

The two primary methods used here are the startReader method and the onTimer method. The startReader method parses the iTunes XML file and extracts all of the artist tags from the XML. It then creates a timer that will handle the asynchronous processing of the tags. The callback for that timer is the onTimer method.

此处使用的两个主要方法是startReader方法和onTimer方法。 startReader方法解析iTunes XML文件并从XML中提取所有艺术家标签。 然后,它创建一个计时器,该计时器将处理标签的异步处理。 该计时器的回调是onTimer方法。

The onTimer method processes a set amount of tags, then dispatches the ARTIST_LIST_CHANGE event to notify our application that there may be some new artists that have been added to this list. This is a custom event that’s dispatched by the Artists Singleton to notify the user that the list of artists is growing and, eventually, has been processed.

onTimer方法处理一定数量的标签,然后调度ARTIST_LIST_CHANGE事件以通知我们的应用程序此列表中可能添加了一些新的艺术家。 这是一个自定义事件,由Artists Singleton调度,用于通知用户艺术家列表正在增加,并且最终已被处理。

When all the processing is complete, the method sends the ITUNES_ANALYSIS_COMPLETE message. Both of these messages are defined below:

当所有处理完成后,该方法将发送ITUNES_ANALYSIS_COMPLETE消息。 这两个消息的定义如下:

File: ArtistEvent.as  
package com.videomashup  
{  
 import flash.events.Event;  
 public class ArtistEvent extends Event  
 {  
   public static const ITUNES_ANALYSIS_COMPLETE:String = 'ITUNES_ANALYSIS_COMPLETE';  
   public static const ARTIST_LIST_CHANGE:String = 'ARTIST_LIST_CHANGE';  
   public function ArtistEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)  
   {  
     super(type, bubbles, cancelable);  
   }  
 }  
}

The MXML code for our iTunes processing application looks like this:

iTunes处理应用程序的MXML代码如下所示:

File: iTunesVideos.mxml  
<?xml version="1.0" encoding="utf-8"?>  
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="onStartup()"  
 title="iTunes Artist List">  
<mx:Style>  
WindowedApplication { padding-bottom:10; padding-left:10; padding-right:10; padding-top:10 }  
</mx:Style>  
<mx:Script>  
<![CDATA[  
import com.videomashup.ArtistEvent;  
import com.videomashup.Artists;  
private function onStartup() : void {  
 Artists.instance.addEventListener( ArtistEvent.ITUNES_ANALYSIS_COMPLETE, onUpdateComplete );  
 var ar:ProgressWindow = new ProgressWindow();  
 ar.title = 'Scanning Artists';  
 ar.open( true );  
 Artists.instance.startReader();  
}  
private function onUpdateComplete( event:ArtistEvent ) : void {  
 artistList.dataProvider = Artists.instance.artists;  
}  
]]>  
</mx:Script>  
<mx:List width="100%" height="100%" id="artistList" labelField="name">  
</mx:List>  
</mx:WindowedApplication>

As you can see, there isn’t much to it! The application starts by registering an event handler that will listen for the completion of our iTunes library analysis. That handler then assigns the list box to the list of artists that were retrieved.

如您所见,没有太多的东西! 该应用程序首先注册一个事件处理程序,该事件处理程序将侦听iTunes库分析的完成情况。 然后,该处理程序将列表框分配给检索到的艺术家列表。

A progress window created by the application tells the user how much iTunes XML processing remains to be done. The code for this window is shown below:

应用程序创建的进度窗口告诉用户要完成多少iTunes XML处理。 该窗口的代码如下所示:

File: ProgressWindow.mxml  
<?xml version="1.0" encoding="utf-8"?>  
<mx:Window xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="onStartup()"  
 styleName="main" width="300" height="70" horizontalAlign="center">  
<mx:Style>  
.main { padding-bottom:10; padding-left:10; padding-right:10; padding-top: 10; }  
</mx:Style>  
<mx:Script>  
<![CDATA[  
import com.videomashup.Artists;  
import com.videomashup.ArtistEvent;  
private function onStartup() : void {  
 prgBar.source = Artists.instance;  
 Artists.instance.addEventListener( ArtistEvent.ITUNES_ANALYSIS_COMPLETE, onFinished );  
}  
private function onFinished( event:Event ) : void {  
 close();  
}  
]]>  
</mx:Script>  
<mx:ProgressBar id="prgBar" label="Scanning %3%%" mode="polled" />  
</mx:Window>

This window launches and attaches the progress bar to the list of artists. The Artists class contains methods for bytesLoaded and bytesTotal, which are called by the progress bar automatically to obtain the current status. Then the window automatically closes when the “iTunes Analysis Complete” dialog is displayed.

该窗口启动,并将进度条附加到艺术家列表。 Artists类包含bytesLoadedbytesTotal方法,进度条会自动调用这些方法以获取当前状态。 然后,当显示“ iTunes Analysis Complete”对话框时,窗口将自动关闭。

Upon launching the application from Flex Builder, an empty main window will open, along with the progress window, as seen in Figure 1.

从Flex Builder启动应用程序后,将打开一个空的主窗口以及进度窗口,如图1所示。

Figure 1. The iTunes Scanning Progress Indicator

When all the artists have been processed, the progress window will disappear. The list of artists is updated in the main window, as shown in Figure 2.

处理完所有艺术家后,进度窗口将消失。 艺术家列表在主窗口中更新,如图2所示。

Figure 2. The iTunes Artist List

The next step is to merge the completed list of artists with the video service from Yahoo Music.

下一步是将完整的歌手列表与Yahoo Music的视频服务合并。

混搭Yahoo Music API (Mashing up the Yahoo Music API)

The first thing you need to access the user-friendly Yahoo Music API, is an API key; you can apply for one directly from the Yahoo Developer Network home page. When you have an API key, you can use it to perform one of any number of Yahoo Music API calls. For example, you can do an API search that, when given an artist name, returns a list of matching artists along with their videos. You can then store these videos in an SQLite database, so that you don’t have to make the same query from Yahoo again.

访问用户友好的Yahoo Music API的第一件事是API密钥; 您可以直接从Yahoo Developer Network主页上申请一个。 当您拥有API密钥时,可以使用它执行任意数量的Yahoo Music API调用之一。 例如,您可以进行API搜索,并在给定艺术家姓名后返回匹配艺术家及其视频的列表。 然后,您可以将这些视频存储在SQLite数据库中,这样就不必再次从Yahoo进行相同的查询。

Our Artists list object now pulls data from Yahoo and iTunes, and manages a cached database of videos. The complete code listing for this object is quite long, so I’ll only talk about the key functionality. If you’re interested in exploring any of the other methods contained in this class, be sure to download the code archive for this tutorial.

现在,我们的Artists列表对象从Yahoo iTunes中提取数据,并管理视频的缓存数据库。 该对象的完整代码清单很长,因此我仅讨论关键功能。 如果您有兴趣探索此类中包含的任何其他方法,请确保下载本教程的代码档案

The differences start in the constructor, where I build an SQLite database in a file called artists.db.

区别始于构造函数,在该构造函数中,我在名为artists.db的文件中构建了SQLite数据库。

File: Artists.as   
public function Artists()  
   {  
     super();  
     _sqlConnection = new SQLConnection();  
     var dbFile:File = File.applicationStorageDirectory.resolvePath( "artists.db" );  
     _sqlConnection.open( dbFile );  
     var artCreateStmt:SQLStatement = new SQLStatement();  
     artCreateStmt.sqlConnection = _sqlConnection;  
     artCreateStmt.text = 'CREATE TABLE IF NOT EXISTS artist ( artistName VARCHAR( 128 ), artistID VARCHAR( 32 ) )';  
     artCreateStmt.execute();  
     var vidCreateStmt:SQLStatement = new SQLStatement();  
     vidCreateStmt.sqlConnection = _sqlConnection;  
     vidCreateStmt.text = 'CREATE TABLE IF NOT EXISTS video ( artistID VARCHAR( 32 ), year INT, videoID VARCHAR( 32 ), name VARCHAR( 128 ) )';  
     vidCreateStmt.execute();  
   }  

As you can see from the code above, our artists.db database has two tables: Artist and Video. As the names suggest, the Artist table stores the name of the artists and their IDs, which are supplied by Yahoo, while the Video table stores information about the videos for each artist. This includes the artist ID, the year of the video, the video ID (required for video thumbnails), and the name of the video.

从上面的代码中可以看到,我们的artists.db数据库具有两个表:Artist和Video。 顾名思义,“艺术家”表存储由Yahoo提供的艺术家的名称及其ID,而“视频”表存储有关每个艺术家的视频的信息。 其中包括艺术家ID,视频的年份,视频ID(视频缩略图需要)和视频名称。

With this in hand, we need to upgrade our onTimer method to retrieve the artist ID from the database–if it’s known. The onTimer method also triggers the Yahoo scanning portion of the list creation, if the iTunes scanning has completed. This is done by invoking the updateArtistData method:

有了这个,我们需要升级onTimer方法以从数据库中检索艺术家ID(如果已知)。 如果iTunes扫描已完成,则onTimer方法还会触发列表创建的Yahoo扫描部分。 这是通过调用updateArtistData方法来完成的:

File: Artists.as   
private function onTimer( event:Event ) : void {  
     if ( _dicts.length > 0 ) {  
       for( var i:int = 0; i < 50; i++ ) {  
         var dict:XML = _dicts.pop() as XML;  
         if ( dict == null || _dicts.length == 0 ) {  
           dispatchEvent( new ArtistEvent( ArtistEvent.ITUNES_ANALYSIS_COMPLETE ) );  
           return;  
         }  
         _dictsProcessed++;  
         var art:XML = dict.string[2];  
         if ( art != null ) {  
           var artName:String = String( art );  
           if ( _artists[ artName ] == null ) {  
             _artists[ artName ] = { name:artName, count: 1 };  
             var fetchIdStmt:SQLStatement = new SQLStatement();  
             fetchIdStmt.sqlConnection = _sqlConnection;  
             fetchIdStmt.text = 'SELECT * FROM artist WHERE artistName=:name';  
             fetchIdStmt.parameters[':name'] = artName;  
             fetchIdStmt.execute();  
             var fetchResult:SQLResult = fetchIdStmt.getResult();  
             for each ( var row:Object in fetchResult.data ) {  
               _artists[ artName ].artistID = row.artistID;  
             }  
             _artistCount++;  
           } else  
             _artists[ artName ].count += 1;  
         }  
       }  
       dispatchEvent( new ArtistEvent( ArtistEvent.ARTIST_LIST_CHANGE ) );  
     }  
     else  
     {  
       if ( updateArtistData() == false ) {  
         _timer.stop();  
         dispatchEvent( new ArtistEvent( ArtistEvent.YAHOO_UPDATE_COMPLETE ) );  
       }  
     }  
   }  

The updateArtistData method first checks to see whether a request to Yahoo is in process. If there is a pending request, it lets this invocation go. If there is no request in process, then it looks to find the first artist for which no ArtistID is assigned. It then makes a request of Yahoo to search for that artist. Here’s what that method looks like:

首先, updateArtistData方法检查对Yahoo的请求是否正在处理中。 如果有待处理的请求,则此调用可以进行。 如果没有正在处理的请求,则它将查找未ArtistID分配ArtistID的第一位艺术家。 然后,它请求Yahoo搜索该艺术家。 该方法如下所示:

File: Artists.as   
private function updateArtistData() : Boolean {  
 if ( _searchingYahoo == false ) {  
       dispatchEvent( new ArtistEvent( ArtistEvent.STARTING_YAHOO_SEARCH ) );  
       _searchingYahoo = true;  
     }  
     if ( _artistSearch == null ) {  
       _yahooSearchTotal = 0;  
       _yahooSearchCompleted = 0;  
       // Find any artist that doens't have an AristID associated with it          
       var artist:Object = null;  
       for each ( var art:Object in artists ) {  
         if ( art.artistID == null ) {  
           if ( artist != null )  
             artist = art;  
           _yahooSearchCompleted++;  
         }  
         _yahooSearchTotal++;  
       }  
       if ( artist == null )  
         return false;  
       // Send a search request to Yahoo for that artist  
       _searchingArtist = artist.name;  
       _artistSearch = new HTTPService();  
       _artistSearch.addEventListener( ResultEvent.RESULT, onArtistResult );  
       _artistSearch.addEventListener( FaultEvent.FAULT, onArtistFault );  
       _artistSearch.url = "http://us.music.yahooapis.com/artist/v1/list/search/artist/"+escape(artist.name)+"?appid="+Constants.APPID+"&response=videos";  
       _artistSearch.resultFormat = 'e4x';  
       _artistSearch.send();  
     }  
     return true;  
   }  

Search results are sent to either onArtistResult or onArtistFault. In the case of a failure, we set the ArtistID to blank. If a result is recorded, we find the first artist listed and store that ArtistID along with the list of videos in the database.

搜索结果将发送到onArtistResultonArtistFault 。 如果失败,我们将ArtistID设置为空白。 如果记录了结果,我们将找到列出的第一位艺术家,并将该ArtistID以及视频列表存储在数据库中。

The remaining methods in this class provide information about the artist list. As you can see, their names are self-explanatory. For example, videosMinYear and videosMaxYear return the minimum and maximum year values in the database, respectively; The getVideosByYear method returns an array of the videos for any given year. I won’t list them all here; feel free to poke around the code archive – the code is well commented.

此类中的其余方法提供有关艺术家列表的信息。 如您所见,它们的名称不言而喻。 例如, videosMinYearvideosMaxYear返回数据库中的最小值和最大值。 getVideosByYear方法返回任何给定年份的视频数组。 我不会在这里列出所有内容; 随意浏览代码档案库 -代码受到了很好的注释。

Our custom event class also needs some upgrades to handle the new events that the Artists list generates. This updated code is shown here:

我们的自定义事件类还需要进行一些升级,以处理“艺术家”列表生成的新事件。 此更新的代码如下所示:

File: ArtistEvent.as    
package com.videomashup    
{    
 import flash.events.Event;    
 public class ArtistEvent extends Event    
 {    
   public static const ITUNES_ANALYSIS_COMPLETE:String = 'ITUNES_ANALYSIS_COMPLETE';    
   public static const ARTIST_LIST_CHANGE:String = 'ARTIST_LIST_CHANGE';    
   public static const ARTISTID_UPDATE:String = 'ARTISTID_UPDATE';    
   public static const YAHOO_UPDATE_COMPLETE:String = 'UPDATE_COMPLETE';    
   public static const STARTING_YAHOO_SEARCH:String = 'STARTING_YAHOO_SEARCH';    
   public function ArtistEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)    
   {    
     super(type, bubbles, cancelable);    
   }    
 }    
}

This code contains events for the artist list to start searching Yahoo, notification of the artist IDs update status, and notification that the entire update of the Artists list is complete.

此代码包含事件列表,这些事件用于开始搜索Yahoo的艺术家列表,艺术家ID更新状态的通知以及关于艺术家列表的整个更新已完成的通知。

You must also store the Yahoo API key in the Constants class, as shown here:

您还必须将Yahoo API密钥存储在Constants类中,如下所示:

File: Constants.as    
package com.videomashup    
{    
 public class Constants    
 {    
   public static const APPID:String = 'Your Yahoo APP ID';    
 }    
}

Next, we replace the placeholder string with the application ID that we receive from Yahoo. Our main interface also undergoes a few upgrades, as shown here:

接下来,将占位符字符串替换为从Yahoo收到的应用程序ID。 我们的主界面也进行了一些升级,如下所示:

File: iTunesVideos.mxml    
<?xml version="1.0" encoding="utf-8"?>    
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="onStartup()"    
 title="iTunes Video Timeline">    
<mx:Style>    
WindowedApplication { padding-bottom:10; padding-left:10; padding-right:10; padding-top:10 }    
</mx:Style>    
<mx:Script>    
<![CDATA[    
import com.videomashup.Artists;    
import com.videomashup.ArtistEvent;    
private function onStartup() : void {    
 Artists.instance.addEventListener( ArtistEvent.YAHOO_UPDATE_COMPLETE, onUpdateComplete );    
 Artists.instance.addEventListener( ArtistEvent.STARTING_YAHOO_SEARCH, onStartYahoo );    
 var ar:ProgressWindow = new ProgressWindow();    
 ar.title = 'Scanning Artists';    
 ar.open( true );    
 Artists.instance.startReader();    
}    
private function onStartYahoo( event:ArtistEvent ) : void {    
 var ar:ProgressWindow = new ProgressWindow();    
 ar.title = 'Scanning Yahoo';    
 ar.open( true );    
}    
private function onUpdateComplete( event:ArtistEvent ) : void {    
 timeline.dataProvider = Artists.instance.videosByYear;    
}    
]]>    
</mx:Script>    
<mx:List width="100%" height="100%" id="timeline" itemRenderer="YearRenderer">    
</mx:List>    
</mx:WindowedApplication>

Now we have two progress windows: one for the iTunes reader and another for Yahoo scanning. When all this processing has completed, the onUpdateComplete method sets the dataProvider of the timeline to the list of artists.

现在,我们有两个进度窗口:一个用于iTunes阅读器,另一个用于Yahoo扫描。 所有这些处理完成后, onUpdateComplete方法将时间轴的dataProvider设置为艺术家列表。

The timeline itself is custom-rendered using the YearRenderer MXML code shown below:

时间轴本身是使用YearRenderer MXML代码自定义呈现的,如下所示:

File: YearRenderer.mxml    
<?xml version="1.0" encoding="utf-8"?>    
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" height="100" creationComplete="onDataChange()" dataChange="onDataChange()"    
 horizontalScrollPolicy="off" verticalScrollPolicy="off">    
<mx:Script>    
<![CDATA[    
import mx.controls.Image;    
private function onDataChange() : void {    
 if ( data == null || initialized == false ) return;    
 videosCanvas.removeAllChildren();    
 var index:int = 0;    
 for each( var video:Object in data.videos ) {    
   var img:Image = new Image();    
   img.x = ( index++ * 70 ) + 5;    
   img.y = 5;    
   img.toolTip = video.name;    
   img.source = "http://d.yimg.com/img.music.yahoo.com/image/v1/video/"+video.videoID+"?fallback=defaultImage&size=90x90";    
   videosCanvas.addChild( img );    
 }    
}    
]]>    
</mx:Script>    
<mx:Canvas id="videosCanvas" />    
<mx:Label text="{data.year}" left="10" top="10" fontSize="38" fontWeight="bold" color="white">    
<mx:filters>    
 <mx:GlowFilter blurX="5" blurY="5" color="#cccccc" />    
</mx:filters>    
</mx:Label>    
</mx:Canvas>

This custom-rendering object creates a set of images in our video canvas. The images represent all of the videos from the year specified in the Data field for this item. The creation of the images is performed in the onDataChange method; this method takes the list of videos and creates Image objects that point to Yahoo.

这个自定义渲染对象在我们的视频画布中创建了一组图像。 图像代表该项目在“数据”字段中指定的年份中的所有视频。 图像的创建是通过onDataChange方法执行的; 此方法获取视频列表并创建指向Yahoo的Image对象。

Whew! If you’ve managed to understand all that we’ve covered here, you’re doing well. Let’s launch this application in Flex Builder; it should look something like the screenshot in Figure 3, though of course with thumbnails of much cooler music than that stored in my library.

ew! 如果您已经了解了我们在此介绍的所有内容,那么您的状况很好。 让我们在Flex Builder中启动该应用程序; 它的外观应该类似于图3中的屏幕快照,不过当然带有比存储在我的音乐库中的音乐更酷的音乐缩略图。

Figure 3. Loading videos from Yahoo

The completed video timeline – minus the progress window – is shown in Figure 4.

完整的视频时间表(减去进度窗口)如图4所示。

Figure 4. The completed video timeline

While my motivation for building this application was for educational purposes, it’s actually a cool little AIR widget that could provide the basis for a useful application. And it’s also a fun way to visualize what your favorite artists have been doing over the years.

尽管我构建此应用程序的动机是出于教育目的,但实际上它是一个很酷的AIR小部件,可以为有用的应用程序提供基础。 这也是一种可视化多年来您最喜欢的艺术家所做的有趣的方式。

摘要 (Summary)

In this tutorial, we built a fully fledged Adobe AIR mashup of our iTunes library and the Yahoo Music API.

在本教程中,我们构建了iTunes库和Yahoo Music API的完整的Adobe AIR mashup。

Dissecting this example application exposed us to several different aspects of both the Flex and AIR platforms. On the Flex side, we learned how to parse XML from the desktop and from a web service. We also saw an example of how to use a List control as a way to scroll around a custom visualization by creating a renderer.

剖析此示例应用程序使我们了解了Flex和AIR平台的几个不同方面。 在Flex方面,我们学习了如何从桌面和Web服务解析XML。 我们还看到了一个示例,该示例说明了如何使用List控件作为通过创建渲染器来滚动自定义可视化效果的方式。

And from an AIR perspective, we looked at how to read data from an XML file, as well as how to create and maintain an SQLite database. We also used the Window Flex class to create native pop-up windows that look right at home in the host operating system.

从AIR的角度来看,我们研究了如何从XML文件读取数据,以及如何创建和维护SQLite数据库。 我们还使用Window Flex类来创建本机弹出窗口,这些窗口在主机操作系统中看起来就像在家中一样。

I hope you enjoyed mashing up your iTunes library, and that you’ll use the concepts here to build your own exciting AIR applications!

希望您喜欢混搭iTunes资料库,并希望在这里使用这些概念来构建自己的令人兴奋的AIR应用程序!

测验自己! (Quiz Yourself!)

Test your understanding of this article with a short quiz, and receive a FREE PDF of my book, Getting Started With Flex 3. The first 100 people to complete the quiz will also receive a paper copy delivered to their door for FREE, thanks to Adobe Systems.

通过简短的测验 ,测试您对本文的理解,并获得我的书《 Flex 3入门》的免费PDF。 借助Adobe Systems,完成测验的前100人也将免费获得纸质副本到他们的门口。

Take the quiz!

参加测验!

翻译自: https://www.sitepoint.com/itunes-yahoo-flex-air-mashup/

adobe air 工程师

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值