2010年4月30日 星期五

Design Pattern : 18 Memonto

當我們希望在所開發的程式裡,可以提供Redo Undo的功能
可以利用Memonto Pattern達到這個目標
把Memonto物件放在要提供Undo功能的程式中(Subject)

參與者
1.Memonto
Memonto本身利用一個陣列來儲存資料,當要restor資料,再
由陣列倒回來

public class Memonto {
    private Vector<String> memos=new Vector<String>();
    public void save(String value){
        memos.add(value);
    }
    public String restoreLast(){
        memos.removeElementAt(memos.size()-1);
        return result;
    }
}

2.Subject
要使用memo功能的主程式
當主程式執行save功能時,是把資料丟給memo去儲存
當要undo時,再利用memo把資料取回,寫回本應用程式的變數中

public class Subject {
    private Memonto memo;
    private String myText;
    public Subject(){
        memo=new Memonto();
    }
    public void save(String value){
        myText=value;
        memo.save(myText);
    }
    public String undo(){
        myText=memo.restoreLast();
        return myText;   
    }
}

3.Main
外部程式,只要呼叫應用程式提供的save跟undo method即可
不用管subject內部memo如何運作

TextField text=new TextField()
Subject subject=new Subject();
儲存
subject.save(text.getText());
Undo
text.setText(subject.undo());


2010年4月28日 星期三

Design Pattern : 17 Observer

在一個程式主體(Generator),如果內部運算後產生一些變化,希望可以把變化的結果,通知外部特定對象,可以把要通知的對象都設定成Observer

在Generator內需要有把observer加入觀察的method(addObserver)
與通知observer的功能(notifyObserver),而在observer內,會需要有一個update的method
可以在接收到Generator的通知後,到Generator內取到結果,這樣當主體程式有所變化,所有設定的observer都會接收到通知,而做適當的訊息處理

參與者
1.Generator
   可以使用Observer的Class
   addObserver:把觀察者加進來的method
   notifyObserver:用來通知所有observer的method
   excute:執行程序,在這類別真正要執行的工作,當工作完成
一定要觸發notifyObserver通知所有的觀察者
   getNumber:這是讓Observer接收到通知後,回來取值得method


public abstract class Generator {
    private Vector<Observer> observers=new Vector<Observer>();   
    private int number;
    public void addObserver(Observer observer){
        observers.add(observer);       
    }
    public void deletObserver(Observer observer){
        observers.remove(observer);
    }
    private void notifyObserver(){
        Iterator<Observer> it=observers.iterator();
        while(it.hasNext()){           
            ((Observer)it.next()).update(this);
        }
    }
    public void excute(){
        Random random=new Random();
        number=random.nextInt(50);
        notifyObserver();
    };
    public int getNumber(){
        return number;
    };
}


2.Observer interface
   Observer可能有很多個,先設定一個所有observer需遵循的統一介面
   update:當obsever被通知,就是被Generator呼叫了這個updtae method
   在這個method內可以利用傳進來的Generator物件,再回去取到變化的值

public interface Observer {
    public abstract void update(Generator gen);
}


3.FirstObserver 實作類別

public class FirstObserver implements Observer {   
    public void update(Generator gen) {
        System.out.println("First:"+gen.getNumber());
    }
}


4.SecondObserver

public class SecondObserver implements Observer {
    public void update(Generator gen) {
        System.out.println("Second:"+gen.getNumber());
    }
}


5.Main外部程式
只要產生Generator,加入關聯的observer後
就可以執行他要做的動作,同時在這動作內也已經
包含了通知observer的功能


Generator gen=new Generator();
gen.addObserver(new FirstObserver());
gen.addObserver(new SecondObserver());
gen.excute();


2010年4月27日 星期二

Design Pattern : 16 Mediator

Mediator的角色,通常都是當作UIComponent的代理人
UIComponent是使用者會直接接觸到的元件
如Button,TextField等,當我們在操作這些UIComponent
UIComponent 只是用來當作View顯示,而不做邏輯處理
也就是說,當接收到使用者的指令,如按鈕,輸入文字..
會把這些事件丟出去,往外通知
UIComponent..只是單純被操作
事件丟出的方式,可以是用dispatchEvent方式廣播
或是通知mediatior來處理
而Mediator的角色,就是主程式與UIComponent間的橋樑

