如何在Android上将对象从一个活动传递给另一个活动
我正在尝试从一个Activity
发送客户类的对象,并将其显示在另一个Activity
。
客户类的代码:
public class Customer { private String firstName, lastName, Address; int Age; public Customer(String fname, String lname, int age, String address) { firstName = fname; lastName = lname; Age = age; Address = address; } public String printValues() { String data = null; data = "First Name :" + firstName + " Last Name :" + lastName + " Age : " + Age + " Address : " + Address; return data; } }
我想把它的对象从一个Activity
发送到另一个,然后在另一个Activity
上显示数据。
我怎样才能做到这一点?
一个选项可以让你的自定义类实现Serializable
接口,然后你可以使用Intent#putExtra()
方法的putExtra(Serializable..)
变体传递额外的intent对象实例。
伪代码 :
//To pass: intent.putExtra("MyClass", obj); // To retrieve object in second Activity getIntent().getSerializableExtra("MyClass");
用Serializable实现你的类。 假设这是你的实体类:
import java.io.Serializable; @SuppressWarnings("serial") //With this annotation we are going to hide compiler warnings public class Deneme implements Serializable { public Deneme(double id, String name) { this.id = id; this.name = name; } public double getId() { return id; } public void setId(double id) { this.id = id; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } private double id; private String name; }
我们从X活动发送名为dene
的对象给Y活动。 某处在X活动;
Deneme dene = new Deneme(4,"Mustafa"); Intent i = new Intent(this, Y.class); i.putExtra("sampleObject", dene); startActivity(i);
在Y活动中,我们正在获取对象。
Intent i = getIntent(); Deneme dene = (Deneme)i.getSerializableExtra("sampleObject");
而已。
使用全局静态variables并不是好的软件工程实践。 将对象的字段转换为原始数据types可能是一件繁忙的工作 。 使用可序列化是可以的,但在Android平台上不是性能高效的。 Parcelable是专门为Androiddevise的,您应该使用它。 下面是一个简单的例子: 在Android活动之间传递自定义对象
你可以使用这个网站为你的课程生成Parcelable代码。
在调用一个活动
Intent intent = new Intent(fromClass.this,toClass.class).putExtra("myCustomerObj",customerObj);
在toClass.java中接收活动
Customer customerObjInToClass = getIntent().getExtras().getParcelable("myCustomerObj");
请确保客户类实现parcelable
public class Customer implements Parcelable { private String firstName, lastName, address; int age; /* all your getter and setter methods */ public Customer(Parcel in ) { readFromParcel( in ); } public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { public LeadData createFromParcel(Parcel in ) { return new Customer( in ); } public Customer[] newArray(int size) { return new Customer[size]; } }; @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(firstName); dest.writeString(lastName); dest.writeString(address); dest.writeInt(age); } private void readFromParcel(Parcel in ) { firstName = in .readString(); lastName = in .readString(); address = in .readString(); age = in .readInt(); }
根据我的经验,有三个主要的解决scheme,每个都有其缺点和优点:
-
实现Parcelable
-
实现可序列化
-
使用某种轻型事件总线库(例如,Greenrobot的EventBus或Square的Otto)
Parcelable – 快速和Android标准,但它有大量的样板代码,并需要硬编码的string作为参考时拉出价值的意图(非强types)。
可序列化 – 接近于零样板,但是它是最慢的方法,并且在将数值拉出意向时也需要硬编码的string(非强types)。
事件总线 – 零样式,最快的方法,并不需要硬编码的string,但它确实需要额外的依赖(虽然通常是轻量级的,〜40 KB)
我对这三种方法进行了非常详细的比较,包括效率基准。 如果您有兴趣,可以在Android活动之间传递对象 。
使用gson将您的对象转换为JSON并通过意图传递它。 在新的活动中将JSON转换为对象。
例:
Gson gson = new Gson(); String myJson = gson.toJson(vp); intent.putExtra("myjson", myjson);
而在你的下一个活动中,你想传递的对象是:
Gson gson = new Gson(); YourObject ob = gson.fromJson(getIntent().getStringExtra("myjson"), YourObject.class);
您也可以将对象的数据写入临时string和整数,并将它们传递给活动。 当然,这样,你可以获得传输的数据,而不是对象本身。
但是,如果你只是想显示它们,而不是在另一种方法或类似的东西中使用这个对象,那应该就够了。 我也是这样做的,只是在另一个活动中显示一个对象的数据。
String fName_temp = yourObject.getFname(); String lName_temp = yourObject.getLname(); String age_temp = yourObject.getAge(); String address_temp = yourObject.getAddress(); Intent i = new Intent(this, ToClass.class); i.putExtra("fname", fName_temp); i.putExtra("lname", lName_temp); i.putExtra("age", age_temp); i.putExtra("address", address_temp); startActivity(i);
你也可以直接传递给他们,而不是临时的ivars,但是这种方式在我看来更加清晰。 此外,您可以将temp ivars设置为null,以便更快地清除GarbageCollector。
祝你好运!
注意:重写toString()而不是编写自己的打印方法。
正如下面的评论中所提到的那样,这是如何将数据返回到另一个活动:
String fName = getIntent().getExtras().getInt("fname");
我做了一个持有临时对象的单例助手类。
public class IntentHelper { private static IntentHelper _instance; private Hashtable<String, Object> _hash; private IntentHelper() { _hash = new Hashtable<String, Object>(); } private static IntentHelper getInstance() { if(_instance==null) { _instance = new IntentHelper(); } return _instance; } public static void addObjectForKey(Object object, String key) { getInstance()._hash.put(key, object); } public static Object getObjectForKey(String key) { IntentHelper helper = getInstance(); Object data = helper._hash.get(key); helper._hash.remove(key); helper = null; return data; } }
而不是把你的对象放在意图,使用IntentHelper:
IntentHelper.addObjectForKey(obj, "key");
在你的新活动中,你可以得到这个对象:
Object obj = (Object) IntentHelper.getObjectForKey("key");
请记住,一旦加载,对象被删除,以避免不必要的引用。
有几种方法可以访问其他类或Activity中的variables或对象。
A.数据库
B.共享偏好。
C.对象序列化。
D.一个可以存放公用数据的类可以命名为Common Utilities。 这取决于你。
E.通过Intents和Parcelable接口传递数据。
这取决于你的项目需求。
A. 数据库
SQLite是一个embedded到Android的开源数据库。 SQLite支持标准的关系数据库function,如SQL语法,事务和预处理语句。
教程
B. 共享偏好
假设你想存储用户名。 所以现在有两件事情,一个关键的用户名, 值的价值。
如何存储
// Create object of SharedPreferences. SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); //Now get Editor SharedPreferences.Editor editor = sharedPref.edit(); //Put your value editor.putString("userName", "stackoverlow"); //Commits your edits editor.commit();
使用putString(),putBoolean(),putInt(),putFloat()和putLong()可以保存所需的dtatype。
如何获取
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); String userName = sharedPref.getString("userName", "Not Available");
http://developer.android.com/reference/android/content/SharedPreferences.html
C. 对象序列化
如果我们想要保存一个对象状态通过networking发送它,或者你也可以使用它,你也可以使用对象serlization。
使用Java bean并将其存储在其中,并使用getter和setter来实现。
JavaBeans是具有属性的Java类。 将属性看作私有实例variables。 由于他们是私人的,所以他们可以从课外访问的唯一途径就是通过课堂上的方法。 更改属性值的方法称为setter方法,检索属性值的方法称为getter方法。
public class VariableStorage implements Serializable { private String inString; public String getInString() { return inString; } public void setInString(String inString) { this.inString = inString; } }
通过使用您的邮件方法设置variables
VariableStorage variableStorage = new VariableStorage(); variableStorage.setInString(inString);
然后使用对象序列化来序列化这个对象,并在你的其他类中反序列化这个对象。
在序列化过程中,一个对象可以表示为一个包含对象数据的字节序列,以及关于对象types和存储在对象中的数据types的信息。
序列化对象写入文件后,可以从文件中读取并反序列化。 也就是说,可以使用表示对象及其数据的types信息和字节来重新创build内存中的对象。
如果你想要这个教程参考:
-
Java中的序列化 (博客文章)
-
在其他类中获取variables (堆栈溢出)
D.共同事业
你可以自己创build一个课程,它可以包含你在项目中经常需要的常用数据。
样品
public class CommonUtilities { public static String className = "CommonUtilities"; }
E. 通过意图传递数据
请参考教程Android – 地块数据在使用Parcelable类的活动之间传递这个传递数据的选项。
我发现一个简单而优雅的方法:
- 没有可分类的
- 不可序列化
- 没有静态字段
- 没有事件总线
方法1
第一次活动代码:
final Object objSent = new Object(); final Bundle bundle = new Bundle(); bundle.putBinder("object_value", new ObjectWrapperForBinder(objSent)); startActivity(new Intent(this, SecondActivity.class).putExtras(bundle)); Log.d(TAG, "original object=" + objSent);
第二次活动代码:
final Object objReceived = ((ObjectWrapperForBinder)getIntent().getExtras().getBinder("object_value")).getData(); Log.d(TAG, "received object=" + objReceived);
你会发现objSent
和objReceived
具有相同的hashCode
,所以它们是相同的。
但是为什么我们可以通过这种方式传递一个java对象呢?
实际上,android绑定器将为java对象创build全局JNI引用,并在没有对此java对象的引用时释放此全局JNI引用。 活页夹将在Binder对象中保存这个全局JNI引用。
*注意:只有在两个活动运行在同一个进程中,否则抛出ClassCastException()
类ObjectWrapperForBinder定义
public class ObjectWrapperForBinder extends Binder { private final Object mData; public ObjectWrapperForBinder(Object data) { mData = data; } public Object getData() { return mData; } }
方法2
- 对于发件人,
- 使用自定义本地方法将您的java对象添加到JNI全局引用表(通过JNIEnv :: NewGlobalRef)
- 把返回整数(实际上,JNIEnv :: NewGlobalRef返回jobject,这是一个指针,我们可以把它安全地int)到您的意图(通过Intent :: putExtra)
- 为接收器
- 从Intent获取整数(通过Intent :: getInt)
- 使用自定义本地方法从JNI全局引用表(通过JNIEnv :: NewLocalRef)恢复您的Java对象
- 从JNI全局引用表中删除项目(通过JNIEnv :: DeleteGlobalRef),
但方法2有一个小问题,但是如果接收方无法恢复java对象(例如,在还原java对象之前发生了一些exception,或者接收方Activity根本不存在),java对象将成为孤儿或内存泄漏,方法1没有这个问题,因为android binder会处理这个exception
方法3
为了远程调用java对象,我们将创build一个数据契约/接口来描述java对象,我们将使用aidl文件
IDataContract.aidl
package com.example.objectwrapper; interface IDataContract { int func1(String arg1); int func2(String arg1); }
代码为第一个活动
final IDataContract objSent = new IDataContract.Stub() { @Override public int func2(String arg1) throws RemoteException { // TODO Auto-generated method stub Log.d(TAG, "func2:: arg1=" + arg1); return 102; } @Override public int func1(String arg1) throws RemoteException { // TODO Auto-generated method stub Log.d(TAG, "func1:: arg1=" + arg1); return 101; } }; final Bundle bundle = new Bundle(); bundle.putBinder("object_value", objSent.asBinder()); startActivity(new Intent(this, SecondActivity.class).putExtras(bundle)); Log.d(TAG, "original object=" + objSent);
第二次活动代码:
将AndroidManifest.xml中的android:process属性更改为非空的进程名称,以确保第二个活动在另一个进程中运行
final IDataContract objReceived = IDataContract.Stub.asInterface(getIntent().getExtras().getBinder("object_value")); try { Log.d(TAG, "received object=" + objReceived + ", func1()=" + objReceived.func1("test1") + ", func2()=" + objReceived.func2("test2")); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); }
这样,即使运行在不同的进程中,我们也可以在两个活动之间传递一个接口,并远程调用接口方法
方法4
方法3似乎不够简单,因为我们必须实现一个aidl接口。 如果你只是想做简单的任务,而且方法返回值是不必要的,我们可以使用android.os.Messenger
第一个活动的代码(发件人):
public class MainActivity extends Activity { private static final String TAG = "MainActivity"; public static final int MSG_OP1 = 1; public static final int MSG_OP2 = 2; public static final String EXTRA_MESSENGER = "messenger"; private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub Log.e(TAG, "handleMessage:: msg=" + msg); switch (msg.what) { case MSG_OP1: break; case MSG_OP2: break; default: break; } super.handleMessage(msg); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startActivity(new Intent(this, SecondActivity.class).putExtra(EXTRA_MESSENGER, new Messenger(mHandler))); } }
第二个活动的代码(接收者):
public class SecondActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); final Messenger messenger = getIntent().getParcelableExtra(MainActivity.EXTRA_MESSENGER); try { messenger.send(Message.obtain(null, MainActivity.MSG_OP1, 101, 1001, "10001")); messenger.send(Message.obtain(null, MainActivity.MSG_OP2, 102, 1002, "10002")); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
所有的Messenger.send将在一个Handler中asynchronous执行。
实际上,android.os.Messenger也是一个aidl接口,如果你有android源代码,你可以find一个名为IMessenger.aidl的文件
package android.os; import android.os.Message; /** @hide */ oneway interface IMessenger { void send(in Message msg); }
最好的方法是在你的应用程序中有一个类(称为Control),它将保存一个“Customer”types的静态variables(在你的情况下)。 初始化活动A中的variables
例如:
Control.Customer = CustomerClass;
然后转到活动B并从Control类中获取它。 使用variables之后不要忘记指定一个空值,否则内存将被浪费。
public class MyClass implements Serializable{ Here is your instance variable }
现在你想在startActivity中传递这个类的对象。 简单地使用这个:
Bundle b = new Bundle(); b.putSerializable("name", myClassObject); intent.putExtras(b);
这在这里工作,因为MyClass实现Serializable
。
创build你自己的类Customer
如下:
import import java.io.Serializable; public class Customer implements Serializable { private String name; private String city; public Customer() { } public Customer(String name, String city) { this.name= name; this.city=city; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCity() { return city; } public void setCity(String city) { this.city= city; } }
在你的onCrate()
方法中
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_top); Customer cust=new Customer(); cust.setName("abc"); cust.setCity("xyz"); Intent intent=new Intent(abc.this,xyz.class); intent.putExtra("bundle",cust); startActivity(intent); }
在xyz activity
类你neet使用下面的代码:
Intent intent=getIntent(); Customer cust=(Customer)intent.getSerializableExtra("bundle"); textViewName.setText(cust.getName()); textViewCity.setText(cust.getCity());
如果您select使用Samuh描述的方式,请记住只能发送原始值。 也就是说,可分区的值。 所以,如果你的对象包含复杂的对象,这些将不会遵循。 例如,像位图,HashMap等variables…这些都是棘手的传递的意图。
一般来说,我会build议你只发送原始数据types作为额外的东西,如string,整型,布尔等。在你的情况下,它将是: String fname
, String lname
, int age
和String address
。
我的观点:更复杂的对象通过实现一个ContentProvider , SDCard等更好的共享。它也可以使用静态variables ,但这可能会很快导致错误的代码…
但是,这只是我的主观意见。
我使用parcelable将数据从一个活动发送到另一个活动。 这是我的代码,在我的项目中工作正常。
public class Channel implements Serializable, Parcelable { /** */ private static final long serialVersionUID = 4861597073026532544L; private String cid; private String uniqueID; private String name; private String logo; private String thumb; /** * @return The cid */ public String getCid() { return cid; } /** * @param cid * The cid to set */ public void setCid(String cid) { this.cid = cid; } /** * @return The uniqueID */ public String getUniqueID() { return uniqueID; } /** * @param uniqueID * The uniqueID to set */ public void setUniqueID(String uniqueID) { this.uniqueID = uniqueID; } /** * @return The name */ public String getName() { return name; } /** * @param name * The name to set */ public void setName(String name) { this.name = name; } /** * @return the logo */ public String getLogo() { return logo; } /** * @param logo * The logo to set */ public void setLogo(String logo) { this.logo = logo; } /** * @return the thumb */ public String getThumb() { return thumb; } /** * @param thumb * The thumb to set */ public void setThumb(String thumb) { this.thumb = thumb; } public Channel(Parcel in) { super(); readFromParcel(in); } public static final Parcelable.Creator<Channel> CREATOR = new Parcelable.Creator<Channel>() { public Channel createFromParcel(Parcel in) { return new Channel(in); } public Channel[] newArray(int size) { return new Channel[size]; } }; public void readFromParcel(Parcel in) { String[] result = new String[5]; in.readStringArray(result); this.cid = result[0]; this.uniqueID = result[1]; this.name = result[2]; this.logo = result[3]; this.thumb = result[4]; } public int describeContents() { return 0; } public void writeToParcel(Parcel dest, int flags) { dest.writeStringArray(new String[] { this.cid, this.uniqueID, this.name, this.logo, this.thumb}); } }
在activityA中使用它是这样的:
Bundle bundle = new Bundle(); bundle.putParcelableArrayList("channel",(ArrayList<Channel>) channels); Intent intent = new Intent(ActivityA.this,ActivityB.class); intent.putExtras(bundle); startActivity(intent);
在ActivityB中使用它来获取数据:
Bundle getBundle = this.getIntent().getExtras(); List<Channel> channelsList = getBundle.getParcelableArrayList("channel");
你可以尝试使用这个类。 限制是它不能在一个进程之外使用。
一项活动:
final Object obj1 = new Object(); final Intent in = new Intent(); in.putExtra(EXTRA_TEST, new Sharable(obj1));
其他活动:
final Sharable s = in.getExtras().getParcelable(EXTRA_TEST); final Object obj2 = s.obj(); public final class Sharable implements Parcelable { private Object mObject; public static final Parcelable.Creator < Sharable > CREATOR = new Parcelable.Creator < Sharable > () { public Sharable createFromParcel(Parcel in ) { return new Sharable( in ); } @Override public Sharable[] newArray(int size) { return new Sharable[size]; } }; public Sharable(final Object obj) { mObject = obj; } public Sharable(Parcel in ) { readFromParcel( in ); } Object obj() { return mObject; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(final Parcel out, int flags) { final long val = SystemClock.elapsedRealtime(); out.writeLong(val); put(val, mObject); } private void readFromParcel(final Parcel in ) { final long val = in .readLong(); mObject = get(val); } ///// private static final HashMap < Long, Object > sSharableMap = new HashMap < Long, Object > (3); synchronized private static void put(long key, final Object obj) { sSharableMap.put(key, obj); } synchronized private static Object get(long key) { return sSharableMap.remove(key); } }
创build一个像bean类一样的类并实现Serializable
接口。 然后我们可以通过intent
方法传递它,例如:
intent.putExtra("class", BeanClass);
然后从其他活动中获得它,例如:
BeanClass cb = intent.getSerializableExtra("class");
在你的自定义类中创build两个方法
public class Qabir { private int age; private String name; Qabir(){ } Qabir(int age,String name){ this.age=age; this.name=name; } // method for sending object public String toJSON(){ return "{age:" + age + ",name:\"" +name +"\"}"; } // method for get back original object public void initilizeWithJSONString(String jsonString){ JSONObject json; try { json =new JSONObject(jsonString ); age=json.getInt("age"); name=json.getString("name"); } catch (JSONException e) { e.printStackTrace(); } } }
现在在你的发件人活动做这样的
Qabir q= new Qabir(22,"KQ"); Intent in=new Intent(this,SubActivity.class); in.putExtra("obj", q.toJSON()); startActivity( in);
并在您的接收器活动
Qabir q =new Qabir(); q.initilizeWithJSONString(getIntent().getStringExtra("obj"));
这个问题也在另一个堆栈溢出问题中讨论。 请看看使用Serializable传递数据的解决scheme 。 主要的一点是使用Bundle
对象来存储Intent
必要的数据。
Bundle bundle = new Bundle(); bundle.putSerializable(key1, value1); bundle.putSerializable(key2, value2); bundle.putSerializable(key3, value3); intent.putExtras(bundle);
提取值:
Bundle bundle = new Bundle(); for (String key : bundle.keySet()) { value = bundle.getSerializable(key)); }
Serializable
优点是它的简单性。 但是,如果需要传输多个数据,则应考虑使用Parcelable
方法,因为Parcelable
是专门为Androiddevise的,比Serializable
更有效。 您可以使用以下命令创buildParcelable
类:
- 一个在线工具 – parcelabler
- Android Studio的插件 – Android Parcelable代码生成器
Yeah, using a static object is by far the easiest way of doing this with custom non-serialisable objects.
Android Activity objects can be destroyed and reconstituted. So, you will need to use another approach to look them – or any object they create !!! – up. That is, you could pass as static class reference but then the object handle (Java calls these "references", as does SmallTalk; but they are not references in the sense of C or assembly) will be possibly invalid later because a "feature" of Android OE is any Activity can be annihilated and reconstituted later.
The original question asked "How to pass object from one activity to another in Android" and nobody has answered that. For sure, you can serialized (Serializable, Parcelable, to/from JSON) and pass a copy of the object's data and a new object having the same data could be created; but it will NOT have the same references/handles. Also, many others mentioned you can store the reference in a static store. And that will work unless Android decides to onDestroy your Activity.
So, to really solve the original question you would need a static lookup plus each object will update its reference when/if it is recreated. Eg each Android Activity would relist itself if its onCreate is called. You can also see how some people use the task list to search out an Activity by name. (system is temporarily destroying this instance of the activity to save space..getRunningTasks, the task list is effectively a specialized listing of the most recent object instance of each Activity).
以供参考:
Stopped: "The activity is completely obscured by another activity (the activity is now in the "background"). A stopped activity is also still alive (the Activity object is retained in memory , it maintains all state and member information, but is not attached to the window manager). However, it is no longer visible to the user and it can be killed by the system when memory is needed elsewhere."
onDestroy "system is temporarily destroying this instance of the activity to save space."
So, the Message Bus is a workable solution. It basically "punts". Rather than try to have references to objects; then you re-architect your design to use MessagePassing instead of SequentialCode. Exponentially harder to debug; but it lets you ignore these sort of OperatingEnvironment understandings. Effectively, each object method access is inverted so the caller posts a Message and the object itself defines a handler for that message. Lots more code but can make it robust with the Android OE restrictions.
If all you want is the top Activity (typical thing in Android apps due to "Context" being needed everywhere), then you can just have each Activity lists itself as "top" in the static global space whenever its onResume is called. Then your AlertDialog or whatever which needs a context can just grab it from there. Also, its a bit yucky to use a global but can simplifying passing a Context up and down everywhere and, for sure, when you use a MessageBus then IT IS global anyways.
Start another activity from this activity and pass parameters via Bundle Object
Intent intent = new Intent(getBaseContext(), YourActivity.class); intent.putExtra("USER_NAME", "xyz@gmail.com"); startActivity(intent);
Retrive data on another activity (YourActivity)
String s = getIntent().getStringExtra("USER_NAME");
This is ok for simple kind of data type. But if u want to pass complex data in between activity. U need to serialize it first.
这里我们有员工模型
class Employee{ private String empId; private int age; print Double salary; getters... setters... }
你可以使用google提供的Gson lib来像这样序列化复杂的数据
String strEmp = new Gson().toJson(emp); Intent intent = new Intent(getBaseContext(), YourActivity.class); intent.putExtra("EMP", strEmp); startActivity(intent); Bundle bundle = getIntent().getExtras(); String empStr = bundle.getString("EMP"); Gson gson = new Gson(); Type type = new TypeToken<Employee>() { }.getType(); Employee selectedEmp = gson.fromJson(empStr, type);
-
I know that static is bad, but it seems that we're forced to use it here. The problem with parceables/seriazables is that the two activities have duplicate instances of the same object = waste of memory and CPU.
public class IntentMailBox { static Queue<Object> content = new LinkedList<Object>(); }
Calling activity
IntentMailBox.content.add(level); Intent intent = new Intent(LevelsActivity.this, LevelActivity.class); startActivity(intent);
Called activity (note that onCreate() and onResume() may be called multiple times when the system destroys and recreates activities)
if (IntentMailBox.content.size()>0) level = (Level) IntentMailBox.content.poll(); else // Here you reload what you have saved in onPause()
-
Another way is to declare a static field of the class that you want to pass in that very class. It will serve only for this purpose. Don't forget that it can be null in onCreate, because your app package has been unloaded from memory by system and reloaded later.
-
Bearing in mind that you still need to handle activity lifecycle, you may want to write all the data straight to shared preferences, painful with complex data structures as it is.
I had always wondered why this can't be as simple as calling into a method of the other activity. I recently wrote a utility library that makes it almost as simple as that. You can check it out here( https://github.com/noxiouswinter/gnlib_android/wiki/gnlauncher ).
GNLauncher makes sending objects/data to an Activity from another Activity etc as easy as calling a function in tha Activity with the required data as parameters. It introduces type safety and removes all the hastles of having to serialize, attaching to the intent using string keys and undoing the same at the other end.
用法
Define an interface with the methods you want to call on the Activity to launch.
public interface IPayload { public void sayHello(String name, int age); }
Implement the above interface on the Activity to launch into. Also notify GNLauncher when the activity is ready.
public class Activity_1 extends Activity implements IPayload { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //Notify GNLauncher when the Activity is ready. GNLauncher.get().ping(this); } @Override public void sayHello(String name, int age) { Log.d("gnlib_test", "Hello " + name + "! \nYour age is: " + age); } }
In the other Activity, get a proxy to the above Activity and call any method with the desired parameters.
public class Activity_2 extends Activity { public void onClick(View v) { ((IPayload)GNLauncher.get().getProxy(this, IPayload.class, Activity_1.class)).sayHello(name, age); } }
The first activity will be launched and the method called into with the required parameters.
先决条件
Please refer to https://github.com/noxiouswinter/gnlib_android/wiki#prerequisites for information on how to add the dependencies.
Pass object from one activity to another activity.
(1) source activity
Intent ii = new Intent(examreport_select.this, BarChartActivity.class); ii.putExtra("IntentExamResultDetail", (Serializable) your List<ArraList<String>> object here); startActivity(ii);
(2) destination acitivity
List<ArrayList<String>> aa = (List<ArrayList<String>>) getIntent() .getSerializableExtra("IntentExamResultDetail");
I used to set object with Pacelable or Serializable to transfer, but whenever I add other variables to object(model), I have to register it all. It's so nconvenient.
It's super easy to transfer object between activities or fragments.
Android DataCache
We can pass the object from one activity to another activity:
SupplierDetails poSuppliersDetails = new SupplierDetails();
Inside poSuppliersDetails
we have some values. Now I am sending this object to target activity:
Intent iPODetails = new Intent(ActivityOne.this, ActivityTwo.class); iPODetails.putExtra("poSuppliersDetails", poSuppliersDetails);
How to get this in ACtivityTwo:
private SupplierDetails supplierDetails; supplierDetails =(SupplierDetails) getIntent().getSerializableExtra("poSuppliersDetails");
Above answers almost all correct but for those who doesn't undestand those answers Android has powerfull class Intent with help of it you share data between not only activity but another components of Android (broadcasr receiver, servises for content provide we use ContetnResolver class no Intent). In your activity you build intent
Intent intent = new Intent(context,SomeActivity.class); intent.putExtra("key",value); startActivity(intent);
In your receving activity you have
public class SomeActivity extends AppCompactActivity { public void onCreate(...){ ... SomeObject someObject = getIntent().getExtras().getParceable("key"); } }
You have to implement Parceable or Serializable interface on your object in order to share between activities. It is hard to implement Parcealbe rather than Serializable interface on object that's why android has plugin especially for this.Download it and use it
Pass one activity to another:
startActivity(new Intent(getBaseContext(),GetActivity.class).putExtra("passingkey","passingvalue"));
Get values:
String myvalue= getIntent().getExtras("passingkey");
Hello all I see a lot of good options but I was wondering why Binding hasn't been used?
Passing a reference to an object just seems more efficient to me than serializing and desterilizing objects, but I have not done a deep dive to see if that is what is going on behind the scenes.
Creating a Binder is simple enough…
public class MyBinder extends Binder { private Object myObject; public MyBinder(Object object) { myObject = object; } public Object getObject() { return myObject; } }
And creating the parcelable to use it isn't that bad ether.
public class MyParcelable implements Parcelable { private Object myObject; public MyParcelable() { } public MyParcelable(Parcel parcel) { myObject = ((MyBinder)parcel.readStrongBinder()).getObject(); } public void setObject(Object object) { myObject = object; } public Object getObject() { return myObject; } public void writeToParcel(Parcel parcel, int flags) { parcel.writeStrongBinder(new MyBinder(myObject)); } public int describeContents() { return myObject == null ? 0 : 1; } public static final Parcelable.Creator<MyParcelable> CREATOR = new Parcelable.Creator<MyParcelable>() { public MyParcelable createFromParcel(Parcel parcel) { return new MyParcelable(parcel); } public MyParcelable[] newArray(int length) { return new MyParcelable[length]; } }; }
This logic is really cool because you are actually passing a reference from activity to activity.
I would advise checking for nulls and if the instanceof Binder is MyBinder!
and to implement this you just…
Send it off
Object myObject = "some object"; MyParcelable myParcelable = new MyParcelable(); myParcelable.setObject(myObject); intent.putExtra("MyParcelable", myParcelable);
Get it back
myParcelable = (MyParcelable) getIntent().getExtras().getParcelable("MyParcelable"); myObject = myParcelable.getObject();
Heck someone could get all crazy and make this sucker a true generic.