自定义对象是按值传递还是通过片段和活动中的引用传递。

时间:2013-04-25 11:47:44

标签: java android android-intent android-fragments android-activity

你好Java和Android专家。我遇到了问题。 我正在制作一个基于XMPP的聊天应用程序。有一些事让我感到困惑。

我有一个名为Room_Structure的类,它实现了 Serializable 。此类有一个名为 currentRoom 的对象。

如果我将两个片段之间的 currentroom 对象放在一个捆绑中,它的工作正常,并且令人惊讶的是它通过引用传递。我不知道为什么会这样。它不应该像这样。顺便说一句,我正在使用Android支持库?

但是,如果我在使用捆绑包的活动之间传递 currentRoom 对象并将该捆绑包放入intent中,那么每当我尝试使用该意图启动新活动时,我就会崩溃。

更多说明这是代码

public class Room_Structure implements Serializable {


    private static final long serialVersionUID = 1L;
    private String Rname;
    private ArrayList<Message_Pattern> msg_list;
    private MultiUserChat XmppSession;
    private boolean Background;
    private boolean Modified;
    private boolean Destroyed;
}

上面的类有构造函数以及getter和setter。

现在这就是我在做什么:

考虑一下currentRoom对象已经被填充了,这就是我将它传递给Fragment的方式

    Bundle b = new Bundle();
    b.putSerializable("RoomObject", currentRoom);
    Fragment_Chat newChat = new Fragment_Chat();
    newChat.setArguments(b);
    FragmentManager fm = getChildFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    ft.replace(R.id.fl_chatFragment, newChat);
    ft.addToBackStack(null);
    ft.commit();

从Fragment_Chat OnActivityCreated()方法中检索它,如下所示

Bundle extras = getArguments();
Room_Structure recievedRoom = (Room_Structure) extras.getSerializable("RoomObject");

现在上面的代码工作正常碎片。唯一的问题是对象的引用被传递给新的片段。这不是它应该如何表现的。它应该只发送值而不是引用。

以下是我知道对象是通过引用传递的方式

Sending Object : com.software.chat.Classes.Room_Structure@425585e8
Recieved Object: com.software.chat.Classes.Room_Structure@425585e8

都有相同的引用或地址。在调试

期间检查出来

现在我无法在活动中复制此行为

我有一个包含ExpandibleListView的Activity。我已经通过从BaseExpandableListAdapter扩展它来为此Expandiblelistview实现了适配器。此适配器类名称为Websites_ListAdapter.java。它还在其构造函数中传递了activity的上下文。 我已经在列表中点击了布局。我想在点击时开始一项活动。请不要问为什么我这样做是一个很长的故事。 我正在从这个Websites_ListAdapter发送此对象

Intent i=new Intent(ActivityContext, ChatScreen.class);
    Bundle b = new Bundle();
    b.putSerializable("RoomObject", currentRoom);
    i.putExtras(b);
    i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    ActivityContext.startActivity(i);

但是我在Logcat中遇到这个错误这次我调用了ActivityContext.startActivity(i)

04-25 15:38:07.474: E/AndroidRuntime(10250): FATAL EXCEPTION: main
04-25 15:38:07.474: E/AndroidRuntime(10250): java.lang.RuntimeException: Parcelable encountered IOException writing 

serializable object (name = com.software.chat.Classes.Room_Structure)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at android.os.Parcel.writeSerializable(Parcel.java:1279)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at android.os.Parcel.writeValue(Parcel.java:1233)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at android.os.Parcel.writeMapInternal(Parcel.java:591)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at android.os.Bundle.writeToParcel(Bundle.java:1619)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at android.os.Parcel.writeBundle(Parcel.java:605)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at android.content.Intent.writeToParcel(Intent.java:6814)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at android.app.ActivityManagerProxy.startActivity

(ActivityManagerNative.java:1910)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at android.app.Instrumentation.execStartActivity(Instrumentation.java:1415)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at android.app.Activity.startActivityForResult(Activity.java:3446)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at android.app.Activity.startActivityForResult(Activity.java:3407)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at android.support.v4.app.FragmentActivity.startActivityForResult

(FragmentActivity.java:817)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at android.app.Activity.startActivity(Activity.java:3617)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at android.app.Activity.startActivity(Activity.java:3585)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at com.software.chat.Adapters.Websites_ListAdapter$1.onClick

(Websites_ListAdapter.java:211)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at android.view.View.performClick(View.java:4211)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at android.view.View$PerformClick.run(View.java:17267)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at android.os.Handler.handleCallback(Handler.java:615)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at android.os.Handler.dispatchMessage(Handler.java:92)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at android.os.Looper.loop(Looper.java:137)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at android.app.ActivityThread.main(ActivityThread.java:4898)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at java.lang.reflect.Method.invokeNative(Native Method)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at java.lang.reflect.Method.invoke(Method.java:511)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run

(ZygoteInit.java:1006)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at dalvik.system.NativeStart.main(Native Method)
04-25 15:38:07.474: E/AndroidRuntime(10250): Caused by: java.io.NotSerializableException: 

org.jivesoftware.smackx.muc.MultiUserChat
04-25 15:38:07.474: E/AndroidRuntime(10250):    at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1364)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at java.io.ObjectOutputStream.writeObjectInternal

(ObjectOutputStream.java:1671)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1517)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:979)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at java.io.ObjectOutputStream.defaultWriteObject

(ObjectOutputStream.java:368)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1074)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1404)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at java.io.ObjectOutputStream.writeObjectInternal

(ObjectOutputStream.java:1671)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1517)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481)
04-25 15:38:07.474: E/AndroidRuntime(10250):    at android.os.Parcel.writeSerializable(Parcel.java:1274)
04-25 15:38:07.474: E/AndroidRuntime(10250):    ... 24 more

我知道有很多方法可以在活动之间传递对象,但我想知道它为什么会这样发生以及序列化在后台做什么?

非常感谢有关此事的任何帮助。

3 个答案:

答案 0 :(得分:4)

如果您查看Bundle来源,您会看到它使用Map存储对象,并且只会在Bundle本身被序列化时序列化对象。

似乎Bundle在传递给片段时没有被序列化。它可以是优化技巧或实现“bug”。

但是当你想开始新的活动时,Bundle将被序列化而不是反序列化。这就是为什么你只有活动才有这个例外。

答案 1 :(得分:2)

不同之处在于,您不像使用片段那样创建活动对象,而是要求系统执行此操作。您创建一个intent以请求系统创建活动,intent中的每个东西都被序列化,然后通过系统传递给新活动。无法在共享同一对象的同时创建两个活动。 如果你真的需要相同的对象引用,你总是可以创建一个单例。

答案 2 :(得分:0)

问题出在这里:

Caused by: java.io.NotSerializableException: 

org.jivesoftware.smackx.muc.MultiUserChat

答案是:

public Class MultiUserChat implements Serializable