參與者
1.Mediator 介面
createColleagus:利用這method把所有的UIComponent登錄到Mediator上
colleagusChanged:當有登錄的UIComponent狀態改變時都會呼叫這method
通知mediator作處理

public interface Mediator {
    public abstract void createColleagus();
    public abstract void colleagusChanged(Colleagus colleagus);
}

2.Colleagus
所有的UIComponent都implement這介面,讓UIComponent都有可以跟
mediator溝通的共同method
setColleagusEnabled:要改變UComponent不要直接去操作到UIComponent,
而是透過一個public API去操作


public interface Colleagus {
    public abstract void setMediator(Mediator mediator);
    public abstract void setColleagusEnabled(boolean enabled);
}

3.ColleagusTextField 實作的Colleagus
本身是TextField,同時也以自己當作TextListener
textValueChanged:當TextEvent被觸發時會執行這method
在這method中通知mediator

public class ColleagusTextField extends TextField implements Colleagus,TextListener{
    private Mediator mediator;
    public ColleagusTextField(String text,int columns){
        super(text,columns);
    }
    @Override
    public void setColleagusEnabled(boolean enabled) {       
        setEnabled(enabled);
        setBackground(enabled?Color.white:Color.gray);
    }
    @Override
    public void setMediator(Mediator mediator) {       
        this.mediator=mediator;
    }
    @Override
    public void textValueChanged(TextEvent arg0) {       
        this.mediator.colleagusChanged(this);
    }
}

4.LoginFrame 實作的Mediator

public class LoginFrame extends Frame implements Mediator,ActionListener{
    private ColleagusTextField textUser;
    public LoginFrame(String title){
        super(title);
        setBackground(Color.lightGray);
        setLayout(new GridLayout(4,2));       
        createColleagus();
        add(textUser);
        pack();
        setVisible(true);       
    }
    @Override
    public void colleagusChanged(Colleagus c) {
       
    }
    @Override
    public void createColleagus() {
        textUser=new ColleagusTextField("input user name",10);
        textUser.setMediator(this);
        textUser.addTextListener(textUser);   
    }
    @Override
    public void actionPerformed(ActionEvent arg0) {
           
    }
}

5.Main 外部程式

new LoginFrame("Main Frame");


2010年4月26日 星期一

Android 開發入門注意事項

一.在模擬器安裝apk
    在網路上下載到已經開發好的Android程式(*.apk)
    要如何安裝到模擬器上執行?
    1.先在電腦環境變數內(path)加入Android_SDK/tools目錄
       讓SDK內tools下的指令可以直接執行
    2.在cmd下執行
       adb install xxx.apk,即可把程式安裝到模擬器內
    3.解除安裝
       adb shell rm data/app/xxx,apk

二.Compile錯誤處理
   在Eclipse中Compile Android 是針對Activity Java Compile
   如果不小心在layout xml上compile發生錯誤後
   將產生的out.xml刪除,再到Problems Panel內刪除錯誤的列表
   才可以再重新Compile

三.xml檔案名稱必須要是小寫
   在設計layout xml時,檔案名稱一定要使用全小寫
   loginPage.xml~~這是不允許的
   可改用login_page.xml代替

四.View元件屬性設定不完全錯誤
   若在layout xml內加入 view元件,layout_width與layout_height
   一定要設定,否則即使compile成功,在模擬器上執行一定會發生錯誤

五.將元件參考變數設定在class範圍
   在Activity內會利用findViewById來取得各個view元件參考
   如 TextView mytext=(TextView)findViewById(R.id.myText)
   這些變數,不要當作function內的local變數使用
   最好是宣告在class的變數上,否則,在其他function內是無法操作
   來改變這些view元件的屬性

2010年4月22日 星期四

FlashDevelop 上發布Air Project相關事項

一.設定讓FlashDevelop Air API Auto Complete
    在Project Properties/compiler Option/SWC Include Lib
    加入air swc的路徑
    C:\Program Files\Adobe\Adobe Flash CS4\AIK1.5\frameworks\libs\air\airglobal.swc
    C:\Program Files\Adobe\Adobe Flash CS4\AIK1.5\frameworks\libs\air\servicemonitor.swc

