Android中Parcelable的原理和使用方法

2023-05-16

Parcelable的简单介绍

介绍Parcelable不得不先提一下Serializable接口,Serializable是Java为我们提供的一个标准化的序列化接口,那什么是序列化呢?

进行Android开发的时候,无法将对象的引用传给Activities或者Fragments,我们需要将这些对象放到一个Intent或者Bundle里面,然后再传递。简单来说就是将对象转换为可以传输的二进制流(二进制序列)的过程,这样我们就可以通过序列化,转化为可以在网络传输或者保存到本地的流(序列),从而进行传输数据 ,那反序列化就是从二进制流(序列)转化为对象的过程.

Parcelable是Android为我们提供的序列化的接口,Parcelable相对于Serializable的使用相对复杂一些,但Parcelable的效率相对Serializable也高很多,这一直是Google工程师引以为傲的,有时间的可以看一下Parcelable和Serializable的效率对比 Parcelable vs Serializable 号称快10倍的效率

Android源码中的Parcelable

/**
     * Interface for classes whose instances can be written to
   * and restored from a {@link Parcel}.  Classes implementing the Parcelable
 * interface must also have a non-null static field called <code>CREATOR</code>
 * of a type that implements the {@link Parcelable.Creator} interface.
 * 
 * <p>A typical implementation of Parcelable is:</p>
 * 
 * <pre>
 * public class MyParcelable implements Parcelable {
 *     private int mData;
 *
 *       public int describeContents() {
 *         return 0;
 *     }
 *
 *     public void writeToParcel(Parcel out, int flags) {
 *         out.writeInt(mData);
 *     }
 *
 *     public static final Parcelable.Creator<MyParcelable> CREATOR
 *             = new Parcelable.Creator<MyParcelable>() {
 *         public MyParcelable createFromParcel(Parcel in) {
 *             return new MyParcelable(in);
 *         }
 *
 *         public MyParcelable[] newArray(int size) {
 *             return new MyParcelable[size];
 *         }
 *     };
 *     
 *     private MyParcelable(Parcel in) {
 *         mData = in.readInt();
 *     }
 * }</pre>
 */

通过源码中的介绍 可以知道,Parcelable接口的实现类是可以通过Parcel写入和恢复数据的,并且必须要有一个非空的静态变量 CREATOR,而且还给了一个例子,这样我们写起来就比较简单了,但是简单的使用并不是我们的最终目的,通过查看Android源码中Parcelable可以看出,Parcelable实现过程主要分为序列化,反序列化,描述三个过程,下面分别介绍下这三个过程。

Parcel的简介

在介绍之前我们需要先了解Parcel是什么?Parcel翻译过来是打包的意思,其实就是包装了我们需要传输的数据,然后在Binder中传输,也就是用于跨进程传输数据

简单来说,Parcel提供了一套机制,可以将序列化之后的数据写入到一个共享内存中,其他进程通过Parcel可以从这块共享内存中读出字节流,并反序列化成对象,下图是这个过程的模型。

Parcel可以包含原始数据类型(用各种对应的方法写入,比如writeInt(),writeFloat()等),可以包含Parcelable对象,它还包含了一个活动的IBinder对象的引用,这个引用导致另一端接收到一个指向这个IBinder的代理IBinder。
Parcelable通过Parcel实现了read和write的方法,从而实现序列化和反序列化

Parcelable中的三大过程介绍(序列化,反序列化,描述)

什么是序列化

序列化,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。

到这里,基本上关系都理清了,也明白简单的介绍和原理了,接下来在实现Parcelable之前,介绍下实现Parcelable的三大流程 .
 

我先把代码贴出来

public class Album implements Parcelable {

    /**
     * 负责反序列化
     */
    public static final Creator<Album> CREATOR = new Creator<Album>() {
        /**
         * 从序列化对象中,获取原始的对象
         * @param source
         * @return
         */
        @Override
        public Album createFromParcel(Parcel source) {
            return new Album(source);
        }

        /**
         * 创建指定长度的原始对象数组
         * @param size
         * @return
         */
        @Override
        public Album[] newArray(int size) {
            return new Album[0];
        }
    };



