Android 序列化 Parcelable

本文链接: Android 序列化 -- Parcelable     

Android 序列化 -- Parcelable

Oct 12th, 2013 

序列化

  • 为什么要序列化?

    1. 永久性保存对象,保存对象的 字节序列 到本地文件中
    2. 通过序列化在网络中传递对象。
    3. 通过序列化在进程间传递对象。
  • 序列化:将数据结构或者对象 state 转换成可以存储的格式(如文件,memory buffer,或者在网络上传输),之后再在相同的计算机或者不同的计算机环境中恢复。当生成的bits序列按serilization 格式被重新读出时,它可以创建一个语义唯一(semantically identical) 的原始对象的克隆。
    序列化的过程也被叫做 deflating 或者 marshalling 。相反的操作则叫做 deserialization (也叫做 inflating 或者 unmarshalling )。

  • 序列化格式:

    • XML , 有常规的xml(human readable text-based encoding,可以用文本编辑器打开) 和 Binary xml。在20世纪,XML经常被用于Ajax网站应用的客户端和服务器之间的数据结构的异步传输。
    • JSON, 是一个较之于XML 更加轻量级的序列化格式,JSON 也普遍被用于web 应用的C/S通讯, JSON 基于JavaScript 语法格式,不过也支持其他编程语言。
    • YAML, 高效的JSON超集,包括了一些特性使得它拥有更加强大的序列化功能,对人更加友好,拥有更好的潜在兼容性。在看jekyll 时发现了这个: YAML Ain’t Markup Language
    • MAC OS X Cocoa..
  • 编程语言支持

    • Java — java.io.Serializable interface …

参考:wiki百科 Serilization


安卓序列化

  • Android 序列化的两种方法
    1. Serializable 接口
    2. Parcelable 接口
实现 Parcelable 接口实现安卓序列化
  • implemnts Parceable
  • 需要序列化的类必须有一个 static field : CREATEOR ( CREATEOR 是一个实现了Parcelable.Creator 接口的对象)
代码示例:
  • 目的: 实现 Parcelable 接口用于进程间(?)传递对象。程序的运行流程是: 点击MyParcelable 的button ,启动ActivityB 并将一个Person 实例传递过去,然后再再ActivityB 中将收到的Person 对象的信息显示在Textview 上。

  • 主要结构: 一个Project, 建两个Activity— MyParcelable,ActivityB 。 MyParcelable 布局中添加一个button, 为Button 添加属性:
    android:onClick=“onClick”
    ActivityB 的xml 布局里添加一个TextView。
    一个 Person 类实现 Parcelable 接口。

  • 代码:

MyParcelable :

public class MyParcelable extends Activity implements OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.btn1:
            Intent intent = new Intent();
            intent.setClass(this, ActivityB.class);
            Bundle extras = new Bundle();
            extras.putParcelable(Person.PARCELABLE_KEY, new Person("Libelosophy", 100));
            intent.putExtras(extras);
            startActivity(intent);
        }
    }
}


ActivityB :

public class ActivityB extends Activity {
    private TextView tv = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_activity_b);
        tv = (TextView) findViewById(R.id.textview);

        Person person = getIntent().getExtras().getParcelable(Person.PARCELABLE_KEY);
        String person_info = "Name: " + person.getmName() 
                                + "\n Age: " + person.getmAge();

        tv.setText(person_info);

        }       
}


Person :

public class Person  implements Parcelable {
    public static final String PARCELABLE_KEY = "PersonParcelableObject";

    private String mName;
    private int mAge;


    public String getmName() {
        return mName;
    }

    public void setmName(String mName) {
        this.mName = mName;
    }

    public int getmAge() {
        return mAge;
    }

    public void setmAge(int mAge) {
        this.mAge = mAge;
    }

    Person(String name, int age) {
        setmName(name);
        setmAge(age);
    }



    private Person(Parcel in) {

        setmName(in.readString());
        setmAge(in.readInt());
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(getmName());
        dest.writeInt(getmAge());
    }

    public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {

        @Override
        public Person createFromParcel(Parcel source) {

            return new Person(source);
        }

        @Override
        public Person[] newArray(int size) {

            return new Person[size];
        }
    };

}