二.產生AIR
1.當設定的Project為AIR
   在Project目錄下會有兩個bat檔CreateCertificate.bat與PackageApplication.bat
2.CreateCertificate.bat 產生認證檔
    編輯
   1.設定Flex SDK路徑
      set PATH=%PATH%;C:\flex_sdk_4\bin
   2.設定這認證pfx檔案的,名字,密碼與輸出檔名
set NAME=MyName
set PASSWORD=MyPassword
set CERTIFICATE=MyName.pfx
這在產生air檔案時,會需要這帳號密碼確認
   3.修改完,執行,即會產生一個pfx檔
3.PackageApplication.bat 封裝AIR
    編輯
    1.設定Flex SDK路徑
set PATH=%PATH%;C:\flex_sdk_4\bin
    2.指定要使用的數位認證檔
       set CERTIFICATE=MyName.pfx
    3.設定要輸出的檔案路徑
       set AIR_FILE=air/FlexTest1.air
    4.執行,即產生AIR檔
4.注意
  若在封裝AIR檔案發生錯誤
  如application.xml error 102:invaid namespace
  請確認,系統安裝的AIRSDK版本,與application.xml
  namespace設定的版本是否相符

三.發布到網頁
1.下載 Badge Sample
Adobe Badge Sample
http://download.macromedia.com/pub/developer/air/badge_install_samples.zip
2.修改網頁參數
   1.flaVar參數
appname:AIR App名稱(需URL encode,也就是經過escape過)
appurl:要下載的air檔案網址
airversion:要跑這個air的 runtime版本需求
imageurl:(非必填)要放到badge內的圖片路徑
buttoncolor:(非必填)按鈕顏色,預設為000000
messagecolor:(非必填)訊息文字顏色,預設為000000

   2.<noscript>內放當不支援flash player時,要提供顯示的文字連結內容

3.手動讓Web Server認得AIR檔案
  在Apache 的http.conf 加入
  <IfModule>
   AddType application/vnd.adobe.air-application-installer-package+zip .air
   </IfModule>
4.若使用Flash Player Detection Kit,可以讓使用者在站上就直接更新flash player
http://www.adobe.com/products/flashplayer/download/detection_kit/
5.執行程序
在網站上點badge安裝時
系統會先檢查,是否有Air RunTime,如果沒有會自動安裝下載
結束後,自動安裝應用程式
若已經安裝過,會檢查版本是否有更新過,如無,則可直接開啟程式
若有新版,則會安裝新版本
6.資料來源
http://www.adobe.com/devnet/air/articles/air_badge_install.html

四.安裝AIR runtime到Ubuntu上
1.下載
     http://airdownload.adobe.com/air/lin/download/1.5/AdobeAIRInstaller.bin
2.設定為可執行檔
     chmod +x AdobeAIRInstaller.bin
3.安裝
     sudo ./AdobeAIRInstaller.bin

五.AIR 自動Update機制
1.AIR Project的Application.xml內設定了這個app的版本
   安裝到client上,client上以這作為已安裝版本依據
2.在發布新的air更新檔,同時要放置一個updateInfo.xml到網站上
   當作一個版本比對的參考,只要有更新AIR版本,就要修改這份XML內容
<?xml version="1.0" encoding="utf-8"?>
<update xmlns="http://ns.adobe.com/air/framework/update/description/1.0">
<version>1.0</version>
            <url>http://192.168.11.80/air/myApp.air</url>
    <description>
  <text xml:lang="en_US">AIR AutoUpdate</text>
  <text xml:lang="zh_TW">AIR 自動更新</text>
  </description>
</update>
3.當使用者在執行其已安裝的app時,會去連線檢查
server上updateInfo.xml內的版本跟本機的是否一致
如有新版,則自動更新
4.所以,在你的AIR App程式內
需要利用ApplicationUpdater 這Class來載入Server上的updateInfo.xml
讀取版本資料來做比對,並做更新下載




