好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

音乐播放器

音乐播放器

最近在做一个音乐播放器,纯粹练手,前端使用FLex,后台使用JAVA,现在慢慢的在实现,主要涉及的技术还在不断学习中:
这里也一点一点记录下来和大家分享哈。

自定义组件 :(左边是一个播放列表,右边是音乐播放控件)
自定义组件要继承 SkinnableComponent 类。主要有两部分组成,一个是组件的功能逻辑,一个是皮肤。
功能逻辑和普通的as写法一样,要用到皮肤就需要遵守皮肤的契约.看看下面的代码:
( 音乐播放控件:PlayerControlBar.as ):

   1   package components
    2   {
    3       import   events.PlayEvent;
    4       import   events.StopEvent;
    5      
   6       import   flash.events.Event;
    7       import   flash.media.Sound;
    8       import   flash.media.SoundChannel;
    9       import   flash.net.URLRequest;
   10      
  11       import   mx.controls.Alert;
   12       import   mx.controls.HSlider;
   13       import   mx.controls.sliderClasses.Slider;
   14       import   mx.events.SliderEvent;
   15       import   mx.messaging.AbstractConsumer;
   16      
  17       import   service.IPlayController;
   18       import   service.impl.PlayController;
   19      
  20       import   spark.components.Button;
   21       import   spark.components.TextArea;
   22       import   spark.components.supportClasses.SkinnableComponent;
   23      
  24      [SkinState( "stop"  )]
   25      [SkinState( "run"  )]
   26       /*  *播放控制栏组件  */ 
  27       public   class  PlayerControlBar  extends   SkinnableComponent
   28       {
   29          [SkinPart(required= "true"  )]
   30           public   var   lyricText:TextArea;
   31          [SkinPart(required= "true"  )]
   32           public   var   playSlider:HSlider;
   33          [SkinPart(required= "true"  )]
   34           public   var   preButton:Button;
   35          [SkinPart(required= "true"  )]
   36           public   var   stateButton:Button;
   37          [SkinPart(required= "true"  )]
   38           public   var   nextButton:Button;
   39          [SkinPart(required= "true"  )]
   40           public   var   stopButton:Button;
   41          
  42           public   function   PlayerControlBar()
   43           {
   44               super  ();
   45               //  添加播放状态更改的监听器 
  46               this  .addEventListener(PlayEvent.PLAY, handleStateButtonClick);
   47               this  .addEventListener(StopEvent.STOP, handleStopButtonClick);
   48               this  .addEventListener(SliderEvent.CHANGE, handlePlaySilderChange);
   49           }
   50          
  51           /*  *是否在播放  */ 
  52           public   var  isStart: Boolean  =  false  ;
   53           /*  *音乐播放控制器  */ 
  54           private   var   playController:IPlayController;
   55           /*  *播放状态改变的处理函数  */ 
  56           private   function  handleStateButtonClick(event:PlayEvent): void 
  57           {
   58               if (! isStart)
   59               {
   60                   //  加载音乐并开始播放 
  61                  playController =  new  PlayController( this  );
   62                  playController.start( "gole.mp3"  );
   63                  isStart =  true  ;
   64                   //  改变皮肤的状态 
  65                   this .skin.currentState= "stop"  ;
   66               }
   67               else   if ( this .skin.currentState ==  "stop"  )
   68               {
   69                   //  暂停播放音乐 
  70                   playController.pause();
   71                   this .skin.currentState= "run"  ;
   72               }
   73               else   if ( this .skin.currentState ==  "run"  )
   74               {
   75                   //  开始音乐播放 
  76                   playController.play();
   77                   this .skin.currentState= "stop"  ;
   78               }
   79           }
   80          
  81           private   function  handleStopButtonClick(e:StopEvent): void 
  82           {
   83              isStart =  false  ;
   84               this .skin.currentState =  "run"  ;
   85               if  (playController)
   86                  playController.stop( true  );
   87           }
   88          
  89           //  活动条拉动的触发函数,从指定位置开始播放 
  90           private   function  handlePlaySilderChange(e:SliderEvent): void 
  91           {
   92               if  (isStart)
   93               {
   94                   (playController as PlayController).clickPlay();
   95                   if ( this .skin.currentState ==  "run"  )
   96                       this .skin.currentState =  "stop"  ;
   97               }
   98           }
   99       }
  100  }