运行结果: 如预期。

实例

project简单介绍:OIFileManager一个文件浏览器。FileHolder 类包含文件基本信息(文件,扩展名…),FileHolderAdapter 是用来关联View 和 file列表数据的Adapter,FileListFragment 则是界面及执行体。

首先看看FileHolder 里面的代码,FileHolder 实现了 Parcelable 以支持序列化 ,比较熟悉了:

// FileHolder.java 不完整代码
public class FileHolder implements Parcelable, Comparable<FileHolder> {
    private File mFile;
    private Drawable mIcon;
    private String mMimeType = "";
    private Context mContext;
    private String mExtension;

    // 。。。。。。

    // 用 Parcel 中保存的对象来够造FileHolder对像 的构造函数 
    public FileHolder(Parcel in){
        mFile = new File(in.readString());
        mMimeType = in.readString();
        mExtension = in.readString();
    }

    // 序列化

    @Override
    public int describeContents() {
        return 0;
    }

    // 可以看见向 Parcel 只写入了三条String : 文件路径, Mimetype, 扩展名
    // [可以直接用 dest.writeSerializable() 将mFile写到Parcel] ? [怎么写] : [为什么不这么用]
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mFile.getAbsolutePath());
        dest.writeString(mMimeType);
        dest.writeString(mExtension);
    }

    public static final Parcelable.Creator<FileHolder> CREATOR = new Parcelable.Creator<FileHolder>() {
        public FileHolder createFromParcel(Parcel in) {
            return new FileHolder(in);
        }

        public FileHolder[] newArray(int size) {
            return new FileHolder[size];
        }
        };
}

在 FileListFragment 中 :

// FileListFragment.java 不完整代码, 函数也被删去了部分代码

private static final String INSTANCE_STATE_PATH = "path";
private static final String INSTANCE_STATE_FILES = "files";
private static final String TAG = "FileListFragment";
File mPreviousDirectory = null;


protected FileHolderListAdapter mAdapter;
protected DirectoryScanner mScanner; //目录扫描器,扫描目录文件列表并将列表作为消息发送的线程
protected ArrayList<FileHolder> mFiles = new ArrayList<FileHolder>();
private String mPath;
private String mFilename;

private ViewFlipper mFlipper;
private File mCurrentDirectory;

// onSaveInstanceState(Bundle) 回调函数用来保存fragment 的state 用于重新构造fragment, 
//  bundle 所放的state 在函数onCreate , onCreateView onActivityCreate 中可用 
// 当然还应该有onViewCreated ,
@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    outState.putString(INSTANCE_STATE_PATH, mPath); 


    // ArrayList 实现了 Serialization 接口, FileHolder 实现了Parcelable 接口。
    // Inserts a List of Parcelable values into the mapping of this Bundle
    outState.putParcelableArrayList(INSTANCE_STATE_FILES, mFiles); // 就这个调用了。
}

// 
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {

    // 删掉了一些无关 主题的代码

    // Get arguments
    if (savedInstanceState == null) {
        // 如果没有保存过Fragment 的 实例, 则说明是第一次,从启动时的设置参数中取出path 和filename
        mPath = getArguments().getString(FileManagerIntents.EXTRA_DIR_PATH);


        mFilename = getArguments().getString(
                FileManagerIntents.EXTRA_FILENAME);
    } else { // 否则直接从保存的bundle 中恢复state
        mPath = savedInstanceState.getString(INSTANCE_STATE_PATH);
        mFiles = savedInstanceState
                .getParcelableArrayList(INSTANCE_STATE_FILES);
    }
    pathCheckAndFix();
    renewScanner();

    // 设置数据源,及关联到 Fragment ( ? 一个 ListView 在哪?? )
    Log.v(TAG, "设置数据源, FileHolderAdapter关联到 FileListFragment");
    mAdapter = new FileHolderListAdapter(mFiles, getActivity());

    setListAdapter(mAdapter);
    mScanner.start();

}

Oct 12th, 2013

另看见一篇写java 序列化的文章: 深入理解 Java 序列化



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值