简体   繁体   English

在android中分配对象以从一个活动转移到另一个活动

[英]Parceling objects in android to transfer from one activity to another

Recently an interviewer asked me a very tricky question. 最近一位采访者问我一个非常棘手的问题。 There are several parts of the question. 这个问题有几个部分。

  1. Why (question is why and not how) do you need to parcel objects while sending from one activity to another and not send directly 为什么 (问题是为什么而不是如何)在从一个活动发送到另一个活动而不是直接发送时需要包裹对象

Answer I gave - 我给的答案 -

Parcelable gives the capability to developers to restrict object creation which in a way makes it faster to use. Parcelable为开发人员提供了限制对象创建的能力,从而使其更快地使用。

I was confused on the part, so decided to site difference between using serializable and parcelable :p (clever huuuhhh !), http://www.developerphil.com/parcelable-vs-serializable/ used this reference. 我对此感到困惑,所以决定使用serializable和parcelable之间的区别:p(聪明的huuuhhh!), http://www.developerphil.com/parcelable-vs-serializable/使用了这个引用。

  1. While using Bundle, when we use String, int we do not need to parcel the data, so do you think the String/int is by default internally parcelled ? 在使用Bundle时,当我们使用String时,int我们不需要包含数据,所以你认为String / int默认是在内部包含的吗?

Answer I gave - 我给的答案 -

because String/int is a primitive data-type, if we had used the Wrapper class directly, might be possible we had to use parcelable(I am not sure on that part) 因为String / int是原始数据类型,如果我们直接使用Wrapper类,可能我们必须使用parcelable(我不确定那部分)

I did not get any useful link after googling, also I or the interviewer is not quite satisfied with the answer. 谷歌搜索后我没有得到任何有用的链接,我或者面试官对答案也不太满意。 If you guys can help, would be wonderful ! 如果你们能提供帮助,那就太好了!

Why (question is why and not how) do you need to parcel objects while sending from one activity to another and not send directly 为什么(问题是为什么而不是如何)在从一个活动发送到另一个活动而不是直接发送时需要包裹对象

Parcelling/serializing objects isn't for speed as you had guessed. Parcelling / serializing对象并不像你猜到的那样速度。

When you're sending data between Activities, and especially between different applications (remember that Intent objects aren't only meant for communication between your own Activities, but are also for between yours and those of other apps as well), you cannot expect the sender and the receiver to have access to the same memory address spaces. 当您在活动之间,特别是在不同的应用程序之间发送数据时(请记住, Intent对象不仅用于您自己的活动之间的通信,也适用于您和其他应用程序之间的通信),您不能指望发送方和接收方可以访问相同的内存地址空间。

Android's documentation states that applications run in their own discrete memory spaces. Android的文档指出应用程序在自己的独立内存空间中运行。 Here's a quote to that effect from the docs: 以下是来自文档的引用:

Each process has its own virtual machine (VM), so an app's code runs in isolation from other apps. 每个进程都有自己的虚拟机(VM),因此应用程序的代码与其他应用程序隔离运行。

So when you want to send an object myObject to some receiving Activity , you can't send its reference/pointer because the receiver won't necessarily have access to the location specified by the pointer. 因此,当您想要将对象myObject发送给某些接收Activity ,您无法发送其引用/指针,因为接收器不一定能访问指针指定的位置。 Instead you'll have to send some representation of myObject that the receiver can access and use -- this is why you need to marshall the data into a form that can be unmarshalled , and the easiest way to do so is to simply have the class of the object implement Serializable which lets Java do its best to convert the object into an array of bytes that can be easily sent to and unmarshalled by the receiver. 相反,你得送一些代表性myObject接收器可以访问和使用-这就是为什么你需要马歇尔数据成一种形式,可以解组 ,而这样做最简单的方法是简单地具有类对象实现Serializable ,它允许Java尽力将对象转换为一个字节数组,可以很容易地发送到接收器并由接收器解组。 But since Serializable uses reflection, this is slow. 但由于Serializable使用反射,因此速度很慢。

