Android如何在活动之间传递LinkedHashMap?

17

我想在不同的活动之间传递LinkedHashMap,我的代码如下

活动A

LinkedHashMap mLinkedHashMap = new LinkedHashMap<String, Object>();
// setting data in map
Bundle bundle = new Bundle();
bundle.putSerializable("OBJECTS_LINKED_HASHMAP", mLinkedHashMap);  
Intent intent = new Intent(this, ActivityB.class); 
intent.putExtras(bundle);
startActivity(intent);
在我收到 bundle 对象时,出现了“Class cast exception”错误消息。
活动 B。
Bundle bundle = this.getIntent().getExtras();
LinkedHashMap mLinkedHashMap = new LinkedHashMap<String, Object>();
mLinkedHashMap = (LinkedHashMap<String, Object>) bundle.getSerializable("OBJECTS_LINKED_HASHMAP");

获取类转换异常

ClassCastException: java.util.HashMap cannot be cast to LinkedHashMap

我已经查阅了LinkedHashMap的文档,并且实现了Serializable接口。

我正在使用LinkedHashMap,因为我想保持对象的顺序,它们插入的方式我希望能按照原来的顺序返回。

如何在不同的活动(activities)之间传递LinkedHashMap?


当你将LinkedHashMap插入/提取到Intent中时,不能可靠地进行操作,因为Android在将Map序列化到IntentBundle中时会将LinkedHashMap转换为HashMap。在接收端,你得到的是一个HashMap,而LinkedHashMap的顺序已经消失了。你需要将LinkedHashMap转换为有序数组并将其传递到Intent中,或者使用另一种序列化/反序列化机制。在我看来,添加GSON库来完成这项工作是过度的,但还有其他更高效的选择。 - David Wasser
请查看https://dev59.com/WWct5IYBdhLWcg3wKqUd#12305459获取更多详细信息。 - David Wasser
5个回答

22

尝试使用 GSON 改变一下 :)

从这个链接下载 gson.jar

然后将 gson-2.2.2.jar 文件添加到您的项目中。
现在,使用 GSON 将您的 LinkedHashMap 传递给另一个活动

像这样(根据您的需求修改以下代码):

MainActivity:::

public class MainActivity extends Activity {
    ObjectClass obj=new ObjectClass();
    LinkedHashMap<String, ObjectClass> mLinkedHashMap = new LinkedHashMap<String, ObjectClass>();
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        obj.id=1;
        obj.name="hello";

        mLinkedHashMap.put("test", obj);

        Gson gson = new Gson();
        String list = gson.toJson(mLinkedHashMap); 
        Intent intent = new Intent(this, secondActivity.class); 
        intent.putExtra("list", list);
        startActivity(intent);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}

secondActivity:::

==>

第二个活动:::

public class secondActivity extends Activity {
    LinkedHashMap<String, ObjectClass> mLinkedHashMap = new LinkedHashMap<String, ObjectClass>();
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
     String str=  getIntent().getStringExtra("list");
     Gson gson = new Gson();

     Type entityType = new TypeToken< LinkedHashMap<String, ObjectClass>>(){}.getType();
     mLinkedHashMap = gson.fromJson(str, entityType);
    ObjectClass obj = mLinkedHashMap.get("test");

     Log.i("list", ""+obj.id);
    }
}

对我有用,希望这能帮助到你。

以下是我的对象类供参考。

public class ObjectClass {

    public int id;
    public String name;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }


}

如何添加gson-2.2.2.jar文件。

1)从下载的文件夹“google-gson-2.2.2”中复制gson-2.2.2.jar文件。
2)将它粘贴到你项目的asset文件夹中。
3)现在通过右键单击你的项目>Build Path>Configure Build Path.进入你的项目构建路径设置。
4)这将打开一个对话框,选择java build path,然后转到库标签,
点击下面的"Add Jars..."按钮(如下图所示),它将打开另一个对话框以添加jar文件。选择我们在项目资产文件夹中添加的gson-2.2.2.jar文件(步骤2)。
它将向你的项目添加jar文件(我已经在我的项目中添加了它,如下面的图像所示)

enter image description here 5)现在选择Order and Export标签,然后选择你的gson-2.2.2.jar文件(如下图所示)。
enter image description here 6)按下OK,现在你可以在你的项目中使用GSON了。


