为什么我需要我的包裹物,即使我只是需要将其发送给同一任务的另一个线程? 其实我需要打开,将甚至在同一个线程(主线程)运行的活动。
换句话说,为什么没有谷歌提供的版本startActivity的是采取一个通用对象的广告parameteer而不是捆绑的,让我开始一个活动的情况下,我知道这是在同一进程中或(大部分时间),甚至同一螺纹(主要的)?
为什么我需要我的包裹物,即使我只是需要将其发送给同一任务的另一个线程? 其实我需要打开,将甚至在同一个线程(主线程)运行的活动。
换句话说,为什么没有谷歌提供的版本startActivity的是采取一个通用对象的广告parameteer而不是捆绑的,让我开始一个活动的情况下,我知道这是在同一进程中或(大部分时间),甚至同一螺纹(主要的)?
你并不需要使用Parcelable从一个活动传递一个对象到另一个。 你可以只保存在一个静态成员变量的对象的引用,就像这样:
public class Globals {
public static MyObject myObject;
}
现在,在有对象的代码,你只是做:
Globals.myObject = object;
而在新的活动,你可以得到它是这样的:
doSomethingWith(Globals.myObject);
现在,话虽如此,您需要注意以下事项:
如果您的应用程序在后台几乎就是了任何时候的Android可以杀死你的进程。 当用户返回到您的应用程序,Android将创建一个新的进程为您的应用,然后将重新仅是在活动堆栈 (即:一个是显示) 的顶部的活动 。 在这种情况下,新创建的活动将无法通过accesing得到IObject提取Globals.myObject
因为进程已新建和成员变量为空。
为了解决这个问题,您可以:
Globals.myObject == null
并作出相应的反应-他告诉需要用户回去,或者只是回去自己,或显示一个对话框或其他) onSaveInstanceState()
在你的活动(其中Android将发送您的应用程序在背景前做),并恢复对对象onCreate()
希望这两个回答你的问题,并解释该怎么做了。
编辑:添加关于为什么意图包含序列化(Parcelable)的对象,而不是对象本身的更多信息
当你调用startActivity()
或startService()
的Android最终可能会开始在另一个进程的活动或服务。 在这种情况下,如果你的意图传递的对象,机器人会以某种方式需要序列化对象将其传递到其他进程。 因为“隐性意图的决议”是Android使用,以确定哪些组件获得处理意向,呼叫者可能会或可能不知道哪个组件将开始。
Android的节省意图的各种原因中的内容:
A.安卓可以随时终止进程。 如果它确实是和用户想要返回到应用程序,Android的创建一个新的进程,然后重新创建在该过程中的活动需要。 要创建的Android也需要做意图提供给活动的活动。 如果进程已被杀死那么任何“对象”的意图都必须保存和恢复。 因为意图包含序列化的对象,它是不是需要重新创建这些问题。 B. PendingIntents是透过Android,以此为操作系统,充当一个Intent的发送者的代理。 一个Android组件可以创建的PendingIntent,并把那个给操作系统,以便它可以在一段时间后触发意向的发送。 所述发送组件可以是或可以不是在该的PendingIntent实际发送的时间激活。 这意味着,可以在一个的PendingIntent传递任何对象必须能够被序列化,这样的Android可以抓住它,即使调用组件不再存在。
意图并非旨在作为组分之间的一般的“参数传递”机制。 当然,你可以用它这样,但你也可以使用其他的(容易)的机制。 在给定的过程中,你可以通过周围用标准的Java机制的对象。 没有什么错误使用静态(类)变量此。
Android的官方文档(在FAQ)提供了很多关于如何通过复杂的数据结构信息的。
我如何通过一个单一的应用程序内的活动/服务之间的数据? http://developer.android.com/guide/faq/framework.html#3
原始数据类型
要共享应用程序中的活动/服务之间的原始数据,使用Intent.putExtras()。 对于传递需要坚持使用首存储机制的基本数据。 非持久性对象
用于共享对于短持续时间复杂非持久用户定义的对象,以下方法被建议:
Singleton类
你可以采取的一个事实,即在相同的过程中,通过使用一个单身的运行应用程序组件的优势。 这是一个被设计成只有一个实例的类。 它具有与一个名字,如getInstance(即返回实例的静态方法); 第一次调用此方法时,它会创建全局实例。 因为所有来电者获得相同的情况下,他们可以用这个作为交互点。 例如活动A可以检索该实例,并且调用的setValue(3); 后来活动B可检索实例和调用的getValue()来检索最后一组值。
公共静态字段/方法
使整个活动/服务数据访问的另一种方法是使用公共静态字段和/或方法。 您可以从任何其他类在应用程序中访问这些静态字段。 要共享一个对象,它创建的对象的活动设置一个静态字段指向这个对象和要使用这个对象只是访问该静态字段的任何其他活动。
在WeakReferences的一个HashMap到对象
您还可以使用在WeakReferences的一个HashMap与长键的对象。 当一个活动要传递一个对象到另一个活动,它只是把在地图中的对象,并通过发送额外意图的关键(这是一个独特的龙基于计数器或时间戳)到接收者的活动。 收件人活动获取使用此键的对象。
持久化对象
即使在一个应用程序似乎继续运行,该系统可以选择杀它的进程,以后再重新启动它。 如果您有需要坚持从一个活动调用到下一个数据,你需要来表示数据状态得到由一个活动时,被告知,它可能消失保存。
对于共享复杂的持久用户定义的对象,则建议使用如下方法:
- Application Preferences - Files - contentProviders - SQLite DB
如果需要共享数据通过在应用过程中可杀点被保留,然后将这些数据用在像应用程序首选项时,SQLite数据库,文件或ContentProviders持久性存储。 请参阅数据存储有关如何使用这些组件的进一步细节。
为什么这是必要的:
由于Android的独特的多任务能力和组件生命周期的理念。 为了允许用户离开一个应用程序(比如与活动A,B,和C,和意图I1,I2,I3)的系统,分离应用到组件 。
这样一来,如果用户使用意图I2启动活动B,但得到一个电话或检查他们的电子邮件,他们可以回到活动B和Android系统可以重新发货意向I2。 并且用户可以轻松,无缝地拿起他们在您的应用程序不放过。
随着组件的生命周期,你做入口和出口各个组成部分容易得多。 它还允许针对不同类型的部件,例如之间的异步通信BroadcastReceivers
, Services
和Activities
。
要做到这一点,操作系统做什么是所谓的“ 编组 ”。 它变平数据以原始数据类型(如int
和char
,以便它可以容易地在存储器中被保持或写入到供以后检索临时存储)。
此外,该所需的任何类型的IPC(进程间通信)的。
使用Intent
允许开发者让Android操作系统执行编组-这通常会是乏味(并且可能难以或越野车)。
所有的活动,您可以创建仅在UI线程上运行。 有没有其他办法。 至于你对需要包裹你的对象问题,实际上它是不是唯一的方式。 您可以通过对象实现Serializable接口也传递对象。
在高层次上,意图是用于不同的部件等之间进行通信的异步消息传递机制:活动,服务和广播接收机。 源和目的地组件可能会或可能不相同的应用程序(因此处理)和Android框架的一部分需要如果需要横穿过程对象的标准化方式。
Android的要求你通过任务,活动,螺纹或服务之间的任何对象必须被压扁成Parcel
或实现Serializable
。 他们这样做,这样你可以按值传递的对象。 当你通过对象的方法或功能,你通过引用传递。 意图传递给系统,系统决定了路由你的意图,无论是启动你的活动的一个或可能打开另一个应用程序。
在接收对象不是你的应用程序的一部分的情况下,接收器将无法访问您的应用程序的内存。 出于这个原因,传递一个对象引用将导致接收应用程序崩溃。 通过压平使对象与包裹或序列化斑点,接收器可作用于该无需访问原始参考被送往的值。 如果谷歌是实现一个设施,你可以通过一个基本的对象,它会要求他们写出深刻的复印功能为所有对象,你会被要求写深拷贝功能,为您所有的自定义对象这将带来麻烦,缓慢并会占用相当多的系统内存可能溢出VM的。 通过提供用于传递对象的公共,基础设施,他们能够提高性能,减少内存需求,并确保安全性不容许其他应用来引用您的应用程序的内存。
正如前面提到的,虽然,你可以创建全球引用对象,你想活动之间传递,只要他们是你的应用程序的所有部分。 这不是最优雅的解决方案,并要求你当你与他们所做的来清零引用这样你就不会吃了不必要的内存,但它工作得很好。
为了通过活动之间/ /服务等自定义类对象(或多个)。 通过Bundle
内的Intent
,你的类必须要实现Parcelable
或Serializable
。
这就是你需要推到前包裹你的对象的原因Bundle