    private final String mId;
    private final String mCoverPath;
    private final String mDisplayName;
    private final long mCount;


    Album(String id, String coverPath, String displayName, long count) {
        mId = id;
        mCoverPath = coverPath;
        mDisplayName = displayName;
        mCount = count;
    }

    Album(Parcel source) {
        mId = source.readString();
        mCoverPath = source.readString();
        mDisplayName = source.readString();
        mCount = source.readLong();
    }

    /**
     * 描述
     * 返回的是内容的描述信息
     * 只针对一些特殊的需要描述信息的对象,需要返回1,其他情况返回0就可以
     *
     * @return
     */
    @Override
    public int describeContents() {
        return 0;
    }

    /**
     * 序列化
     *
     * @param dest
     * @param flags
     */
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mId);
        dest.writeString(mCoverPath);
        dest.writeString(mDisplayName);
        dest.writeLong(mCount);
    }

实现Parcelable的作用

1)永久性保存对象,保存对象的字节序列到本地文件中;

2)通过序列化对象在网络中传递对象;

3)通过序列化在进程间传递对象。

首先写一个类实现Parcelable接口,会让我们实现两个方法:

  • describeContents 描述
    其中describeContents就是负责文件描述.通过源码的描述可以看出,只针对一些特殊的需要描述信息的对象,需要返回1,其他情况返回0就可以
  • writeToParcel 序列化
    我们通过writeToParcel方法实现序列化,writeToParcel返回了Parcel,所以我们可以直接调用Parcel中的write方法,基本的write方法都有,对象和集合比较特殊下面单独讲,基本的数据类型除了boolean其他都有,Boolean可以使用int或byte存储

我们将上面的Album对象实现序列化,Album对象包含四个字段。

反序列化

反序列化需要定义一个CREATOR的变量,上面也说了具体的做法,这里可以直接复制Android给的例子中的,也可以自己定义一个(名字千万不能改),通过匿名内部类实现Parcelable中的Creator的接口

Parcelable的使用和实现

根据上面三个过程的介绍,Parcelable就写完了,就可以直接在Intent中传输了,可以自己写两个Activity传输一下数据试一下,其中一个putExtra另一个getParcelableExtra即可。

Parcelable中对象和集合的处理

import android.os.Parcel;
import android.os.Parcelable;

import java.util.ArrayList;


public class ParcelDemo implements Parcelable {

    private int count;
    private String name;
    private ArrayList<String> tags;
    private Book book;
    // ***** 注意: 这里如果是集合 ,一定要初始化 *****
    private ArrayList<Book> books = new ArrayList<>();


    /**
     * 反序列化
     *
     * @param in
     */
    protected ParcelDemo(Parcel in) {
        count = in.readInt();
        name = in.readString();
        tags = in.createStringArrayList();

        // 读取对象需要提供一个类加载器去读取,因为写入的时候写入了类的相关信息
        book = in.readParcelable(Book.class.getClassLoader());


        //读取集合也分为两类,对应写入的两类

        //这一类需要用相应的类加载器去获取
        in.readList(books, Book.class.getClassLoader());// 对应writeList


        //这一类需要使用类的CREATOR去获取
        in.readTypedList(books, Book.CREATOR); //对应writeTypeList

        //books = in.createTypedArrayList(Book.CREATOR); //对应writeTypeList


        //这里获取类加载器主要有几种方式
        getClass().getClassLoader();
        Thread.currentThread().getContextClassLoader();
        Book.class.getClassLoader();


    }

    public static final Creator<ParcelDemo> CREATOR = new Creator<ParcelDemo>() {
        @Override
        public ParcelDemo createFromParcel(Parcel in) {
            return new ParcelDemo(in);
        }

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

    /**
     * 描述
     *
     * @return
     */
    @Override
    public int describeContents() {
        return 0;
    }

    /**
     * 序列化
     *
     * @param dest
     * @param flags
     */
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(count);
        dest.writeString(name);
        //序列化一个String的集合
        dest.writeStringList(tags);
        // 序列化对象的时候传入要序列化的对象和一个flag,
        // 这里的flag几乎都是0,除非标识当前对象需要作为返回值返回,不能立即释放资源
        dest.writeParcelable(book, 0);

        // 序列化一个对象的集合有两种方式,以下两种方式都可以


        //这些方法们把类的信息和数据都写入Parcel,以使将来能使用合适的类装载器重新构造类的实例.所以效率不高
        dest.writeList(books);


        //这些方法不会写入类的信息,取而代之的是:读取时必须能知道数据属于哪个类并传入正确的Parcelable.Creator来创建对象
        // 而不是直接构造新对象。(更加高效的读写单个Parcelable对象的方法是:
        // 直接调用Parcelable.writeToParcel()和Parcelable.Creator.createFromParcel())
        dest.writeTypedList(books);


    }
}