六.另外需要注意的是,在FlashDevelop上開啟AIR Project在Property OutPut的設定上,需使用預定的Run Custom Command,也就是執行
C:\flex_sdk_4.1\bin\adl.exe;application.xml bin
如果只是當作一般SWF輸出到Tab上,AIR相關API會失效

2010年4月20日 星期二

Design Pattern : 15 Facade

當要執行複雜的多物件功能呼叫使用
可以利用Facade提供單一介面,整合這些要做的功能
讓使用者只要透過呼叫Facade所提供的單一介面窗口
就可執行整個複雜的工作內容
例如,希望載入外部資料庫(DataBase),並利用這些載入的資料,
產生網頁(HtmlWriter),這工作
參與者
1.DataBase
  用來載入外部資料的類別

public class Database {
    private Database(){}
    public static Properties getProperties(String dbName){
        String fileName=dbName;
        Properties prop=new Properties();
        prop.load(new FileInputStream(fileName));
        return prop;       
    }
}

2.HtmlWriter
  用來產生網頁檔案的類別

public class HtmlWriter {
    private Writer writer;
    public HtmlWriter(Writer writer){
        this.writer=writer;
    }
    public void title(String title)throws IOException{
        writer.write("<html><head>");   
        writer.write("<title>"+title+"</title");
        writer.write("</head><body>\n");
        writer.write("<h1>"+title+"</h1>\n");
    }
    public void close()throws IOException{
        writer.write("</body></html>");
        writer.close();
    }
 }

3.Facade
用來整合功能的介面

public class Facade {
    private Facade(){}
    public static void makeWelcomePage(String dbFileName,String addr, String outFileName){
        Properties mailProp=Database.getProperties(dbFileName);
        String userName=mailProp.getProperty(addr);               
        HtmlWriter writer=new HtmlWriter(new FileWriter(outFileName));
        writer.title("Welcome "+userName);           
        writer.close();
    }
}

4.Main
外部程式

Facade.makeWelcomePage("d:\\list.txt","xxx@xxx.com","d:\\newPage.htm");

  

2010年4月16日 星期五

focusEnabled對Event影響

當我們要讓一個物件可以監聽到滑鼠或鍵盤的動作
通常會把addEventListener到該物件上,
但如果該物件沒有取得Focus,那所有的動作將都不會有所作用
利用focusEnabled屬性的設定,可以讓滑鼠click到該物件
由該物件取得focus,而非由其上層物件取得focus
例如
將一個TileList包裝在一個mxml的Component上
希望TileList可以監聽到Keyboard動作而有所回應
設定如下
tileList.focusEnabled=true;
tileList.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDownEvent)

1.KeyboardEvent需直接加在tileList上,不可加在他上層的mxml上

2.利用tileList.focusEnabled = true讓滑鼠click到myList即讓
    tileList變成focus狀態,讓上面的event可以有作用

Design Pattern : 14 Chain of Responsibility


轉送,當對於一個複雜的問題處理,可以把問題拆解成多個單一的問題處理方法(Support)每個Support,遇到丟進來的問題,會試著去解決
Support.support(trouble)
當無法解決時,就看看是否已經有利用Support.setNext(nextSupport),設定好下一個Support
如果有,就把問題丟給下一個support處理
nextSupport.support(trouble)
這樣的做法,可以讓每個Class可以很單純的處理一個問題,而且可以彈性的串接不同的Command

參與者
1.abstract Support
在Support這主要的Class內定義好程式判斷的流程,也就是support function
決定了判斷邏輯,後面繼承者,只需要把問題處理的部份(resolve)實作即可

public abstract class Support {
  public Support setNext(Support next){
     this.next=next;
     return next;
  }
  public final void support(Trouble trouble){
    if(resolve(trouble)){
        success();
    }else{
        fail();
        if(next!=null){
          next.support(trouble);
        } 
    }
  }
 protected abstract boolean resolve(Trouble trouble);
 private void success(){}
 private void fail(){}
}


2.RealSupport
可以針對各式的解決方法,產生多個不同的support子類別
每個class的都只要針對resolve function實作處理的結果即可

public Class RealSupport01 extends Support{
    protected boolean resolve(Trouble trouble){
              ......
      }
}



public Class RealSupport02 extends Support{
     protected boolean resolve(Trouble trouble){
         ......
     }
}


