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

猜你喜欢

转载自blog.csdn.net/junshangshui/article/details/78553905