Book类,需要先实现Parcelable,实现步骤就不贴出来了,和普通的对象一样,实现三个过程。

import android.os.Parcel;
import android.os.Parcelable;


public class Book implements Parcelable {

    protected Book(Parcel in) {
    }

    public static final Creator<Book> CREATOR = new Creator<Book>() {
        @Override
        public Book createFromParcel(Parcel in) {
            return new Book(in);
        }

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

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
    }
}

写入和读取集合有两种方式,
一种是写入类的相关信息,然后通过类加载器去读取, –> writeList | readList
二是不用类相关信息,创建时传入相关类的CREATOR来创建 –> writeTypeList | readTypeList | createTypedArrayList
第二种效率高一些
一定要注意如果有集合定义的时候一定要初始化 like this –>
public ArrayList<T> demo = new ArrayList<>();

举个详细的例子:

class MessageFilter() : Parcelable{

    var sender: List<FilterSender>? = null

    var messageType: FilterMessageType? = null

    var time: FilterTime? = null

    //读数据进行恢复
    constructor(parcel: Parcel) : this() {
        this.sender = mutableListOf()
        parcel.readList(sender, FilterSender.javaClass.classLoader)
        messageType = parcel.readParcelable(FilterMessageType.javaClass.classLoader)
        time = parcel.readParcelable(FilterTime.javaClass.classLoader)
    }

    //写数据进行保存
    override fun writeToParcel(dest: Parcel?, flags: Int) {
        dest?.writeList(sender)
        dest?.writeParcelable(messageType, Parcelable.PARCELABLE_WRITE_RETURN_VALUE)
        dest?.writeParcelable(time, Parcelable.PARCELABLE_WRITE_RETURN_VALUE)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<MessageFilter> {
        override fun createFromParcel(parcel: Parcel): MessageFilter {
            return MessageFilter(parcel)
        }

        override fun newArray(size: Int): Array<MessageFilter?> {
            return arrayOfNulls(size)
        }
    }
}

//涉及到的相关类都需要实现Parcelable接口
data class FilterSender(val type: String, val id: String): Parcelable {

    constructor(parcel: Parcel) : this(
        parcel.readString(),
        parcel.readString())

    override fun writeToParcel(dest: Parcel?, flags: Int) {
        dest?.writeString(type)
        dest?.writeString(id)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<FilterSender> {
        override fun createFromParcel(parcel: Parcel): FilterSender {
            return FilterSender(parcel)
        }

        override fun newArray(size: Int): Array<FilterSender?> {
            return arrayOfNulls(size)
        }
    }
}

Parcelable和Serializable的区别和比较

Parcelable和Serializable都是实现序列化并且都可以用于Intent间传递数据,Serializable是Java的实现方式,可能会频繁的IO操作,所以消耗比较大,但是实现方式简单 Parcelable是Android提供的方式,效率比较高,但是实现起来复杂一些 , 二者的选取规则是:内存序列化上选择Parcelable, 存储到设备或者网络传输上选择Serializable(当然Parcelable也可以但是稍显复杂)

选择序列化方法的原则

1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。

2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。

3)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,但此时还是建议使用Serializable 。

延伸:

下面介绍下ParcelableSerializable的作用、效率、区别及选择。

1、作用

Serializable的作用是为了保存对象的属性到本地文件、数据库、网络流、rmi以方便数据传输,当然这种传输可以是程序内的也可以是两个程序间的。而Android的Parcelable的设计初衷是因为Serializable效率过慢,为了在程序内不同组件间以及不同Android程序间(AIDL)高效的传输数据而设计,这些数据仅在内存中存在,Parcelable是通过IBinder通信的消息的载体。

从上面的设计上我们就可以看出优劣了。

2、效率及选择

Parcelable的性能比Serializable好,在内存开销方面较小,所以在内存间数据传输时推荐使用Parcelable,如activity间传输数据,而Serializable可将数据持久化方便保存,所以在需要保存或网络传输数据时选择Serializable,因为android不同版本Parcelable可能不同,所以不推荐使用Parcelable进行数据持久化。

3、编程实现

对于Serializable,类只需要实现Serializable接口,并提供一个序列化版本id(serialVersionUID)即可。Parcelable则需要实现writeToParceldescribeContents函数以及静态的CREATOR变量,实际上就是将如何打包和解包的工作自己来定义,而序列化的这些操作完全由底层实现。

4、高级功能上

Serializable序列化不保存静态变量,可以使用Transient关键字对部分字段不进行序列化,也可以覆盖writeObjectreadObject方法以实现序列化过程自定义。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android中Parcelable的原理和使用方法 的相关文章

