【轉】 Pro Android學習筆記(八一):服務(6):複雜資料Parcel

來源:互聯網
上載者:User

標籤:

目錄(?)[-]

  1. 自訂的Parcelable類
  2. AIDL檔案
  3. 服務的實現
  4. Client的實現
  5. 同步和非同步
  

文章轉載只能用於非商業性質,且不能帶有虛擬貨幣、積分、註冊等附加條件。轉載須註明出處:http://blog.csdn.net/flowingflying/

在之前的StockQuote遠程服務的介面中的方法為double getQuote(String ticker);。在遠程服務中的方法的資料類型支援原始類型(primitive),如int這類的;支援String、CharSequence;複雜是類型支援List、Map,但在使用中有一些限制;如果我們希望使用自訂的類作為類型,需要使用Parcelable。本筆記將學習如何通過Parcelable封裝在遠程服務中的方法調用中進行複雜的資料傳遞。

遠程服務實際是處理序間通訊,因此在介面的串連中,並不是傳遞對象,而是向原始類型那樣,複製資料。Java的對象實際是C中的指標,Java並非沒有指標,而是除了primitive類型外,全部是指標,當都是指標時,開發人員感覺不到指標和非指標的差異,有時會有錯誤的感覺,以為Java無指標。由於不同進程有各自的記憶體空間,另一個進程不能操控其他進程的記憶體空間,也就是不能操控其他進程記憶體空間的對象。client和遠程服務建立了AIDL介面的串連,在操作時,將資料的內容整份進行傳遞,類似我們在socket中傳遞資料,我們傳遞資料的地址(指標/對象)是毫無意義的,我們必須傳遞資料的內容。

自訂的Parcelable類

Parcel是訊息(資料和對象)的容器,可以在IBinder(即遠程服務的串連)中傳遞。Parcel是Android中設計用於高效能的IPC傳輸,因此我們不要將Parcel資料直接寫到物理存貯中,因為Parcel中某個資料的改變,會使得其他資料變得不可讀。Parcelable則是介面,我們自訂的資料類型,需要實現該介面,才能作為Parcel在IBinder中傳遞。

下面的例子很簡單,我們自訂的資料類型Person含有兩個資料,一是int age,一是String name。

public class Person implements Parcelable
   //【1】自訂的類型具體包含的資料,本例為age和name。
    private int age = 0; 
    private String name = null; 
    
    @Override 
    public int describeContents() {  
        return 0; 
    } 

    /* 【2】要實現Parcelable介面,需要實現writeToParcel()和readFromParcel(),實現將對象(資料)寫入Parcel,和從Parcel中讀出對象。需要注意,寫的順序和讀的順序必須一致,因為Parcel類是快速serialization和deserialization機制,和bundle不同,沒有索引機制,是線性資料存貯和讀取。 
     * 注意其中readFromParcel()並不是overrider,而是我們自己提供的方法,如果我們不提供,就要在 
     * 
private Person(Parcel in){ 
     *     age = in.readInt(); 
     *     name = in.readString(); 
     * } 
     * 鑒於實際的資料類型會比小例子複雜,以及便於代碼閱讀,我們仿照writeToParcel()的命名,給出readFromParcel() */ 
    @Override 
    public void writeToParcel(Parcel out, int flag) {  
        out.writeInt(age);            //先寫入age
        out.writeString(name);   //其次寫如name 
    } 
    
    public void readFromParcel(Parcel in){ 
        age = in.readInt();          //先讀出age,保持與寫同順序
        name = in.readString();  //其次讀出name,保持與寫同順序
    } 

   /* 【3】:提供建構函式,用於從Parcel中建立對象,也即是讀的過程。這裡設定為private,禁止外部調用 */
    private Person(Parcel in){
 
        readFromParcel(in); 
    }  
     
    // 這個建構函式,是方便我們在client中創新相關對象,並將之作為介面串連中調用方法的的參數 
    public Person(){    
    } 
    
   /* 下面是我們在自訂類中的自訂方法,本例簡單提供age和name的讀寫 */ 
    public int getAge(){ 
        return age; 
    } 
    
    public String getName(){ 
        return name; 
    } 
    
    public void setAge(int age){ 
        this.age = age; 
    } 
    
    public void setName(String name){ 
        this.name = name; 
    }  
     
    /*【4】 實現Parcelable介面的類必須要有一個static field稱為CREATOR,用於實現Parcelable.Creator介面的對象。在AIDL檔案自動產生的Java介面中,IBinder將調用Parcelable.Creator來獲得傳遞對象:_arg1 = cn.wei.flowingflying.proandroidservice.Person.CREATOR.createFromParcel(data);  */ 
    public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() { 
        @Override 
        public Person createFromParcel(Parcel source) {  
            return new Person(source);  
//見【3】
        } 

        @Override 
        public Person[] newArray(int size) {  
            return new Person[size]; 
        }          
    };  
      
}