在Android上,这是一个不好的想法。虚方法调用是昂贵的,比实例字段查找要昂贵得多。遵循常见的面向对象编程实践,在公共接口中使用getter和setter是合理的,但在类内部,您应该直接访问字段。 - The Holy Coder
没有即时编译(JIT)的情况下,直接访问字段比调用一个简单的getter方法快大约3倍。而在有JIT的情况下(直接访问字段与访问本地变量一样廉价),直接访问字段比调用一个简单的getter方法快大约7倍。这在Froyo中是成立的,但当JIT内联getter方法时,将来会有所改善。 - The Holy Coder
@ManishAndroid,对于Pragnani的问题,我同意你的看法。我尝试了你的解决方案,但是我一直得到ClassCastException异常,因为bundle始终只返回Hashmap对象,我不知道它是如何在你那里工作的?你能否更新你的答案,包括完整的代码,例如你如何声明Linked Hashmap以及如何传递和接收它?感谢你宝贵的建议。 - Mac
你好,如何在 Kotlin 中转换为 LinkedHashMap?谢谢。 - famfamfam

4

有没有任何方法可以实现相同的输出? - Mac
1
@Mac 你错了... LinkedHashMap 是可序列化的,请参考这个链接:http://docs.oracle.com/javase/1.4.2/docs/api/java/util/LinkedHashMap.html - Pragnani
2
因为HashMap实现了Serializable接口,而LinkedHashMap继承了HashMap。 - ρяσѕρєя K
您似乎是正确的 - 我错了。HashMap实现了Serializable,尽管这似乎没有被记录下来。我很抱歉。请注意,这将取决于可序列化的键和值。 - The Holy Coder
1
请查看此链接 https://dev59.com/VU3Sa4cB1Zd3GeqPzvcL ,或许可以帮到您。 - The Holy Coder
@ManishAndroid 给链接点赞+1 - Pragnani

3

编辑:

根据Manish Android提供的链接,解决方案是

  if (getIntent().getSerializableExtra("OBJECTS_LINKED_HASHMAP") != null)
                HashMap<?, ?>   user_info = (HashMap<?, ?>) getIntent().getSerializableExtra("OBJECTS_LINKED_HASHMAP");


    LinkedHashMap<String, Object>   userdata= (LinkedHashMap<String, Object>) user_info

你需要像这样获取
if (getIntent().getSerializableExtra("OBJECTS_LINKED_HASHMAP") != null)
        LinkedHashMap<String, Object>   user_info = (LinkedHashMap<String, Object>) getIntent().getSerializableExtra("OBJECTS_LINKED_HASHMAP");

1
"null" getIntent().getSerializableExtra("OBJECTS_LINKED_HASHMAP") 没有问题;它返回的不是 LinkedHashMap 对象,而是 HashMap 对象。因此,我会得到 ClassCastException。 - Mac
@Mac:你在 Object 的位置传递了哪个值?如果是自定义类对象,则该类必须实现 Serializable 接口。 - ρяσѕρєя K
@Mac,请参考Manish Android提供的链接,这将解决您的问题。 - Pragnani
2
@Pragnani 他遇到了 hashmap 无法转换为 linkedhashmap 的错误。但是您在您的答案中又再次做了同样的事情。 - Diffy
这种方法对我不起作用。我正在使用这个解决方案 - Juan Saravia
显示剩余5条评论

0
我的方法如下:
CustomObject必须实现Parcelable接口。为了设置bundle:
    LinkedHashMap<Integer, List<CustomObject>> mItems

    Bundle bundle = new Bundle();

    bundle.putInt("ItemsSize",mItems.size());          
    int mapIndex=0;

for(Map.Entry<Integer, List<CustomObject>> entry : mItems.entrySet()) {
    int key = entry.getKey();
    bundle.putInt("Key"+mapIndex, key);
    bundle.putParcelableArrayList("Value"+mapIndex, mItems.get(key));
    mapIndex++;
}

获取捆绑包:

for(int i=0;i<bundle.getInt("ItemsSize");i++) {
    int key = bundle.getInt("Key"+i);
    ArrayList<CustomObject> value = bundle.getParcelableArrayList("Value"+i);
    mItems.put(key, value);
}

0

将其作为字节数组传递,然后在目标 Activity 中进行反序列化并转换为 LinkedHashMap


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接