  • linux环境下如何卸载一路赚钱(yilu/mservice)

    一 删除定时任务 xff1a sudo crontab l u root 2 gt dev null grep v mservice sudo crontab u root 二 停止服务 对于ubuntu以及centos 7的用户 serv
  • 【图像处理】多帧降噪算法

    本文参考论文 xff1a Denoising image sequences does not require motion estimation http citeseerx ist psu edu viewdoc download do
  • VINS-Fusion初始化------IMU与Camera外参旋转标定,IMU角速度偏置标定,重力向量、单目尺度标定

    本文基于VINS Fusion解释VIO系统的初始化 xff0c 包括在线标定IMU Camera的外参旋转 xff0c IMU角速度偏置 xff0c 重力方向 xff0c 单目尺度 单目初始化相比于双目 xff0c 多一个构建SFM问题优
  • 视觉惯性里程计Visual–Inertial Odometry(VIO)概述

    本文主要来自于博客园关于知乎的讨论 链接如下 xff1a Visual Inertial Odometry VIO
  • IBM Was 打补丁记录

    0 拷贝解压ifph52925升级包 通过FTP工具 xff0c 把压缩包传到服务器 xff0c unzip d test01 9 0 0 0 ws was ifph52925 zip 1 停掉was 服务 ps ef grep was k
  • 阿里云服务器远程桌面安装

    阿里云服务器远程桌面安装 环境说明 xff1a CentOS 8 3 一 安装桌面环境 root用户下执行命令 yum grouplist yum groupinstall y span class token string 34 Serv
  • STM32与Futaba遥控器进行S.Bus的通讯程序

    Futaba xff08 日本双叶电子工业 xff0c 戏称 扶他爸 xff09 的遥控器用航模中使用较为广泛的遥控器 S Bus则是Futaba公司提出的舵机控制总线 本篇博文主要以T6K为对象 xff0c 介绍STM32与S Bus协议
  • c++ 小知识点记录

    数据类型 数据类型类型说明符位数取值范围整型int32 2147483648 43 2147483647短整型short int16 32767 43 32768长整型long int32 2147483648 43 2147483647单
  • makefile简明教程

    makefile 主要是编译就是用来编译源文件的 一个工程中的源文件不计其数 xff0c 其按类型 功能 模块分别放在若干个目录中 xff0c makefile定义了一系列的规则来指定哪些文件需要先编译 xff0c 哪些文件需要后编译 xf
  • SLAM 定位和导航

    码一篇文章后面看 xff1a gt https www cnblogs com hiram zhang p 10416081 html
  • 开发工具及环境配置

    一 jdk下载 安装与环境变量配置 1 下载 xff08 1 xff09 打开下载网址Java Downloads Oracle或直接搜索Oracle JDK下载 xff08 2 xff09 根据电脑系统 xff08 win linux等
  • ros2中 用python编写action 的service和client

    第一步 xff1a 定义请求反馈的变量 主要参考官网网站 xff1a Writing an action server and client C 43 43 ROS 2 Documentation Rolling documentation
  • TX2自动刷机视频教程