AIDL檔案

我們定義Person.aidl對Parcelable進行說明,由於我們已經有一個Person.java,所以系統不會再自動產生相關的java代碼。

package cn.wei.flowingflying.proandroidservice; 
parcelable Person;

當定義了Person.aidl中,我們可以在介面定義中使用該類型。在非原語類型,非String類型,其他的類型在介面中作為參數需要描述傳遞的方向in、out或者inout。

package cn.wei.flowingflying.proandroidservice; 
import cn.wei.flowingflying.proandroidservice.Person; 

interface IStockQuoteService2{ 
    String getQuote(in String ticker, in Person requester); 
}

服務的實現

服務的實現和之前的遠程服務沒有什麼區別,只是方法中資料類型的不同,下面是StockQuoteRemoteService2.java的片段,為了更好地和使用者互動,Service會在通知欄上出現,詳細可以下載我們的原始碼進行查看。此外我們需要在AndroidManifest.xml中對service進行定義。

public class StockQuoteRemoteService2 extends Service{  
    public class StockQuoteServiceImpl extends IStockQuoteService2.Stub{ 
        private int count = 0; 
        @Override 
        public String getQuote(String ticker, Person requester) throws RemoteException { 
            return "Hello " + requester.getName() + "! Quote for " + ticker + " is " + (20.0+(count++));
        } 
    } 
     
   ... ... 

    @Override 
    public IBinder onBind(Intent arg0) {  
        return new StockQuoteServiceImpl(); 
    } 
}

Client的實現

我們建立一個project來作為client。這個client同樣需要瞭解介面,瞭解介面中所涉及的parcelable Person的定義,因此我們需要將service中的IStockQuoteService2.aidl,Person.aidl以及Person.java拷貝過來。

和之前的client只是串連介面後,調用方法的參數不同,相關代碼如下:

public class MainActivity extends Activity { 
    private IStockQuoteService2 stockService2 = null;  
    … … 
    private ServiceConnection servConn = new ServiceConnection() {         
        @Override 
        public void onServiceDisconnected(ComponentName name) { 
            … …  
            stockService2 = null; 
        } 
        
       @Override 
        public void onServiceConnected(ComponentName name, IBinder service) { 
            … …  
            stockService2 = IStockQuoteService2.Stub.asInterface(service);         
        } 
    };     
    

    private void callService(){ 
        try{ 
            Person person = new Person(); 
            person.setAge(25); 
            person.setName("Flowingflying"); 
            String response = stockService2.getQuote("WEI", person); 
            Toast.makeText(this, response, Toast.LENGTH_LONG).show(); 
        }catch(RemoteException e){ 
            Log.e("Client2",e.toString()); 
        } 
    } 

同步和非同步

這裡學習的服務都是同步的,因為我們在UI thread中進行調用。如果service需要大量的運算,我們希望能夠運行在後台,也就是client在後台線程中對服務進行調用。

本博文涉及的例子代碼,可以在Pro Android學習:Android service小例子中下載。

相關連結: 我的Android開發相關文章

  

 

【轉】 Pro Android學習筆記(八一):服務(6):複雜資料Parcel

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.