You can use other ways that are faster to marshall the data -- one, for example, is converting the object into its JSON representation using a library like Gson and just sending it across since any JSON document can be represented as a String and easily converted back to a Java Object . 您可以使用更快速编组数据的其他方法 - 例如,使用像Gson这样的库将对象转换为JSON表示并将其发送到任何JSON文档可以表示为String并轻松转换回到Java Object Another way, which is probably faster in pretty much all cases is using the Parcelable interface which lets you specify exactly how you want to marshall the data and exactly how it should be unmarshalled. 另一种方式,这可能是在几乎所有情况下更快地使用Parcelable接口,它可以让你指定你到底如何想马歇尔的数据,它应该究竟如何解组。 It basically gives you more control on the transmission of the object. 它基本上可以让您更好地控制对象的传输。

The tl:dr : Parcelling/Serializing etc is used because you can't send memory addresses across, so you have to send the actual data of the object and it has to be represented in some form. 使用tl:dr :Parcelling / Serializing等因为你不能发送内存地址,所以你必须发送对象的实际数据,它必须以某种形式表示。

While using Bundle, when we use String, int we do not need to parcel the data, so do you think the String/int is by default internally parcelled ? 在使用Bundle时,当我们使用String时,int我们不需要包含数据,所以你认为String / int默认是在内部包含的吗?

How Bundle works internally is that it puts everything into a Map and parcels/unparcels the data as needed (ie when get/put is called). Bundle如何在内部工作,它将所有内容放入Map并根据需要对数据进行parcels / unparcel(即调用get / put时)。 For putting Objects into a Bundle , the object's class needs to implement Serializable or Parcelable because it needs to tell the Bundle how it should be marshalled/unmarshalled internally. 为了将对象放入Bundle ,对象的类需要实现SerializableParcelable因为它需要告诉Bundle它应该如何在内部编组/解组。

But primitive types and Strings are simple enough and used often enough that the developer doesn't need to specify how that needs to happen and Bundle provides convenience methods for it. 但是原始类型和字符串很简单并且经常使用,开发人员不需要指定需要如何发生,而Bundle为它提供了便利方法。 I can't give you a solid answer at the lowest level of how they works because a lot of the Parcel code is natively implemented and I couldn't find it online, but they must certainly be straightforward to convert to their representation in bytes. 我无法在最低级别的工作中给出一个可靠的答案,因为很多Parcel代码是本地实现的,我无法在线找到它,但它们必须直接转换为字节表示。

Just to add what @uj- said, Parcelling/Serializing is needed as @uj- said it will be sent across JVMs so they need to be converted into some format so that the other party will be able to understand. 只是添加@ uj-所说的,需要Parcelling / Serializing,因为@ uj-表示它将通过JVM发送,因此需要将它们转换为某种格式,以便对方能够理解。

Let me take an example to explain why serializing/parcelling is needed, 让我举一个例子来解释为什么需要序列化/分配,

you are sending data from an application written in "C++" to an application written in java, so the following are the classes, 您正在将用“C ++”编写的应用程序中的数据发送到用java编写的应用程序,因此以下是类,

In C++, 在C ++中,

class Android {
    public: int dataToSend; //for example purpose making field public and omitting setter/getters
}

In Java, 在Java中

class Android{
    public int dataToSend;
}

suppose the C++ code generates dynamic library (which will be generated by compiling using the standard C++ compiler and then linked), and Java code generates a jar (by compiling using the javac). 假设C ++代码生成动态库(将通过使用标准C ++编译器进行编译然后链接生成),Java代码生成jar(通过使用javac进行编译)。

When the C++ application sends data (object of Android class) to the java application the way it is compiled and linked in C++ is completely different as compared to the way its compiled in java and hence java will be wondering what has this C++ application sent to me. 当C ++应用程序将数据(Android类的对象)发送到java应用程序时,它在C ++中编译和链接的方式与它在java中编译的方式完全不同,因此java会想知道这个C ++应用程序发送到什么内容我。