    TX2自动刷机视频教链接https v qq com x page b0515967lbr html
  • python 中 机器学习算法 --决策树

    文章目录 思维脑图3 1 2 用pandas加载数据集3 1 3 清洗数据集现在计算这些的实际值主队和客队最后一场比赛赢了吗 xff1f 3 2 决策树3 2 1 决策树中的参数3 2 2 决策树的使用 3 3 体育赛事结果预测 3 4 随
  • 结合OPENNI2,Aruco与OPENCV进行视觉定位

    前些时间写了篇文章把我在做这个项目中遇到的问题以及思路说了一下 传送门 http jcs130 iteye com blog 2185533 在上篇文章的思路下作了实现 已经达到了教授的要求 nbsp 首先第一步检测四个角的坐标 经试验 在
  • oracle 备份表

    一 PL SQL备份 xff08 1 xff09 打开PL SQL xff08 2 xff09 在Tools下选择Export Tables xff08 3 xff09 在列表中找到想要备份的表 xff0c 右键选择Export Data
  • 概率机器人——机器人环境交互

    状态 环境特征以状态表征 xff0c 状态是所有会对未来产生影响的机器人及其环境的所有方面因素 概率生成法则 状态转移概率 xff0c 根据条件独立 xff0c 可得到 xff1a 它指出了环境状态作为机器人控制ut的函数是如何随着事件变化
  • cmake、catkin知识点点点点

    GNU GPL GCC G 43 43 GNU xff1a 一个计划 运动 xff0c 目标是创建一套完全自由的操作系统 GPL xff1a GNU通用公共许可协议 xff0c 广泛应用的自由软件许可证 xff0c linux发行时选择了G
  • 大陆ARS-408XX毫米波雷达

    前期准备 xff1a 使用创芯科技CAN分析仪 xff0c 大陆ARS 408XX毫米波雷达 xff0c 电源 xff1a 12DC 24DC 一 安装USBCAN 驱动 1 打开设备管理器 2 鼠标右键 更新驱动 3 手动查找 4 找到自
  • 书籍记录了我技术的成长历程

    看到了有奖征文的内容 xff0c 觉得内容很好 xff0c 很想把自己读过的技术书籍整理一下 xff0c 给自己的技术类图书梳理一下思绪 xff0c 觉得是一件很值得做的事情 xff0c 花了一点时间整理了下 xff0c 与各位博友分享 x

随机推荐

  • 2021-11-01 福州高速公路定位测试有感

    室内定位测试大大小小经历了数十次 xff0c 这次福州的高速公路隧道测试感触颇多 第一 强大的自驱力 xff1a 从测试安排出差伊始 xff0c 团队成员主动提出听从安排 xff0c 积极配合 xff1b 讨论测试计划和方案时 xff0c
  • New Timeline的Toolbar样式设计

    最近在做新版的Timeline xff0c Toolbar Menu 的功能基本完成 xff0c 因此把截图拿出来与各位博友分享一下 新版Timeline HTML版本 主页面 xff1a 这次主要讲解一下Toolbar Menu 的功能
  • VS改大小写的快捷键

    改成小写 xff1a Ctrl 43 U 改成大写 xff1a Ctrl 43 Shift 43 U 记得要选中要修改的一段英文
  • 我的2013,我的CSDN

    2013年是我写CSDN博客的第三个年头了 xff0c 这一年我的博客访问量直线上升 xff0c 这一年我知道了什么是博客专栏 xff0c 这一年我知道如何申请CSDN专家 虽然失败了 xff0c 这一年我从CSDN博客收获了很多很多 xf
  • SQL两表之间:根据一个表的字段更新另一个表的字段

    1 写法轻松 xff0c 更新效率高 xff1a update table1 set field1 61 table2 field1 field2 61 table2 field2 from table2 where table1 id 6
  • 多边形面积计算公式

    function polygonArea points var i j var area 61 0 for i 61 0 i lt points length i 43 43 j 61 i 43 1 points length area 4
  • 《最重要的事,只有一件》读书笔记

    背景 每天都在忙忙碌碌中度过 xff0c 感觉到很累 xff0c 但仔细思考一下好像也没有收获 仔细想一想 xff0c 在每天之中 xff0c 大脑主动或被动的接受了太多的信息 xff0c 如果没有给信息分出轻重缓急 xff0c 整理归类
  • table合并单元格colspan和rowspan