4.Trouble

public Class Trouble{...} 



5.Main
外部程式,產生各個解決問題的support實體,並利用
setNext設定其解決問題的順序

Support sp1=new RealSupport01();
Support sp2=new RealSupport02();
sp1.setNext(sp2);
sp1.support(new Trouble());


 

2010年4月15日 星期四

Design Pattern : 13 Visitor

如果我們需要對一個複雜系統架構(Acceptor),針對整個系統做一巡訪
並做不同的動作處理,將把這處理器(Visitor)的部份獨立出來成為物件
也就是將資料處理由資料結構中分離出來,就是Visitor Pattern

例如,你有一個檔案架構系統,你希望把整個檔案目錄架構整個列印出來
我們需要有一個print_Visitor是負責來做把檔案列印出來的工作,
只要把這print_Visitor丟到一個複雜架構(acceptor)內,就會達到這目的

如果我們希望在這檔案架構內,希望可以把所有圖檔都可以產生一個縮圖
這時候,你可以產生另一個thumb_Visitor,用來負責產生縮圖的工作
只要把這thumb_Visitor丟到架構內,就會達到目的

對於一個複雜架構的系統(Acceptor),丟進去不同功能的Visitor
就可以對整個系統做不同功能的事

實作Visitor Pattern會用到一個比較複雜的遞迴(Double dispatch)
一般遞迴是自己呼叫自己,在這裡面是Acceptor與Visitor的彼此呼叫遞迴


參與者
1.Acceptor
Acceptor內需要定義一個accept method,這method只是都固定用來
把自己當作參數,呼叫啟動visitor的巡訪動作

public Class Acceptor {
     public void accept(Visitor v){
   v.visit(this)
     };
     .....
}

2.Visitor
程式的運作核心是在Visitor的visit function

public Class Visitor{
 public void visit(Acceptor entry){ 
  Iterator it=entry.iterator()
  while(it.hasNext()){
   Acceptor en=it.next();
   en.accept(this);
  }
 }
}

3.Main
外部程式

Acceptor rootdir=new Acceptor("root");
rootdir.accept(new Visitor());
4.在Visitor實作迴圈上

private String currentdir=""
public void visit(Directory dir){
 String savedir=currentdir+"/"+dir.getName()
 Iterator it=dir.iterator();
 while(it.hasNext()){
  Entry entry=(Entry)it.next();
  entry.accept(this)
 }
 currentdir=savedir;
}

在這範例內,先以一個currentdir儲存目前所在的目錄名稱
savedir會是下一層的entry所在的目錄名稱
所以在while迴圈內,利用it.next()取到的entry是與目前entry同層級的物件
entry.accept(this)裡 的this內的currentdir與現在所在的相同
while迴圈處裡完,也就是同層級的都處裡完了

currentdir=savedir是設定好,下一層級所在的目錄
下一個層級的this取到currentdir就會是目前層級得savedir

2010年4月8日 星期四

非同步指令實作


在Class內,開發好多個獨立基本功能的function,希望以這些獨立的functio
如同積木般去組合成各式不同應用,把這些function看成一個個獨立的command
這時候會需要可以做到,讓command可以非同步的依順序執行,在執行過程中,
提供給command的參數,除了是使用一般變數外,可能需要是上一個command作用
完的結果,再丟到下一個command內執行
要達到這目標,建立一個用來控制Command用的MultiCommander來處理所有要做的功能
包括提供
1.addCommand():讓使用者設定,當接收到什麼evnet,要去執行什麼command
2.dispatchComplete():在使用者所開發好的各項command function內,在執行
  command完成後,去執行dispatchComplete(),好讓控制流程的commander知道
  接下來要去執行哪個command
3.execute():呼叫,即開始執行整個command list
4.當有需要將上一個command執行的結果傳遞給下一個command當作參數去執行
  這部分利用外部一個共用object物件,把要傳遞的參數放到object內傳遞
  達到command要執行時,才讀到真正要給的變數值,而非一開始設定addCommand
  時提供的值

虛擬code

class MyClass{
 public const cmd1Complete:String = "cmd1Complete";
 public const cmd2Complete:String = "cmd2Complete";
 public var commander:MultiCommander;
 public var infoObj:Object = new Object();
 public function TestMultiCommander(){ 
  infoObj.x = 1;
  commander = new MultiCommander(this);
  commander.addEventListener(MultiCommander.CommandComplete, onCommandComplete);
  commander.addCommand(MultiCommander.CommandStart,run1,infoObj).addCommand(cmd1Complete,run2,infoObj).execute();
 }
 public function run1(_info:Object):void {
  _info.x++;
  trace("run1 infoObj.x=",infoObj.x)
  commander.dispatchComplete(cmd1Complete);  
 }
 public function run2(_info:int):void {
  _info.x++;
  trace("run2 infoObj.x=",infoObj.x)  
  commander.dispatchComplete(cmd2Complete);
 }
}

執行結果
run1 infoObj.x=2
run2 infoObj.x=3

說明
1.產生一個commander物件,並將commander所在的主程式class丟進去當參考
 commander=new MultiCommander(this)
2.設定所有會觸發的事件名稱,與用來交換資訊的物件
 private var Run1Complete:String="Run1Complete";
 private var Run2Complete:String="Run2Complete";
 public var infoObj:Object=new Object()
3.設定監聽所有指令列完成,所發出的通知
  commander.addEventListener(MultiCommander.CommandComplete, onCommandComplete);
4.加入要執行的command
  commander.addCommand(EventType,function,args...):MultiCommander
  EventType:設定當接收到這eventType時
  function:就會去執行設定的function
  args:可以放所有要給function執行的參數

  若是第一個執行的command,EventType設定就是用MultiCommander.CommandStart
  addCommand可以用串接方式執行
  例:
  commander.addCommand(MultiCommander.CommandStart,run1,...).addCommand(Run1Complete,run2,...)..

  如果要在各個command間交換的變數,希望在command執行時,才到上層取值的部分
  將通用的變數包裝在上層的infoObj物件,再將物件傳遞給command執行
5.所有執行的command,在完成時,都需dispatchComplete()
  例:
 
function run1(){
    ...
    commander.dispatchComplete(Run1Complete);
  }


6.執行
 
commander.execute();

呼叫Function,參數以值傳遞與物件傳遞的差異


在呼叫執行function時,參數以物件傳遞與以變數傳遞是有相當的不同的
如果以變數傳遞,變數值傳到function內會變成一個獨立的值,傳入後就與function外部無關
若是把變數包在一個外部的物件上,改傳入物件,則在function內改變物件內的變數值
改變到的是funcion外部的物件,就會跟其他程式發生關聯,也就是說傳遞到function內的
物件可以看作只是一個物件的參考

用物件傳遞的好處是,若希望做非同步多function依序執行
以物件傳遞,可以達到,在function真正要執行時,
才透過物件參考取到要傳進去的值
也就是說只要利用一個class變數的object,來傳遞,要在各個function交換的值

以下範例,是不考慮非同步執行的虛擬程式碼

值傳遞

class MyClass{
 protected var x=1
 public function MyClass():void{
  run1(x);
  run2(x)
 }
 public function run1(_input:int):void{
  _input++;
  trace('run1=',x)
 }
 public function run2(_input):void{
  _input++;
  trace('run2=',x)
 }
}

得到的結果是
run1=1
run2=1

物件傳遞

class MyClass2{
 protected var infoObj:Object=new Object();
 public function MyClass2():void{
  infoObj.x=1;
  run1(infoObj);
  run2(infoObj)
 }
 public function run1(_info:Object):void{
  _info.x++;
  trace('run1=',infoObj.x)
 }
 public function run2(_info:Object):void{
  _info.x++;
  trace('run2=',infoObj.x)
 }
}

得到的結果是
run1=2
run2=3

2010年4月6日 星期二

Android Activity與Layout XML關係

Activity與Layout XML關係
在Android上,視覺外觀的View部分都是以XML型態存放在res/layout/目錄下
真正執行動作的Activity程式碼,是以Java型態
放在src的目錄下,這部份是真正執行的程式碼

