可打包,通过活动携带信息

Parcelable, carrying information through activities

所以,我正在尝试为 android 制作类似角色扮演游戏的东西来练习编程。我有一个英雄对象,我正尝试按照其他人的建议使用 parcelable 传递它,但我不确定如何将它传递回去。

在一个 activity 中,我将

myIntent.putExtra("heroData", hero);

然后,在myIntent中,activity开始于原来的activity,我将

hero = (Protag) getIntent().getParcelableExtra("heroData");

注意:Protag是英雄对象的class

因此,第一个 activity 确实成功地将对象传递给第二个 activity,但是第二个 activity 不会影响第一个 [=25] 中的对象=].就像,如果第一个 activity 中的对象发生了什么事,它会保留到第二个 activity,但是如果第二个 activity 中的对象发生了什么事,那么第二个 activity 中的对象第一个activity还是老样子

我如何创建一个可以被任何 activity 更改的对象,以便通过其他活动保留更改?

让它在顶部静态化class

所有activity都可以调用。喜欢

MyObject 英雄 = topActivity.Hero

但是但是但是

我完全不确定这是正确的方法还是最好的方法。所以也许等待其他回应

此致

您现在正在处理并发。由于您有 2 'activities' 可能作用于单个 'data'。但是,Parcelable 是一种序列化技术,这意味着一旦传递一个可打包对象(通过 parcelable),您将失去引用。这意味着您不能将可打包对象用作同步的中心点(两者都用数据更新它)。

如果您 永远 计划拥有您的 class 的单个对象,那么您可以使该对象具有静态值。否则这是执行此操作的错误机制。


通知每个线程 'registered' 对象值更改的 AIDL one-way 异步服务是可行的。 (AIDL one-way 其实不难写,只是需要一些练习) Here is a project I wrote 利用它,来展示同步和异步服务的用法。 (我的博士生导师对他教授的 MOOC 的 REPO)


更新以解释为什么我说这是 'concurrency'。

首先,我采用 'wide breadth' 方法来了解 'concurrent' 与您的想法。您对 'concurrent' 的工作定义是有效的。但是,与我正在考虑的相比,它的范围有些有限。 (通常无关紧要,但 Android 生命周期的细微差别实际上使它变得重要)

Android 活动有 6 life-cycle states they could possibly be in.

  • 已创建
  • 开始(可见)
  • 已恢复(可见)
  • 已暂停(部分可见)
  • 已停止(隐藏)
  • 已销毁

这就是并发问题出现的地方....当您有 2 个或更多不处于 'Destroyed' 状态的 Activity 时。

此外,还有很多事情会增加您的逻辑的不可预测性,您必须非常仔细考虑...

Android 的 non-deterministic 行为。用户可以按 power/home/back 或其他按钮,phone 调用 in/AMBER 警报优先于phone、and/or 垃圾收集器 "magic divine/unholy ritualistically" 决定生死(夸张,但你明白了)。

但是假设 A 没有被杀死(这实际上是这里的 'problem' 场景)。

于是A创建了一个X对象(hero什么的),并通过值(parcelable+intent)将X的值传递给B。此时,X的值(和引用)在A中。但是X的值在B中。因此,我们已经处于并发状态。因为A和B的life-cycles重叠了。不仅仅是 life-cycles 的 "visible" 部分。所以这意味着......你把"when to pass back the value of X"的逻辑放在哪里?你把它传回 onPause() 吗? (但是如何?如果用户按下后退按钮,意图将不起作用)

简短回答:没有 'great' 方法可以做到这一点。 (至少只有活动和 Intents/Parcelables。)

您需要一些适当的并发机制,允许对 A 中 X 的更改传播以更改 B 中 X 的值。(这需要可靠、正确和高效地完成。)

The base goals of concurrent programming include correctness, performance and robustness. (from WIKI:Concurrency(CS) )

理想情况下,您不会按值传递数据,而是通过引用传递数据,当一个 class 更新 X(无论是 A 还是 B)时,X 只存在一个值。这样当A 或 B 是 re-started 它将有一个 'valid' X 的值。但是你不能通过 parcelable 数据做到这一点 'nicely'。

因此我会用一个服务作为'value of X'的权威守护者,任何时候A或B想要更新X,那么他们必须通过同步方法到get/set X。 (我从来没有真正 运行 进入过这样的场景,其中两个活动想要像这样具有相同的 'live data',所以也许有更好的解决方案,可能使用处理程序(但我想不出随手))使用服务,从 A 告诉服务 X 已更新到 B 可以获取该信息的时间,您会有轻微的时间延迟。但这是我现在能想到的最好的。

此外,SQLite 数据库旨在像这样促进数据存储,并内置了对监视器的支持,以在另一个线程访问数据库时阻止对数据库的访问。 (这里有细微差别我不会涉及,例如'setLockingEnabled(boolean)')

一种可能性是:

Activity1 使用方法 startActivityForResult() 启动 Activity2。在 Activity2 中,您将对对象 "hero" 进行所有需要的修改,然后您可以将其放入意图中并使用 setResult (int resultCode, Intent data) 将其发回。这样,当 Activity1 恢复时,使用 onActivityResult(int requestCode, int resultCode, Intent data),您将能够捕获对象 "hero" 已修改。

在这里您可以找到有关此机制的更多信息。 http://developer.android.com/training/basics/intents/result.html

您可以在共享首选项中写入对象数据。这样就不需要服务了。无论如何你都需要保存游戏的进度。我认为一旦应用程序关闭进度回到原来的位置,这样的更改应该保存在内存中。

编辑:

或者您可以保存在内部存储中。将 Protag 对象另存为文件。 这完全取决于对象更改的频率。

提示:您不应该在每次对对象进行更改时都进行写入。将数据保存在一些数据结构中,然后当一切都完成时,例如关卡结束或其他东西,然后你写入存储或共享首选项。这样你就可以保持高效,否则所有在存储中的写入都会降低应用程序的速度。