    span style font family none code span style background color rgb 255 255 0 span style font family none code span style f
  • jQuery两个稳定版本的比较

    jquery历经了多个版本的更新 xff0c 版本上的比较貌似没什么必要性 xff0c 一般来说新的版本会比旧的版本各方面都略有提升 xff0c 但由于新版中增加了各种新的功能 xff0c 难免会引起bug的发生 评估一个版本是否适合当前开
  • 室内定位简介

    室内定位定义 xff1a 室内定位是指在室内环境中实现位置定位 xff0c 主要采用无线通讯 基站定位 惯导定位等多种技术集成形成一套室内位置定位体系 xff0c 从而实现人员 物体等在室内空间中的位置监控 室内定位需求 xff1a 在室外
  • 命令行提交代码到gitLab服务器

    1 创建项目 xff0c 前提是gitLab服务器已经搭建完成 xff0c 在gitLab个人账户下创建一个项目 xff0c 项目名称自己定义 xff0c 如图 xff1a 2 拷贝本地代码到指定目录 xff0c 一般自己创建一个固定的代码
  • VS 附加到进程调试技巧

    有些时候碰到自己开发的程序嵌入到别人的框架中 xff0c 而在接口的地方出了问题 xff0c 而又不方便将自己的模快加入到别人的工程中 有很多相关的文件 xff0c 还有mster页面等 xff0c 这个时候VS的附加到进程调试变得不可或缺
  • Request和Response详解

    Request 和 Response 对象起到了服务器与客户机之间的信息传递作用 Request 对象用于接收客户端浏览器提交的数据 xff0c 而 Response 对象的功能则是将服务器端的数据发送到客户端浏览器 一 Request对象
  • 人最宝贵的东西是生命

    钢铁是怎样炼成的 人最宝贵的东西是生命 生命属于人只有一次 一个人的生命是应该这样度过的 当他回首往事的时候 他不会因虚度年华而悔恨 也不会因碌碌无为而羞耻 这样在临死的时候 他才能够说 39 我的生命和全部的经历 都献给世界上最壮丽的事业
  • 树莓派卡在开机界面循环要求输入密码,提示cannot currently show the desktop

    这个必须得记录下来 xff0c 太坑了 昨天树莓派用着好好的 xff0c 突然就拷贝ssh拷贝东西进去拷贝不成功 xff0c VNC登陆图形界面 xff0c 输入密码后又循环弹出输入密码解密 xff0c 还提示 cannot current
  • FreeRTOS----debug之任务的挂起和恢复实验,任务无法切换

    任务的挂起和恢复 debug xff1a 背景 xff1a 有两个Task Task1为LED闪烁任务 Task2为挂起恢复LED任务 调试程序遇到的问题 xff1a LED灯闪烁任务不能正常执行 一直常亮 原因 xff1a LED闪烁任务
  • 提高IT运维效率,深度解读京东云AIOps落地实践(异常检测篇)

    基于深度学习对运维时序指标进行异常检测 xff0c 快速发现线上业务问题 时间序列的异常检测是实际应用中的一个关键问题 xff0c 尤其是在 IT 行业 我们没有采用传统的基于阈值的方法来实现异常检测 xff0c 而是通过深度学习提出了一种
  • Android getResources的作用和需要注意点

    今天做一个Android的文件管理器 xff0c 里面用到很多的地方用到了getResources Drawable currentIcon 61 null currentIcon 61 getResources getDrawable R
  • Mac OS X 的包管理器 HomeBrew

    Homebrew 是最简单和灵活的方式 xff0c 用来在 Mac OS X 安装 Linux 工具包 Homebrew 国内高速安装脚本 xff1a HomebrewCN Homebrew 国内安装脚本 安装过程很简单 xff1a rub
  • Android中Parcelable的原理和使用方法

    Parcelable的简单介绍 介绍Parcelable不得不先提一下Serializable接口 xff0c Serializable是Java为我们提供的一个标准化的序列化接口 那什么是序列化呢 进行Android开发的时候 xff0c