是否可以将来自两个不同的可打包数据类的数据存储在一个意图中以使用它开始新的 Activity?

Posted

技术标签:

【中文标题】是否可以将来自两个不同的可打包数据类的数据存储在一个意图中以使用它开始新的 Activity?【英文标题】:Is it possible to store data from two different parcelable data classes in one single intent to start a new Activitiy with it? 【发布时间】:2020-01-21 14:42:14 【问题描述】:

经过大量研究,我无法找到解决问题的真正方法。大多数答案基于将单个可打包对象附加到意图并从中开始新活动。

在我的例子中,我使用来自两个不同的 parcelable 类的数据。我有两个不同的 RecyclerView 适配器类,它们存在于同一个活动中。

因此,当用户单击第一个(父)适配器类的数据集时,视图会显示第二个适配器类的所有可用(子)数据集。

我想保存用户第一次单击的父对象数据集,以及用户最后执行长单击的子对象。这两个对象需要附加到相同的意图上,完成后,应该启动一个新的活动。来自两个对象(父对象和子对象)的数据必须在新活动中传递。

为了清楚起见,我只发布代码的相关部分。

这是父适配器类的一部分,我需要将对象数据保存为一种“全局”意图,我的代码将只产生一个本地意图(这就是它只被注释的原因)。

                itemView.setOnClickListener 
                notifyItemChanged(selectedPos)
                selectedPos = adapterPosition
                notifyItemChanged(selectedPos)
                listener.onHeadItemClicked(weKopf.WENR, p1)
                // save parent parcelable object data to "global" intent 
                // val intent = Intent(context, StorageGoodsActivity::class.java)
                // intent.putExtra("weKopf", weKopf)

            

这是我想将子对象数据附加到相同意图然后启动新活动的代码部分。

                itemView.setOnLongClickListener
                notifyItemChanged(selectedPos)
                selectedPos = adapterPosition
                notifyItemChanged(selectedPos)
                listener.onPositionLongClicked(wePos.lfdNr.toInt())
                /**
                 * setting-up for passing objects between activities
                 */
                val intent = Intent(context, StorageGoodsActivity::class.java)
                //intent.putExtra("weKopf", weKopf)
                intent.putExtra("wePos", wePos)
                context.startActivity(intent)
                true

最优雅的方法是什么?我的想法是将意图存储到共享组件中,但只要用户单击后退按钮返回旧活动并在此之后选择新的父子星座,这个意图就应该存在。如果是这样,这个创建的项目会被丢弃,还是仍然存在于共享组件中?

我对 android Studio 和 Kotlin 还很陌生,我很感激每一个帮助或建议。非常感谢你。

【问题讨论】:

【参考方案1】:

您可以在 Intent 中添加任意数量的附加内容,只要每个内容都有自己的名称即可。唯一的限制是对 Intent 总大小的限制(大约 2 MB iirc)。

【讨论】:

感谢您的回复。但是如何创建“全局”意图来存储对象和生命,直到用户按下后退按钮返回旧活动?我必须先调用两个适配器类中的 Intent 并附加数据,然后才能使用它启动新的 Activity。 你不会的。当用户按下后退按钮时,您将返回旧活动。如果那还在记忆中,你会回到它原来的位置。如果它因资源而被杀死,您应该实现 onSaveInstanceState 和 onRestoreInstanceState 来进行状态的加载和卸载。没有地方应该使用 Intent。如果您实际上是在尝试使后退按钮转到第三个意图,那就不要了。这不是Android的工作方式。但即便如此,您还是会将数据传递给第二个意图并让它启动第三个意图,而不是以某种方式将其全局保存 是的,确实如此。我只能开始一个新的活动一次,我想我只能用一个单一的意图来做到这一点。那么,这个意图如何包含来自适配器/可打包类的数据?【参考方案2】:

这个问题的解决方案是一些小的工作。不可能以相同的意图附加来自两个适配器类的数据对象,因为新活动只能从一个适配器启动。 在这种情况下,我将数据对象从第一个(父)适配器传递给 SharedPreferences 对象,该对象使用 Gson 转换为他的 JSON 表示形式。

itemView.setOnClickListener 
                notifyItemChanged(selectedPos)
                selectedPos = adapterPosition
                notifyItemChanged(selectedPos)
                listener.onHeadItemClicked(weKopf.WENR, p1)

                /**
                 * store object in SharedPreferences
                 */
                val sharedPreferences:SharedPreferences = context.getSharedPreferences("StoreHeadObj", MODE_PRIVATE)
                val editor : SharedPreferences.Editor = sharedPreferences.edit()
                val gson = Gson()
                val json = gson.toJson(weKopf)

                editor.putString("JSONString", json)
                editor.commit()

第二个(子)对象传递了一个意图,并启动了新的 Activity。

itemView.setOnLongClickListener
                notifyItemChanged(selectedPos)
                selectedPos = adapterPosition
                notifyItemChanged(selectedPos)
                listener.onPositionLongClicked(wePos.lfdNr.toInt())
                /**
                 * setting-up for passing objects between activities
                 */                
                val intentPos = Intent(context, StorageGoodsActivity::class.java)                
                intentPos.putExtra("wePos",wePos)
                context.startActivity(intentPos)

                true

在新的 Activity 中,我从两个对象中检索数据。首先,我将 JSON 字符串转换为数据对象,然后将数据从 Intent 中取出。因此,两个可打包的数据对象现在都可以在新的 Activity 中使用了。

override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(getContentView())

        /**
         * get data from clicked weKopf-Object using Gson, at the end clear SharedPreferences
         */
        val sharedPreferences:SharedPreferences = getSharedPreferences("StoreHeadObj", Context.MODE_PRIVATE)
        val gson = Gson()
        val json:String = sharedPreferences.getString("JSONString", "")
        val weKopf:WeKopf = gson.fromJson(json, WeKopf::class.java)
        /**
         * get data from long-clicked wePos-Object using Intent
         */
        val extras = getIntent().getExtras()
        val wePos = extras.getParcelable<WePos>("wePos")

【讨论】:

以上是关于是否可以将来自两个不同的可打包数据类的数据存储在一个意图中以使用它开始新的 Activity?的主要内容,如果未能解决你的问题,请参考以下文章

来自不同命名空间的同名对象的可重用函数代码?

跨两个不同域的单个API存储?

连接来自两个独立数据库的结果

将来自多个 API 端点的数据合并到一个数据库中

连接来自 2 个不同主机的两个数据库

来自 ArrayList 类的列表视图