Hence to get rid of such problems serialisation/parcelling is needed which will make sure that both of the application know how the data is converting while transmitting through network (in case of android how it is transmitted to another activity, may be in same or different application). 因此,为了摆脱这些问题,需要序列化/分区,这将确保两个应用程序都知道数据在通过网络传输时如何转换(在android的情况下如何将其传输到另一个活动,可能是相同或不同的应用)。

And yea when we start comparing Serialisation and Parcelling, Parcelling gets the upper hand as we will be specifying the way the data must be converted when sending the data, else in the case of serialisation the object is converted to string using reflection and reflection always takes time. 当我们开始比较Serialization和Parcelling时,Parcelling占了上风,因为我们将指定数据在发送数据时必须转换的方式,否则在序列化的情况下,对象将使用反射和反射转换为字符串时间。 Hence Parcelling is faster compared to Serialisation. 因此,与序列化相比,Parcelling更快。

For your second question, 对于你的第二个问题,

if we consider the above example itself then we can say that String and int being primitive types (no user defined fields in them) and hence android will be able to handle the marshalling and unmarshalling of the data which will be sent. 如果我们考虑上面的例子本身,那么我们可以说String和int是原始类型(其中没有用户定义的字段),因此android将能够处理将被发送的数据的编组和解组。

I tried going through the code when we go on digging deeper we end up getting native code as said by @uj-. 当我们继续深入挖掘时,我尝试了解代码,我们最终获得了@ uj-所说的本机代码。

Some extract from the android source code: while writing the parcel: 一些从android源代码中提取:在编写包裹时:

parcel.writeInt(BUNDLE_MAGIC);
int startPos = parcel.dataPosition();
parcel.writeArrayMapInternal(mMap);
int endPos = parcel.dataPosition();

parcel.setDataPosition(lengthPos);
int length = endPos - startPos;
parcel.writeInt(length);
parcel.setDataPosition(endPos);

while reading the parcel, 在读包裹的同时

int magic = parcel.readInt();
if (magic != BUNDLE_MAGIC) {
    //noinspection ThrowableInstanceNeverThrown
    throw new IllegalStateException("Bad magic number for Bundle: 0x"
    + Integer.toHexString(magic));
}

int offset = parcel.dataPosition();
parcel.setDataPosition(offset + length);

Parcel p = Parcel.obtain();
p.setDataPosition(0);
p.appendFrom(parcel, offset, length);
p.setDataPosition(0);

mParcelledData = p;

set the magic number which will identify the start of the parcel while writing and the same will be used while we read the parcel. 设置在写入时识别包裹起点的幻数,并在读取包裹时使用相同的数字。

Hope I answered your question. 希望我回答你的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 哪种方法是将大量数据(即对象)从一个Activity转移到Android中的另一个Activity? - Which is the best way to transfer bulk of data (i.e. objects) from one Activity to another Activity in Android? 如何将 ArrayList 个对象从一个 Activity 转移到另一个 Activity - How to transfer an ArrayList of objects from one Activity to another 有关Java类对象和Android中从一个活动到另一个活动的数据传输的查询 - An inquiry regarding Java classes objects and data transfer from one activity to another in Android 如何在android中将数据从一个活动传输到另一个活动 - How to transfer data from one activity to another in android 如何在android中将多个字符串从一个活动转移到另一个活动 - how to transfer more then one string from one activity to another in android 从一项活动转移到另一项活动 - Transfer from one activity to another 如何在Android中将数据从一项活动转移到另一项活动? - How do I transfer data from one activity to another in Android? 试图在 android 中将数据从一个活动传输到另一个活动,但它在另一个活动上显示 null 值 - Trying to transfer data from one activity to another in android but it show null value on another activity 将数据从一项活动转移到另一项活动 - Transfer data from one activity to another 将Socket从一个Activity转移到另一个Activity - Transfer Socket from one Activity to another
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM