通过活动传递信息

时间:2015-12-30 16:58:05

标签: java android parcelable

所以,我正在尝试为android练习编程做类似rpg的东西。我有一个英雄对象,我试图通过其他人推荐的parcelable传递,但我不知道如何传回它。

在一项活动中,我将

myIntent.putExtra("heroData", hero);

然后,在myIntent中,活动开始于原始活动,我将

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

注意:Protag是英雄对象的类

因此,第一个活动成功将对象传递给第二个活动,但第二个活动不会影响第一个活动中的对象。比如,如果第一个活动中的对象发生了某些事情,它将保留到第二个活动,但如果第二个活动中的对象发生了某些事情,则第一个活动中的对象仍然是相同的。

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

4 个答案:

答案 0 :(得分:2)

你正在处理并发问题。由于您有2个'活动'可能会对单个'数据'执行操作。但是,Parcelable是一种序列化技术,这意味着一旦传递一个可分割的对象(通过parcelable),您将丢失引用。这意味着您不能将parcelable对象用作同步的中心点(用数据更新它)。

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

AIDL单向ascync服务可以通知每个线程对“已注册”对象的值的更改。 (AIDL单向实际上并不难写,只需要一些练习)Here is a project I wrote利用它来显示同步和异步服务的使用。 (我的博士生导师为他所教的MOOC的REPO)

更新解释为什么我说这是'并发'。

首先,我采取'广泛'的方法来解决'并发'与你可能想到的问题。您对'并发'的工作定义是有效的。但是,与我的想法相比,它的范围有限。 (通常没关系,但Android生命周期的细微差别实际上使其变得重要)

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

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

现在这里出现了并发问题....当你有2个或更多活动没有处于'Destroyed'状态时。

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

Android的非确定性行为..用户可以按电源/家庭/返回或其他按钮,电话进来/ AMBER警报优先于电话,和/或垃圾收集器“魔法神圣/邪恶的仪式”决定谁活着或死亡(夸大,但你明白了)。

但是让我们假设A没有被杀死(这实际上是这里的'问题'场景)。

所以A创建一个X对象(英雄或其他)并通过值(parcelable + intent)传递给B的值X.此时,X的值(和引用)在A中但是值为X在B中。因此,我们已经处于并发状态。因为A和B的生命周期重叠。不仅仅是生命周期中的“可见”部分。所以这意味着......你在哪里把逻辑放在“何时传回X的值”?你把它传回onPause()吗? (但如何?如果用户按下后退按钮,意图将不起作用)

简短的回答:没有一个“伟大的”方法可以做到这一点。 (至少只有活动和意图/分类。)

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

  

并发编程的基本目标包括正确性,性能和稳健性。 (来自WIKI:Concurrency(CS)

理想情况下,您不会按值传递数据,而是通过引用传递数据,并且当一个类更新X(无论是A还是B)时,只存在一个X值。这样,当A或B重新出现时开始它将具有X的“有效”值。但是你不能通过可分割数据“很好地”做到这一点。

因此我会使用服务作为'X值'的权威守护者,任何时候A或B想要更新X,那么他们必须通过同步方法来获取/设置X.(我是从来没有真正遇到这样的场景,其中两个活动想要拥有相同的“实时数据”,所以也许有一个更好的解决方案,可能使用处理程序(但我无法想到它))通过服务你从A告诉服务X更新到B可以获得该信息时,会有轻微的时间延迟。但它是我能想到的最好的东西。

此外,SQLite DB旨在促进此类数据存储,并内置支持监视器,以便在另一个线程访问数据库时阻止对数据库的访问。 (这里有细微之处我不会介入,比如'setLockingEnabled(boolean)')

答案 1 :(得分:0)

让它在顶级

上保持静态

所有活动都可以调用它。像

MyObject hero = topActivity.Hero

但是

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

真诚

答案 2 :(得分:0)

可能性是:

Activity1使用方法Activity2启动startActivityForResult()。在Activity2中,您将完成对象“hero”所需的所有修改,然后您可以将其置于意图中并使用setResult (int resultCode, Intent data)将其发回。这样,当使用onActivityResult(int requestCode, int resultCode, Intent data)恢复Activity1时,您将能够捕获修改过的“英雄”对象。

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

答案 3 :(得分:0)

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

编辑:

或者您可以保存在内部存储中。将Protag对象保存为文件。 这一切都取决于对象变化的频率。

提示:每次对对象进行更改时都不应该编写。将数据保存在某些数据结构中,然后在完成所有内容(如级别结束或其他内容)后,您可以在存储或共享首选项中编写。这样你保持高效,否则所有写入存储都会降低应用程序的速度。