xamarin學習筆記A17(安卓Parcel和IParcelable)

(每次學習一點xamarin就做個學習筆記和視頻來加深記憶鞏固知識)
如有不正確的地方,請幫我指正。
簡介
    要在同一程序的不同組件之間(如Activity與Activity之間)傳遞對象或者要在兩個不同進程之間傳遞對象,就可以使用Parcel和IParcelable來實現。
也可用ISerializable,但ISerializable在序列化對象時會產生大量臨時變量,效率不高。
還可以用Json字符串來傳遞對象。

主要用到下面的類和接口

Parcel

可把數據序列化以方便傳輸,IPC(跨進程)傳輸數據用到了此類。

IParcelable接口

用來定義(把數據寫到Parcel中的)方法。(即規定打包方法)

IParcelableCreator接口

用來定義(從Parcel中解析出數據的)方法。(即規定解包方法)

具體打包和解包方法讓我們自己去實現,系統到時自動調用。

使用
    查看Intent類,可以看到要傳遞一個對象或多個對象是使用下面的方法
public class Intent
{
//..........................
	public virtual Intent PutExtra(string name, IParcelable value);
	public virtual Intent PutExtra(string name, IParcelable[] value);
//..........................
}
也就是要求必須是實現了IParcelable接口的對象纔可傳遞。
查看IParcelable接口
namespace Android.OS
{
    public interface IParcelable : IJavaObject, IDisposable
    {
        void WriteToParcel(Parcel dest, [GeneratedEnum] ParcelableWriteFlags flags);
	int DescribeContents();
    }
}
從上面的代碼可看出,這個接口定義了兩個要實現的方法,WriteToParcel()是用來把數據打包到Parcel對象中,需要我們來實現具體要把對象中的哪些數據以什麼順序打包進去。DescribeContents()是在系統內部進行安全保護所使用的,返回0即可,不用管它。
查看IParcelableCreator接口
namespace Android.OS
{
    public interface IParcelableCreator : IJavaObject, IDisposable
    {
        Java.Lang.Object CreateFromParcel(Parcel source);
        Java.Lang.Object[] NewArray(int size);
    }
}
從上面的代碼可看出,這個接口定義了兩個要實現的方法,CreateFromParcel(Parcel source)方法用於將parcel對象的數據解析爲指定的對象。NewArray不用管,直接返回指定對象的數組就行。

舉個例子,首先定義個Book類,實現IParcelable接口
public class Book :Java.Lang.Object, IParcelable
    {
        public int BookId{ get; set; }
        public string BookName { get; set; }
        public double BookPrice { get; set; }

        public Book()
        {
        }
		//自定義個解析數據的方法(解析順序和打包順序一定要一致)
		private Book(Parcel parcel)
        {
            BookId = parcel.ReadInt();
            BookName = parcel.ReadString();
            BookPrice = parcel.ReadDouble();
        } 
 
        //打包數據到Parcel類的對象dest中 (解析順序和打包順序一定要一致)
        public void WriteToParcel(Parcel dest, [GeneratedEnum] ParcelableWriteFlags flags)
        {
            dest.WriteInt(BookId);
            dest.WriteString(BookName);
            dest.WriteDouble(BookPrice);
        }

        public int DescribeContents()
        {
            return 0; //這個值是在系統內部進行安全保護所使用的,就填0即可
        }

private static readonly BookParcelableCreator _creator = new BookParcelableCreator();
[ExportField("CREATOR")]//必須使用CREATOR這個固定的名稱
        public static BookParcelableCreator GetCreator()
        {
            return _creator;
        }

}

然後還是在Book類中,定義個BookParcelableCreator類,實現IParcelableCreator接口

public class BookParcelableCreator : Java.Lang.Object, IParcelableCreator
        {
            public Java.Lang.Object CreateFromParcel(Parcel source)
            {
                return new Book(source);
            }

            public Java.Lang.Object[] NewArray(int size)
            {
                return new Java.Lang.Object[size];
            }
        }
然後就可以使用了,在MainActivity中發送對象到另一個Activity

public class MainActivity : AppCompatActivity
    {
        //...........................省略其它代碼

        private void SendBookToActivity()
        {
            Book book = new Book();
            book.BookId = 1;
            book.BookName = "C#高級編程";
            book.BookPrice = 68.8;

            Intent intent = new Intent(this, typeof(SecondActivity));
            intent.PutExtra("s", book);
            this.StartActivity(intent);
        }
    }
然後在SecondActivity中接收Book對象

public class SecondActivity : AppCompatActivity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            SetContentView(Resource.Layout.Second);

            var book = Intent.GetParcelableExtra("s") as Book;
            if (book != null)
                Toast.MakeText(this, book.BookName, ToastLength.Long).Show();
        }
    }
可以把上面的BookParcelableCreator類的功能提取出來做個通用的,這樣其它實體類就不用再寫像BookParcelableCreator類這樣的代碼了。
如下所示
public sealed class MyParcelableCreator<T> : Java.Lang.Object, IParcelableCreator
        where T:Java.Lang.Object,new ()
    {
        private readonly Func<Parcel, T> _createMethod;

        public MyParcelableCreator(Func<Parcel, T> createMethod)
        {
            _createMethod = createMethod;
        }

        public Java.Lang.Object CreateFromParcel(Parcel source)
        {
            return _createMethod(source);
        }

        public Java.Lang.Object[] NewArray(int size)
        {
            return new T[size];
        }
    }

然後在Book類中這樣使用

private static readonly MyParcelableCreator<Book> _creator = new MyParcelableCreator<Book>(parcel => new Book(parcel));

        //解包數據
        private Book(Parcel parcel)
        {
            BookId = parcel.ReadInt();
            BookName = parcel.ReadString();
            BookPrice = parcel.ReadDouble();
        }

        [ExportField("CREATOR")]
        public static MyParcelableCreator<Book> GetCreator()
        {
            return _creator;
        }
代碼和視頻在我上傳的CSDN資源中http://download.csdn.net/download/junshangshui/10121790
發佈了74 篇原創文章 · 獲贊 50 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章