看到24~25行为自定义组件加了两个SkinState标注,这个是皮肤的状态,
第29~40行为几个组件加了[SkinPart(required="true")]标注,这个是皮肤必须要拥有的控件
皮肤的契约如下图:

利用flex builder的功能可以为自定义组件添加皮肤,它会根据皮肤的契约自动生成提示:
如下:
( 音乐播放控件的皮肤:PlayerControlBarSkin.mxml ):

  1   <?  xml version="1.0" encoding="utf-8"  ?> 
  2   <  s:Skin   xmlns:fx  ="http://ns.adobe.com/mxml/2009"  
  3           xmlns:s  ="library://ns.adobe.com/flex/spark"  
  4           xmlns:mx  ="library://ns.adobe.com/flex/mx" 
  5           creationComplete  ="this.currentState = 'run'" 
  6           > 
  7       <!--   host component   --> 
  8       <  fx:Metadata  > 
  9           [HostComponent("components.PlayerControlBar")]
  10       </  fx:Metadata  > 
 11       <  fx:Script  > 
 12           <![CDATA[ 
 13               import events.PlayEvent;
  14               import events.StopEvent;
  15              
 16               import mx.events.SliderEvent;
  17           ]]> 
 18       </  fx:Script  > 
 19      
 20       <!--   states   --> 
 21       <  s:states  > 
 22           <  s:State   id  ="runState"   name  ="run"  /> 
 23           <  s:State   id  ="stopState"   name  ="stop"   /> 
 24       </  s:states  > 
 25      
 26       <!--   SkinParts
  27       name=lyricText, type=spark.components.TextArea, required=true
  28       name=stateButton, type=spark.components.Button, required=true
  29       name=nextButton, type=spark.components.Button, required=true
  30       name=preButton, type=spark.components.Button, required=true
  31       name=stopButton, type=spark.components.Button, required=true
  32       --> 
 33      
 34       <  s:Group   width  ="700"   height  ="600"  > 
 35           <  s:Image   source  ="asserts/img/background.jpg"   alpha  =".6"  /> 
 36          
 37           <  s:VGroup   width  ="100%"   height  ="100%"   horizontalAlign  ="center"   paddingTop  ="20"  > 
 38               <  s:Group   width  ="60%"   height  ="80%"   horizontalCenter  ="0"  > 
 39                   <  s:TextArea   id  ="lyricText"   width  ="100%"   height  ="100%"   alpha  =".8"   borderVisible  ="false"  > 
 40                   </  s:TextArea  > 
 41               </  s:Group  > 
 42               <  s:HGroup   width  ="55%"   verticalAlign  ="middle"  > 
 43                   <  mx:HSlider   id  ="playSlider"   width  ="100%"   height  ="100%"   minimum  ="0"   maximum  ="100" 
 44                               change  ="dispatchEvent(new SliderEvent(SliderEvent.CHANGE,true))"  /> 
 45               </  s:HGroup  > 
 46               <  s:HGroup   width  ="60%"   horizontalAlign  ="center"   paddingBottom  ="10"  > 
 47                   <  s:Button   id  ="preButton"   skinClass  ="skins.PreButtonSkin"  /> 
 48                   <  s:Button   left  ="15"   id  ="stateButton"   skinClass.run  ="skins.PlayButtonSkin"   skinClass.stop  ="skins.PauseButtonSkin"   click  ="dispatchEvent(new PlayEvent(PlayEvent.PLAY))"  /> 
 49                   <  s:Button   left  ="15"   id  ="nextButton"   skinClass  ="skins.NextButtonSkin"  /> 
 50                   <  s:Button   left  ="15"   id  ="stopButton"   skinClass  ="skins.StopButtonSkin"   click  ="dispatchEvent(new StopEvent(StopEvent.STOP))"  /> 
 51               </  s:HGroup  > 
 52           </  s:VGroup  > 
 53       </  s:Group  > 
 54   </  s:Skin  > 

自定义组件的好处是将逻辑内部封装好,安全也便于维护,通过皮肤改变外观也是很方便的,需要对外的服务只要提供接口就可以了。

在主界面使用自定义组件:

 1   <  s:HGroup   horizontalAlign  ="center"   verticalAlign  ="middle"   horizontalCenter  ="0"   verticalCenter  ="0"  > 
 2           <  components:MusicList   skinClass  ="skins.MusicListSkin"   listContent  ="{musicList}"   creationComplete  ="initMusicList()"  />         
 3           <  components:PlayerControlBar   skinClass  ="skins.PlayeControlBarSkin"  /> 
 4   </  s:HGroup  > 

运行效果(自定义组件PlayerControlBar) :

自定义事件和事件派发:

事件流有三个阶段:捕获阶段--->目标阶段--->冒泡阶段
1.捕获阶段(从根节点到子节点,检测对象是否注册了监听器,是则调用监听函数)
2.目标阶段(调用目标对象本身注册的监听程序)
3.冒泡阶段(从目标节点到根节点,检测对象是否注册了监听器,是则调用监听函数)
注:事件发生后,每个节点可以有2个机会(2选1)响应事件,默认关闭捕获阶段。
从上到下(从根到目标)是捕获阶段,到达了目标后是目标阶段,然后从目标向上返回是冒泡阶段。

这里需要注意的是:如果派发事件的源(调用dispatchEvent方法)没有在一组容器里,那么这组容器里面的控件是监听不到这个派发事件的。

如下,在点击stateButton按钮的时候会派发一个自定义的事件PlayEvent, 然后在自定义组件PlayControlBar中添加
监听并作出相应处理:

 <  s:Button   left  ="15"   id  ="stateButton"   skinClass.run  ="skins.PlayButtonSkin"   skinClass.stop  ="skins.PauseButtonSkin"   click  ="dispatchEvent(new PlayEvent(PlayEvent.PLAY))"  /> 

( 自定义的事件:PlayEvent.as ) :

  1   package events
   2   {
   3       import   flash.events.Event;
   4      
  5       import   mx.states.OverrideBase;
   6      
  7       public   class  PlayEvent  extends   Event
   8       {
   9           public   static  const PLAY:String =  "play"  ;
  10          
 11           public   function  PlayEvent(type:String =  "play" , bubbles: Boolean = true , cancelable: Boolean = false  )
  12           {
  13               super  (type, bubbles, cancelable);
  14           }
  15          
 16          override  public   function   clone():Event
  17           {
  18               return   new   PlayEvent();
  19           }
  20       }
  21  }

自定义事件要继承Event类和重写clone方法。构造函数的第二参数表示是否要执行冒泡,如果不冒泡,父容器就捕获不到事件

添加监听:

 public   function   PlayerControlBar()
        {
              super  ();
              //  添加播放状态更改的监听器 
             this  .addEventListener(PlayEvent.PLAY, handleStateButtonClick);
          ………………  
        } 

事件处理函数:

  1   private   function  handleStateButtonClick(event:PlayEvent): void 
  2           {
   3               if (! isStart)
   4               {
   5                   //  加载音乐并开始播放 
  6                  playController =  new  PlayController( this  );
   7                  playController.start( "gole.mp3"  );
   8                  isStart =  true  ;
   9                   //  改变皮肤的状态 
 10                   this .skin.currentState= "stop"  ;
  11               }
  12               else   if ( this .skin.currentState ==  "stop"  )
  13               {
  14                   //  暂停播放音乐 
 15                   playController.pause();
  16                   this .skin.currentState= "run"  ;
  17               }
  18               else   if ( this .skin.currentState ==  "run"  )
  19               {
  20                   //  开始音乐播放 
 21                   playController.play();
  22                   this .skin.currentState= "stop"  ;
  23               }
  24          }

音频播放的处理:
Flex中音频的播放主要是靠Sound和SoundChannel两个类来实现的。
具体的使用Adobe的官方文档讲得非常详细,地址是:
http://help.adobe.com/zh_CN/FlashPlatform/reference/actionscript/3/flash/media/Sound.html

( 控制音乐播放类:PlayController.as ):

   1   package service.impl
    2   {
    3       import   components.PlayerControlBar;
    4      
   5       import   flash.display.DisplayObject;
    6       import   flash.events.Event;
    7       import   flash.events.TimerEvent;
    8       import   flash.media.Sound;
    9       import   flash.media.SoundChannel;
   10       import   flash.net.URLRequest;
   11       import   flash.utils.Timer;
   12      
  13       import   mx.managers.CursorManager;
   14      
  15       import   service.IPlayController;
   16      
  17       /*  *音乐播放控制类  */ 
  18       public   class  PlayController  implements   IPlayController
   19       {
   20           private   var   sound:Sound;
   21           private   var   soundChannel:SoundChannel;
   22           private   var   _pausePosition:int;
   23           private   var  _derectory:String =   "music/" 
  24           /*  *实时记录播放进度  */ 
  25           private   var   timer:Timer;
   26           private   var   view:PlayerControlBar;
   27          
  28           public   function   PlayController(view:DisplayObject)
   29           {
   30               this .view =  view as PlayerControlBar;
   31           }
   32          
  33  
  34           /*  *音乐播放暂停位置  */ 
  35           public   function   get   pausePosition():int
   36           {
   37               return   _pausePosition;
   38           }
   39  
  40           /*  *
   41            * @private
   42            */ 
  43           public   function   set  pausePosition(value:int): void 
  44           {
   45              _pausePosition =  value;
   46           }
   47  
  48           /*  *音乐存放的目录  */ 
  49           public   function   get   derectory():String
   50           {
   51               return   _derectory;
   52           }
   53  
  54           public   function   set  derectory(value:String): void 
  55           {
   56              _derectory =  value;
   57           }
   58  
  59           public   function  start(music:String): void 
  60           {
   61              sound =  new   Sound();
   62              timer =  new  Timer(1000 );
   63               var  urlRequest:URLRequest =  new  URLRequest(derectory +  music);
   64              sound.addEventListener(Event.COMPLETE,  function  handleStart(e:Event): void 
  65               {
   66                  soundChannel =  sound.play();
   67                   //  增加音乐播放完毕的监听器 
  68                   soundChannel.addEventListener(Event.SOUND_COMPLETE, handlePlayEnd);
   69                   timer.start();
   70                   sound.removeEventListener(Event.COMPLETE,handleStart);
   71               }
   72               );
   73               timer.addEventListener(TimerEvent.TIMER, handleTimmerWork);
   74               sound.load(urlRequest);
   75           }
   76          
  77           /*  音乐播放结束处理函数  */ 
  78           private   function  handlePlayEnd(e:Event): void 
  79           {
   80              stop( true  );
   81              view.skin.currentState =  "run"  ;
   82              view.isStart =  false  ;
   83               soundChannel.removeEventListener(Event.SOUND_COMPLETE,handlePlayEnd);
   84           }
   85          
  86           /*  每隔一秒,刷新进度条  */ 
  87           private   function  handleTimmerWork(e:TimerEvent): void 
  88           {
   89               var  estimatedLength:int =  Math.ceil(sound.length / (sound.bytesLoaded /  sound.bytesTotal)); 
   90               var  playbackPercent:uint =  Math.round(100 * (soundChannel.position /  estimatedLength));
   91              view.playSlider.value =  playbackPercent;
   92           }
   93          
  94           public   function  pause(): void 
  95           {
   96               if  (soundChannel)
   97               {
   98                  pausePosition =  soundChannel.position;
   99                   stop();                    
  100               }
  101           }
  102          
 103           public   function  play(): void 
 104           {
  105               if  (sound)
  106               {
  107                  soundChannel =  sound.play(pausePosition);
  108                   soundChannel.addEventListener(Event.SOUND_COMPLETE, handlePlayEnd);                
  109               }
  110               if (! timer.running)
  111                   timer.start();
  112           }
  113          
 114           public   function  stop(isExit: Boolean  =  false ): void 
 115           {
  116               if  (soundChannel)
  117               {
  118                   soundChannel.stop();
  119                   soundChannel.removeEventListener(Event.SOUND_COMPLETE,handlePlayEnd);                
  120               }
  121               if  (timer.running)
  122                   timer.stop();
  123               if  (isExit)
  124                   timer.removeEventListener(TimerEvent.TIMER,handleTimmerWork);
  125           }
  126          
 127           /*  *由Slider触发的播放  */ 
 128           public   function  clickPlay(): void 
 129           {
  130               //  根据拖动的位置计算实际音乐播放的位置 
 131               var  percent: Number  = view.playSlider.value /  view.playSlider.maximum;
  132               var  estimatedLength:uint = Math.ceil(sound.length / (sound.bytesLoaded /  sound.bytesTotal));
  133               var  position:uint = Math.round(percent *  estimatedLength);
  134               pause();
  135              pausePosition =  position;
  136               play();
  137           }
  138       }
  139  }

第59至75行是第一次点击播放时调用的方法,第64行Sound增加了一个事件监听,是在音乐加载完后执行的,
这个如果要边加载边播放的时候不适用,可以参考官方文档来解决这个问题。第94~101行中是点击暂停时调用
的方法,暂停的时候要把音乐播放的位置记录下来,如98行,这是为了要在继续播放的时候找到起点。第103
至112行是继续播放函数。


Timer类的使用实现播放进度实时更新:


当音乐播放的时候,这个播放进度条会每个同步的移动位置,拖动进度条,音乐也会播放到相应的位置。

进度条控件:

 <  s:HGroup   width  ="55%"   verticalAlign  ="middle"  > 
                 <  mx:HSlider   id  ="playSlider"   width  ="100%"   height  ="100%"   minimum  ="0"   maximum  ="100"  
                            change  ="dispatchEvent(new SliderEvent(SliderEvent.CHANGE,true))"  /> 
 </  s:HGroup  > 

当进度条通过拖动或者点击改变值的时候会派发自定义事件SliderEvent,这个在自定义组件 PlayerControlBar中进行监听和处理.

public  function   PlayerControlBar()
        {
            super();
           ………………  this  .addEventListener(SliderEvent.CHANGE, handlePlaySilderChange);
        } 

 处理函数:

 //  进度条拉动的触发函数,从指定位置开始播放 
        private  function  handlePlaySilderChange(e:SliderEvent): void  
        {
              if  (isStart)
            {
                (playController as PlayController).clickPlay();
                  if ( this .skin.currentState == "run" )
                      this .skin.currentState = "stop" ;
            }
        } 

clickplay方法:

  1           /*  *由Slider触发的播放  */ 
  2          public  function  clickPlay(): void 
  3           {
   4               //  根据拖动的位置计算实际音乐播放的位置 
  5               var  percent:Number = view.playSlider.value /  view.playSlider.maximum;
   6               var  estimatedLength:uint = Math.ceil(sound.length / (sound.bytesLoaded /  sound.bytesTotal));
   7               var  position:uint = Math.round(percent *  estimatedLength);
   8               pause();
   9              pausePosition =  position;
  10               play();
  11          }

第5~7行是计算当前进度条拖动的进度对应的音乐播放位置。

实时更新播放进度条:

  1  public  function  start(music:String): void 
  2           {
   3              sound =  new   Sound();
   4              timer =  new  Timer(1000 );
   5               var  urlRequest:URLRequest =  new  URLRequest(derectory +  music);
   6              sound.addEventListener(Event.COMPLETE,  function  handleStart(e:Event): void 
  7               {
   8                  soundChannel =  sound.play();
   9                   //  增加音乐播放完毕的监听器 
 10                   soundChannel.addEventListener(Event.SOUND_COMPLETE, handlePlayEnd);
  11                   timer.start();
  12                   sound.removeEventListener(Event.COMPLETE,handleStart);
  13               }
  14               );
  15               timer.addEventListener(TimerEvent.TIMER, handleTimmerWork);
  16               sound.load(urlRequest);
  17          }

第4行,在点击音乐播放的时候新建一个Timer类,并规定1秒执行一次,第11行是音乐播放的时候开始启动这个timer,第15行
中添加timer触发的事件。处理函数如下:

 /*  每隔一秒,刷新进度条  */  
        private   function  handleTimmerWork(e:TimerEvent): void  
        {
              var  estimatedLength: int  =  Math.ceil(sound.length / (sound.bytesLoaded /  sound.bytesTotal)); 
              var  playbackPercent:uint =  Math.round(100 * (soundChannel.position /  estimatedLength));
            view.playSlider.value  =  playbackPercent;
        } 

当停止音乐播放的时候也停止timer,开始播放音乐的时候启动timer:

  1   public   function  stop(isExit: Boolean  =  false ): void 
  2           {
   3               if  (soundChannel)
   4               {
   5                   soundChannel.stop();
   6                   soundChannel.removeEventListener(Event.SOUND_COMPLETE,handlePlayEnd);                
   7               }
   8               if  (timer.running)
   9                   timer.stop();
  10               if  (isExit)
  11                   timer.removeEventListener(TimerEvent.TIMER,handleTimmerWork);
  12          }

  1   public   function  play(): void 
  2           {
   3               if  (sound)
   4               {
   5                  soundChannel =  sound.play(pausePosition);
   6                   soundChannel.addEventListener(Event.SOUND_COMPLETE, handlePlayEnd);                
   7               }
   8               if (! timer.running)
   9                   timer.start();
  10          }

前端(FLEX)和服务器端(JAVA)之间的通信:
这个是通过Socket来实现的.
JAVA端的Socket编程若要和Flex端通信并且传递对象,就需要用到AMF序列化,这个Adobe为我们实现了,
只需要调用接口就可以了。Adobe的这个框架叫做blazeds , 在官网可以下载到,为了方便大家,这里给出了
下载地址: blazeds.zip      BlazeDS开发者指南

java服务端:

  1   public   class   MusicServer {
   2       private   ServerSocket serverSocket;
   3       private   Socket clientSocket;
   4      
  5       public  MusicServer( int   port)
   6       {
   7           try   {
   8              serverSocket =  new   ServerSocket(port);
   9              clientSocket =  serverSocket.accept();
  10               ClientSocketManager.addClient(clientSocket);
  11               MusicListService.sendMusicList(clientSocket);
  12          }  catch   (IOException e) {
  13               e.printStackTrace();
  14           }
  15       }
  16      
 17      
 18       public   static   void   main(String[] args) {
  19           new  MusicServer(9000 );
  20       }
  21  }

第11行是socket输入,输出流处理的类,主要是把服务端里面的所有音乐的文件名发送给客户端。
ClientSocketManager.java:

  1   public   class   MusicListService {
   2      
  3       public   static   void   sendMusicList(Socket socket)
   4       {
   5           try   {
   6              InputStream input =  socket.getInputStream();
   7              OutputStream outputStream =  socket.getOutputStream();
   8              Amf3Output amfoutput =  new  Amf3Output( new   SerializationContext());
   9              
 10               while ( true  )
  11               {
  12                   int  index = 0 ;
  13                   byte [] buffer =  new   byte [100 ];
  14                  StringBuffer requestState =  new   StringBuffer();
  15                   while (-1 != (index = input.read(buffer, 0 , buffer.length)))
  16                   {
  17                      String value =  new  String(buffer, 0 , index);
  18                       requestState.append(value);
  19                      
 20                      ByteArrayOutputStream byteOutput =  new   ByteArrayOutputStream();
  21                      DataOutputStream output =  new   DataOutputStream(byteOutput);
  22                       amfoutput.setOutputStream(output);
  23                      MusicList musicList =  MusicListGet.getMusicList();
  24                       amfoutput.writeObject(musicList);
  25                       output.flush();
  26                      
 27                       byte [] data =  byteOutput.toByteArray();
  28                       outputStream.write(data);
  29                       outputStream.flush();
  30                   }
  31                  
 32                   break  ;
  33               }
  34          }  catch   (IOException e) {
  35               e.printStackTrace();
  36          } finally 
 37           {
  38               try   {
  39                   socket.close();
  40                   ClientSocketManager.removeClient(socket);
  41              }  catch   (IOException e) {
  42                   e.printStackTrace();
  43               }
  44           }
  45       }
  46  }

第8行中导入了 Amf3Output类,这个类就是 blazeds.zip 包下面的,导入到项目中就可以了。


Flex客户端:

  1   public   class  SocketController  extends   EventDispatcher
   2       {
   3           private   static   var  socket:Socket =  null  ;
   4           private   var   view:DisplayObject;
   5          
  6           public   function  SocketController(host:String =  null , port:int = 0, view:DisplayObject =  null  )
   7           {
   8               if (! socket)
   9                  socket =  new   Socket();
  10               this .view =  view;
  11               configureListener();
  12               if (host && port != 0 )
  13               {
  14                   socket.connect(host,port);
  15               }
  16           }
  17          
 18          
 19           private   function  configureListener(): void 
 20           {
  21               socket.addEventListener(Event.CONNECT, handleConnect);
  22               socket.addEventListener(Event.CLOSE, handleClose);
  23               socket.addEventListener(ProgressEvent.SOCKET_DATA, handleRecieve);
  24           }
  25          
 26           private   function  handleConnect(e:Event): void 
 27           {
  28               socket.writeUTFBytes(RequestState.REQUESTLIST);
  29               socket.flush();
  30           }
  31          
 32           private   function  handleClose(e:Event): void 
 33           {
  34               if  (socket.connected)
  35                   socket.close();
  36              socket =  null  ;
  37           }
  38          
 39           private   function  handleRecieve(e:Event): void 
 40           {
  41               var  obj: Object  =  socket.readObject();
  42               if  (socket.connected)
  43                   socket.close();
  44               var  musicList:ArrayCollection =  obj.musicNames;
  45               if  (view)
  46                  view.dispatchEvent( new   MusicListEvent(MusicListEvent.LISTRECIEVE,musicList));        
  47           }
  48          
 49      }

Flex的socket都是异步方式来实现的,通过事件来处理,可以看到第21~23行为socket添加了几个事件监听,
第一个是建立连接成功的事件监听,第二个是连接关闭的监听,第三个是得到服务端返回消息的监听。  

程序还在不断的完善,本人也在学习当中,如果有兴趣的朋友,可以告诉我好的学习资料,或有什么好的建议,也希望告诉我哦.
下面是程序的源码地址:
audioplayer.rar

一颗平常心,踏踏实实,平静对待一切

 

分类:  flex&&ActionScript

标签:  socket通信 ,  事件流 ,  Timer ,  Slider ,  自定义组件 ,  音频

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于音乐播放器的详细内容...

  阅读:40次

上一篇: 权限系统

下一篇:粒子系统