zoukankan      html  css  js  c++  java
  • Android中的Parcel机制 实现Bundle传递对象

    Android中的Parcel机制
        实现了Bundle传递对象
        使用Bundle传递对象,首先要将其序列化,但是,在Android中要使用这种传递对象的方式需要用到Android Parcel机制,即,Android实现的轻量级的高效的对象序列化和反序列化机制。

        JAVA中的Serialize机制,译成串行化、序列化……,其作用是能将数据对象存入字节流当中,在需要时重新生成对象。主要应用是利用外部存储设备保存对象状态,以及通过网络传输对象等。
        
        Android中的新的序列化机制
            在Android系统中,定位为针对内存受限的设备,因此对性能要求更高,另外系统中采用了新的IPC(进程间通信)机制,必然要求使用性能更出色的对象传输方式。在这样的环境下,
            Parcel被设计出来,其定位就是轻量级的高效的对象序列化和反序列化机制。
            Android中序列化有以下几个特征:
            1. 整个读写全是在内存中进行,所以效率比JAVA序列化中使用外部存储器会高很多;
            2. 读写时是4字节对齐的
            3. 如果预分配的空间不够时,会一次多分配50%;
            4. 对于普通数据,使用的是mData内存地址,对于IBinder类型的数据以及FileDescriptor使用的是mObjects内存地址。后者是通过flatten_binder()和unflatten_binder()实现的,目的是反序列化时读出的对象就是原对象而不用重新new一个新对象。

    package com.parcel.main;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.graphics.Color;
    import android.graphics.drawable.Drawable;
    import android.os.Bundle;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.TextView;
    
    public class MyTestParcelActivity extends Activity {
    
        public final static int Sub_Main = 1;
        public final static int Sub_2_Main = 2;
    
        private Button setSubMain;
        private Button setSub2Main;
        private TextView mTextView;
    
        private Drawable defDrawable;
        private MyParcel mMyParcel = new MyParcel();
        private BinderMyParcel mBinderMyParcel = new BinderMyParcel();
    
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
    
            initComponent();
        }
    
        private void initComponent() {
            setSubMain = (Button) findViewById(R.id.btn01);
            if (setSubMain != null) {
                setSubMain.setOnClickListener(setSubMainXML);
            }
    
            setSub2Main = (Button) findViewById(R.id.btn04);
            if (setSub2Main != null) {
                setSub2Main.setOnClickListener(setSub2MainXML);
            }
    
            mTextView = (TextView) findViewById(R.id.main_tv);
            defDrawable = mTextView.getBackground();
        }
    
        private View.OnClickListener setSubMainXML = new OnClickListener() {
    
            @Override
            public void onClick(View v) {
                Intent mIntent = new Intent();
                if (mMyParcel != null) {
                    mMyParcel.setColor(Color.RED);
                    mIntent.putExtra("MyColor", mMyParcel);
                }
                mIntent.setClass(MyTestParcelActivity.this,
                        SubMyTestParcelActivity.class);
    
                mTextView.setBackgroundDrawable(defDrawable);
    
                startActivityForResult(mIntent, Sub_Main);
            }
        };
        private View.OnClickListener setSub2MainXML = new OnClickListener() {
    
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                if (mBinderMyParcel != null) {
                    mBinderMyParcel.setColor(Color.MAGENTA);
                    intent.putExtra("BinderMyColor", mBinderMyParcel);
                }
                intent.setClass(MyTestParcelActivity.this,
                        Sub2MyTestParcelActivity.class);
    
                mTextView.setBackgroundDrawable(defDrawable);
    
                startActivityForResult(intent, Sub_2_Main);
            }
        };
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == RESULT_OK) {
                if (requestCode == Sub_Main) {
                    if (data.hasExtra("MyColor")) {
                        /**
                         * color=data.getParcelableExtra("MyColor"),
                         * 这说明反序列化后是一个新的MyColor对象
                         * 
                         * 如果数据本身是IBinder类型,那么反序列化的结果就是原对象,而不是新建的对象
                         */
                        mMyParcel = data.getParcelableExtra("MyColor");
                        ((TextView) findViewById(R.id.main_tv))
                                .setTextColor(mMyParcel.getColor());
                    }
                } else if (requestCode == Sub_2_Main) {
                    if (data.hasExtra("BinderMyColor")) {
                        ((TextView) findViewById(R.id.main_tv))
                                .setBackgroundColor(mBinderMyParcel.getColor());
                    }
                }
            }
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            return super.onTouchEvent(event);
        }
    
    }

    使用非binder类型代码

    package com.parcel.main;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.graphics.Color;
    import android.graphics.drawable.Drawable;
    import android.os.Bundle;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.TextView;
    
    public class SubMyTestParcelActivity extends Activity implements
            OnClickListener {
    
        private Button setSub2XML;
        private TextView mTextView;
        private MyParcel myColor;
        
        private Drawable defDrawable;
        
    
        /** Called when the activity is first created. */
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            setContentView(R.layout.submain);
    
            setSub2XML = (Button) findViewById(R.id.btn02);
            setSub2XML.setOnClickListener(this);
    
            mTextView = (TextView)findViewById(R.id.sub_tv);
            defDrawable = mTextView.getBackground();
            
            Intent intent = getIntent();
            if (intent != null) {
                if (intent.hasExtra("MyColor")) {
                    myColor = intent.getParcelableExtra("MyColor");
                    mTextView.setBackgroundColor(myColor.getColor());
                }
            }
        }
    
        @Override
        protected void onStart() {
            super.onStart();
        }
    
        @Override
        protected void onRestart() {
            super.onRestart();
        }
    
        @Override
        protected void onResume() {
            super.onResume();
        }
    
        @Override
        protected void onPause() {
            super.onPause();
        }
    
        @Override
        protected void onStop() {
            super.onStop();
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            return super.onTouchEvent(event);
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
            case R.id.btn02:
                Intent mIntent = new Intent(getApplicationContext(),
                        Sub2MyTestParcelActivity.class);
                if (myColor != null) {
                    myColor.setColor(Color.GREEN);
                    mIntent.putExtra("MyColor", myColor);
                }
    
                mTextView.setBackgroundDrawable(defDrawable);
                setResult(RESULT_OK, mIntent);
                finish();
                break;
    
            default:
                break;
            }
        }
    
    }

    使用binder类型代码

    package com.parcel.main;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.graphics.Color;
    import android.graphics.drawable.Drawable;
    import android.os.Bundle;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.TextView;
    
    public class Sub2MyTestParcelActivity extends Activity implements
            OnClickListener {
    
        private Button setMainXML;
        private TextView mTextView;
        private BinderMyParcel myColor;
    
        private Drawable defDrawable;
    
        /** Called when the activity is first created. */
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            setContentView(R.layout.sub2main);
    
            setMainXML = (Button) findViewById(R.id.btn03);
            setMainXML.setOnClickListener(this);
    
            mTextView = (TextView) findViewById(R.id.sub_tv);
            defDrawable = mTextView.getBackground();
    
            Intent intent = getIntent();
            if (intent != null) {
                if (intent.hasExtra("BinderMyColor")) {
                    myColor = intent.getParcelableExtra("BinderMyColor");
                    mTextView.setBackgroundColor(myColor.getColor());
                }
            }
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
            case R.id.btn03:
                Intent mIntent = new Intent(getApplicationContext(),
                        MyTestParcelActivity.class);
                if (myColor != null) {
                    myColor.setColor(Color.WHITE);
                    mIntent.putExtra("BinderMyColor", myColor);
                }
    
                mTextView.setBackgroundDrawable(defDrawable);
                setResult(RESULT_OK, mIntent);
                finish();
                break;
    
            default:
                break;
            }
        }
    
    }

     非Binder类型的Parcel,实现Parcelable接口即可:

    package com.parcel.main;
    
    import android.graphics.Color;
    import android.os.Parcel;
    import android.os.Parcelable;
    
    public class MyParcel implements Parcelable {
        private int color = Color.BLACK;
    
        public int getColor() {
            return color;
        }
    
        public void setColor(int color) {
            this.color = color;
        }
    
        public MyParcel() {
            color = Color.BLACK;
        }
    
        public MyParcel(Parcel in) {
            color = in.readInt();
        }
    
        @Override
        public int describeContents() {
            return 0;
        }
    
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(color);
        }
    
        public static final Parcelable.Creator<MyParcel> CREATOR = new Parcelable.Creator<MyParcel>() {
    
            public MyParcel createFromParcel(Parcel in) {
                return new MyParcel(in);
            }
    
            public MyParcel[] newArray(int size) {
                return new MyParcel[size];
            }
        };
    
    }

     对于Binder类型,首先要实现一个Binder接口(其,最主要的区别在于反序列化仍然是原来的对象,而非Binder类型的反序列化并不是原来的对象,所以在MainActivity中的onActivityResult方法中会出现mMyParcel = data.getParcelableExtra("MyColor")的写法):

    package com.parcel.main;
    
    import android.os.Binder;
    
    public class BinderData extends Binder {
    
        public int color;
    
    }

     其次再实现Parcelable接口:

    package com.parcel.main;
    
    import android.graphics.Color;
    import android.os.Parcel;
    import android.os.Parcelable;
    
    public class BinderMyParcel implements Parcelable {
    
        private BinderData data = new BinderData();
    
        public BinderMyParcel() {
            data.color = Color.BLUE;
        }
    
        public BinderMyParcel(Parcel in) {
            data = (BinderData) in.readValue(BinderData.class.getClassLoader());
        }
    
        public void setColor(int color) {
            data.color = color;
        }
    
        public int getColor() {
            return data.color;
        }
    
        @Override
        public int describeContents() {
            return 0;
        }
    
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeValue(data);
        }
    
        public static final Parcelable.Creator<BinderMyParcel> CREATOR = new Creator<BinderMyParcel>() {
    
            @Override
            public BinderMyParcel[] newArray(int size) {
                return new BinderMyParcel[size];
            }
    
            @Override
            public BinderMyParcel createFromParcel(Parcel source) {
                return new BinderMyParcel(source);
            }
        };
    }

    三个XML:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <TextView android:id="@+id/main_tv" android:layout_width="fill_parent"
            android:layout_height="wrap_content" android:text="@string/main_activity" />
        <LinearLayout android:orientation="horizontal"
            android:layout_width="wrap_content" android:layout_height="wrap_content">
            <Button android:text="SetSubMainXML" android:id="@+id/btn01"
                android:layout_width="wrap_content" android:layout_height="wrap_content" />
            <Button android:id="@+id/btn04" android:layout_height="wrap_content"
                android:layout_width="wrap_content" android:text="SetSub2MainXML" />
        </LinearLayout>
    
    </LinearLayout>
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <TextView android:id="@+id/sub_tv" android:layout_width="fill_parent"
            android:layout_height="wrap_content" android:text="@string/sub_activity" />
        <Button android:text="setMainXML" android:id="@+id/btn02"
            android:layout_width="wrap_content" android:layout_height="wrap_content" />
    </LinearLayout>
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <TextView android:id="@+id/sub_tv" android:layout_width="fill_parent"
            android:layout_height="wrap_content" android:text="@string/sub2_activity" />
        <Button android:text="setMainXML" android:id="@+id/btn03"
            android:layout_width="wrap_content" android:layout_height="wrap_content" />
    </LinearLayout>
  • 相关阅读:
    Windows10:家庭版如何设置开机自动登录
    Windows10:常用快捷键(转载)
    Windows10:找回传统桌面的系统图标
    MyBatis之XML映射文件详解
    MyBatis之核心对象及配置文件详解
    Java用Jsoup登录网站,以JSON格式提交(POST)数据,处理JSON格式返回结果,并将处理结果保存到系统剪贴板
    (转)总结.Net下后端的几种请求方式(WebClient、WebRequest、HttpClient)
    jvisualvm.exe 查看堆栈分配
    Hutool 常用的工具类和方法
    StringRedisTemplate 常用方法
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/5693564.html
Copyright © 2011-2022 走看看