1.XML與Java關係
Java與XML的關係,可以看成相當於Flex下MXML與AS的關係,
如果以MVC架構來看,可以把Layout XML當作一個單純的view,
而Java Code的Activity則相當於Mediator的角色,
由Activity去控制XML的顯示內容

2.如何讓Activity與XML關聯在一起?
可以在Activity內找到setContentView這Method
就是利用這Method把Java與XML的關係串起來
讓Java可以操作到XML上設定的view元素

3.在Java如何取得並操作XML上的元素
要操作xml上的view元素,都是要靠id來找到要控制的物件

4.如何在Layout XML內設定id值
在layout xml內,每個元件都要設定一個id值以供辨識
這view物件,設定值為 :@+id/要設定的id名稱

 <Button android:id="@+id/shareBtn" android:layout_width="wrap_content"  
 android:layout_height="35px" android:text="@string/music_shareBtn" />  

5.如何在Activity Java Code利用id值取到物件
主要利用R.id.viewID來取得

TextView myText=(TextView)findViewById(R.id.myTextId);

6.Activity取得layout view物件的標準流程
在Activity 的onCreate內將layout xml與Activity連結在一起


public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    TextView myText=(TextView)findViewById(R.id.myTextId);
}

2010年4月2日 星期五

Garbage Collection


在Flash內GC的工作是Player本身會自動會去執行,但在程式開發時要
去儘可能回收不必要的記憶體暫存,降低記憶體使用量
1.對Loader物件
在使用Loader物件載入外部圖檔或swf,當已經不再需要使用時
可以loader.unloadAndStop(true),會強制卸載載入物件並做GC
2.對BitmapData
當BitmapData不再使用,要釋放bitmapData內存的資料
可以用bitmapData.dispose();
3.一般DisplayObjectContainer
除了對不必要的child做remove
DisplayObjectContainer.removeChildAt(0);
若是屬AIR專案
可以執行System.gc()強制立刻執行GC
4.判別Child的Class 類型
當要移除Child時,要知道Child的Class類型才可以使用適當的方式處理


var sourceName:String = getQualifiedClassName(_source.getChildAt(0));
var sourceType:Class = getDefinitionByName( sourceName) as Class;
if (sourceType == FlexLoader) {
    _source.unloadAndStop(true);   
}else if (sourceType == Bitmap) {
    Bitmap(_source.getChildAt(0)).bitmapData.dispose(); 
}
_source.removeChildAt(0);
System.gc();

BitmapData與ByteArray的操作


在Flash內,我們如果需要對外部載入圖檔,或是stage上的Sprite
做一些點陣圖形的操作(變形旋轉或其他)
要將處理過後的點陣資料,做頁面上顯示或是另做檔案儲存
在這過程中,都是在於DisplayObject,BitmapData與ByteArray這三者的轉換處理
以下是常用處理範例
BitmapData操作
1.如何取得DisplayObject的bitmapData


var bitmapData:BitmapData=new BitmapData(w,h);
bitmapData.draw(DisplayObject) 

2.如何取得外部圖檔或swf的bitmapData
(也就是將外部檔案寫到bitmapData內)
1.利用Loader載入外部檔案


var loader:Loade=new Loader()
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete);
loader.load('xxx.jpg');

2.載入完成後,將載入資料寫到bitmapData內


var bitmapData:BitmapData=new BitmapData(w,h);
bitmapData.draw(loader)


3.如何將bitmapData變成一個DisplayObject


var bitmapData:BitmapData=new BitmapData(w,h);
var bitmap:Bitmap=new Bitmap(bitmapData);
DisplayObjectContainer.addChild(bitmap); 

4.如何將bitmapData變成byteArray
如果要將圖檔以資料方式傳到Server上,要轉成byteArray形式才能上傳


var byteArray:ByteArray=JPEGEncoder.ecncode(bitmapdata)


ByteArray操作
1.如何將byteArray變成一個實體檔案


var targetFile:File =File.createTempFile();
var stream:FileStream = new FileStream();
stream.open(targetFile, FileMode.WRITE)
stream.writeBytes(byteArray, 0, 0);
stream.close(); 

2.如何將byteArray變成bitmapData


var bitmapData:BitmapData=new BitmapData(w,h);
bitmapData.setPixels(new Rectangle(),byteArray);