我正在尝试从一个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
,然后在另一个{{1}}上显示数据。
我怎样才能做到这一点?
答案 0 :(得分:803)
一个选项可能是让您的自定义类实现Serializable
接口,然后您可以使用putExtra(Serializable..)
方法的Intent#putExtra()
变体在intent extra中传递对象实例。
<强>伪代码强>:
//To pass:
intent.putExtra("MyClass", obj);
// To retrieve object in second Activity
getIntent().getSerializableExtra("MyClass");
注意:确保主要自定义类的每个嵌套类都已实现Serializable接口,以避免任何序列化异常。例如:
class MainClass implements Serializable {
public MainClass() {}
public static class ChildClass implements Serializable {
public ChildClass() {}
}
}
答案 1 :(得分:284)
使用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;
}
我们将名为dene
的对象从X活动发送到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");
就是这样。
答案 2 :(得分:111)
您可以使用此site为您的类生成Parcelable代码。
答案 3 :(得分:91)
调用活动时
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();
}
答案 4 :(得分:82)
根据我的经验,有三种主要解决方案,每种解决方案都有其缺点和优点:
实施Parcelable
实施可序列化
使用某种轻量级的事件总线库(例如,Greenrobot的EventBus或Square的Otto)
Parcelable - 快速和Android标准,但它有很多样板代码,并且需要硬编码字符串以便在将值拉出意图时进行参考(非强类型)。 / p>
Serializable - 接近零样板,但它是最慢的方法,并且在将值拉出意图时也需要硬编码字符串(非强类型)。
Event Bus - 零样板,最快的方法,并且不需要硬编码字符串,但它确实需要额外的依赖(尽管通常很轻,约40 KB)
我发布了围绕这三种方法的非常详细的比较,包括效率基准。
答案 5 :(得分:80)
使用gson将您的对象转换为JSON并通过intent传递它。在新的Activity中将JSON转换为对象。
在build.gradle
中,将其添加到您的依赖项
implementation 'com.google.code.gson:gson:2.8.4'
在您的Activity中,将对象转换为json-string:
Gson gson = new Gson();
String myJson = gson.toJson(vp);
intent.putExtra("myjson", myjson);
在接收活动中,将json-string转换回原始对象:
Gson gson = new Gson();
YourObject ob = gson.fromJson(getIntent().getStringExtra("myjson"), YourObject.class);
对于 Kotlin ,这是完全相同的
传递数据
val gson = Gson()
val intent = Intent(this, YourActivity::class.java)
intent.putExtra("identifier", gson.toJson(your_object))
startActivity(intent)
接收数据
val gson = Gson()
val yourObject = gson.fromJson<YourObject>(intent.getStringExtra("identifier"), YourObject::class.java)
答案 6 :(得分:39)
您还可以将对象的数据写入临时字符串和整数,并将它们传递给活动。当然,这样就可以传输数据,但不能传输对象本身。
但是如果你只想显示它们,而不是在另一种方法或类似的东西中使用该对象,那就足够了。我这样做只是为了在另一个活动中显示来自一个对象的数据。
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);
你也可以直接传递它们而不是temp ivars,但在我看来,这种方式更清晰。此外,您可以将temp ivars设置为null,以便GarbageCollector更快地清除它们。
祝你好运!旁注:覆盖toString()而不是编写自己的print方法。
如下面的评论中所述,这是您将数据重新用于其他活动的方式:
String fName = getIntent().getExtras().getInt("fname");
答案 7 :(得分:35)
我发现了一个简单的&amp;优雅的方法:
第一项活动的代码:
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
&amp; objReceived
具有相同的hashCode
,因此它们完全相同。
但是为什么我们可以用这种方式传递一个java对象呢?
实际上,android binder将为java对象创建全局JNI引用,并在没有此java对象的引用时释放此全局JNI引用。 binder将在Binder对象中保存此全局JNI引用。
*注意:除非两个活动在同一个进程中运行,否则此方法只能工作,否则抛出ClassCastException(ObjectWrapperForBinder)getIntent()。getExtras()。getBinder(&#34; object_value&#34;)* 强>
类ObjectWrapperForBinder defination
public class ObjectWrapperForBinder extends Binder {
private final Object mData;
public ObjectWrapperForBinder(Object data) {
mData = data;
}
public Object getData() {
return mData;
}
}
但是方法2有一点但是严重的问题,如果接收器无法恢复java对象(例如,在恢复java对象之前发生了一些异常,或者接收器Activity根本不存在),那么java对象将成为孤儿或内存泄漏, 方法1没有这个问题,因为android binder会处理这个异常
要远程调用java对象,我们将创建一个描述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();
}
通过这种方式,即使它们在不同的进程中运行,我们也可以在两个活动之间传递接口,并远程调用接口方法
方法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中异步并顺序执行。
实际上,android.os.Messenger也是一个aidl接口,如果你有android源代码,你可以找到一个名为IMessenger.aidl的文件
package android.os;
import android.os.Message;
/** @hide */
oneway interface IMessenger {
void send(in Message msg);
}
答案 8 :(得分:25)
我创建了一个包含临时对象的单例辅助类。
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;
}
}
不要将对象放在Intent中,而是使用IntentHelper:
IntentHelper.addObjectForKey(obj, "key");
在新活动中,您可以获取对象:
Object obj = (Object) IntentHelper.getObjectForKey("key");
请记住,一旦加载,就会删除该对象以避免不必要的引用。
答案 9 :(得分:23)
您可以通过多种方式访问其他类或Activity中的变量或对象。
一个。数据库
B中。共享偏好。
℃。对象序列化。
d。可以保存公共数据的类可以命名为Common Utilities。这取决于你。
电子。通过Intents和Parcelable Interface传递数据。
这取决于您的项目需求。
一个。的数据库强>
SQLite是一个嵌入Android的开源数据库。 SQLite支持标准的关系数据库功能,如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
℃。 对象序列化
如果我们想要保存对象状态以通过网络发送它,或者您也可以将它用于您的目的,则使用对象serlization。
使用Java bean并将其作为其中一个字段存储在其中,并使用getter和setter。
JavaBeans是具有属性的Java类。考虑到 属性作为私有实例变量。因为他们是私人的,唯一的方法 可以通过类中的方法从类外部访问它们。更改属性值的方法称为setter方法,检索属性值的方法称为getter方法。
public class VariableStorage implements Serializable {
private String inString;
public String getInString() {
return inString;
}
public void setInString(String inString) {
this.inString = inString;
}
}
使用
在邮件方法中设置变量VariableStorage variableStorage = new VariableStorage();
variableStorage.setInString(inString);
然后使用对象序列化来序列化此对象,并在其他类中反序列化此对象。
在序列化中,对象可以表示为包含对象数据的字节序列,以及有关对象类型和对象中存储的数据类型的信息。
将序列化对象写入文件后,可以从文件中读取并反序列化。也就是说,表示对象及其数据的类型信息和字节可用于在内存中重新创建对象。
如果你想要这方面的教程,请参考:
Get variable in other classes (Stack Overflow)
d。的 CommonUtilities 强>
您可以自己创建一个类,它可以包含您在项目中经常需要的常用数据。
<强>示例强>
public class CommonUtilities {
public static String className = "CommonUtilities";
}
电子。 通过意图传递数据
请参阅教程 Android – Parcel data to pass between Activities using Parcelable classes 以获取传递数据的选项。
答案 10 :(得分:19)
创建您自己的班级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;
}
}
使用onCreate()
方法
@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
课程中,您需要使用以下代码:
Intent intent=getIntent();
Customer cust=(Customer)intent.getSerializableExtra("bundle");
textViewName.setText(cust.getName());
textViewCity.setText(cust.getCity());
答案 11 :(得分:15)
最好的方法是在你的应用程序中有一个类(称之为Control),它将保存一个类型为'Customer'的静态变量(在你的情况下)。在活动A中初始化变量。
例如:
Control.Customer = CustomerClass;
然后转到活动B并从Control类中获取它。使用变量后不要忘记指定null,否则会浪费内存。
答案 12 :(得分:15)
public class MyClass implements Serializable{
Here is your instance variable
}
现在要在startActivity中传递此类的对象。只需使用:
Bundle b = new Bundle();
b.putSerializable("name", myClassObject);
intent.putExtras(b);
这可以在这里工作,因为MyClass实现了Serializable
。
答案 13 :(得分:12)
如果您选择使用Samuh描述的方式,请记住只能发送原始值。也就是说,值是可以参与的。因此,如果您的对象包含复杂对象,则不会跟随这些对象。例如,像Bitmap,HashMap等变量......这些都很难通过意图。
一般情况下,我建议您只发送原始数据类型作为附加内容,如String,int,boolean等。在您的情况下,它将是:String fname
,String lname
,int age
,和String address
。
我的观点:通过实施 ContentProvider , SDCard 等,可以更好地分享更复杂的对象。还可以使用静态变量 ,但这可能会导致容易出错的代码......
但同样,这只是我的主观意见。
答案 14 :(得分:8)
我使用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");
答案 15 :(得分:7)
您可以尝试使用该课程。限制是它不能在一个过程之外使用。
一项活动:
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);
}
}
答案 16 :(得分:6)
另一个Stack Overflow问题也讨论了这个问题。请看a solution to Passing data through intent using Serializable。重点是使用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
是专为Android设计的,并且效率高于Serializable
。您可以使用
Parcelable
课程
答案 17 :(得分:6)
从此活动开始另一个活动,并通过Bundle Object传递参数
Intent intent = new Intent(getBaseContext(), YourActivity.class);
intent.putExtra("USER_NAME", "xyz@gmail.com");
startActivity(intent);
检索另一项活动的数据(YourActivity)
String s = getIntent().getStringExtra("USER_NAME");
对于简单类型的数据类型,这是可以的。 但是如果你想在活动之间传递复杂的数据。你需要先将它序列化。
这里有员工模型
class Employee{
private String empId;
private int age;
print Double salary;
getters...
setters...
}
您可以使用谷歌提供的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);
答案 18 :(得分:5)
Crete类似bean类,并实现Serializable
接口。然后我们可以通过intent
方法传递它,例如:
intent.putExtra("class", BeanClass);
然后从其他活动中获取它,例如:
BeanClass cb = intent.getSerializableExtra("class");
答案 19 :(得分:5)
在您的自定义类中创建两个方法,如此
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"));
答案 20 :(得分:3)
Android Activity对象可以被销毁和重组。因此,您需要使用另一种方法来查看他们 - 或者他们创建的任何对象! - 起来也就是说,您可以作为静态类引用传递,但随后对象句柄(Java称为“引用”,就像SmallTalk一样;但它们不是C或汇编意义上的引用)以后可能会因为“功能”而无效Android OE的任何活动都可以被歼灭并在以后重组。
最初的问题是“如何在Android中将对象从一个活动传递到另一个活动”,没有人回答这个问题。当然,您可以序列化(Serializable,Parcelable,来自/来自JSON)并传递对象数据的副本,并且可以创建具有相同数据的新对象;但它不会有相同的引用/句柄。此外,许多其他人提到您可以将引用存储在静态存储中。除非Android决定onDestroy你的活动,否则这将有效。
因此,要真正解决原始问题,您需要进行静态查找,每个对象在重新创建时都会更新其引用。例如。如果调用onCreate,则每个Android Activity都会重新启动。您还可以查看某些人如何使用任务列表按名称搜索活动。 (系统暂时销毁此活动实例以节省空间..getRunningTasks,任务列表实际上是每个Activity的最新对象实例的专门列表。)
供参考:
停止: “活动完全被另一个活动遮挡(活动现在处于”背景“)。已停止的活动仍然存在(活动对象保留在内存中,它维护所有州和成员信息,但没有附加到窗口管理器。)但是,它不再对用户可见,并且当其他地方需要内存时系统可以将其杀死。“
的onDestroy “系统暂时销毁此实例以节省空间。”
因此,消息总线是一个可行的解决方案。它基本上是“平底船”。而不是尝试引用对象;然后,您重新设计您的设计以使用MessagePassing而不是SequentialCode。调试指数更难;但它可以让你忽略这些操作环境的理解。实际上,每个对象方法访问都被反转,因此调用者发布一个Message,并且该对象本身定义了该消息的处理程序。更多代码,但可以通过Android OE限制使其健壮。
如果您想要的只是顶级Activity(由于“Context”在任何地方都需要,Android应用程序中的典型事物),那么每当调用onResume时,您可以让每个Activity在静态全局空间中列为“top” 。然后你的AlertDialog或任何需要上下文的东西都可以从那里抓住它。此外,使用全局有点令人讨厌,但可以简化在任何地方上下传递上下文,当然,当您使用MessageBus时,无论如何IT都是全局的。
答案 21 :(得分:3)
是的,使用静态对象是使用自定义非可序列化对象执行此操作的最简单方法。
答案 22 :(得分:2)
我知道静态不好,但似乎我们不得不在这里使用它。 parceables / seriazables的问题在于这两个活动具有相同对象的重复实例=浪费内存和CPU。
public class IntentMailBox {
static Queue<Object> content = new LinkedList<Object>();
}
致电活动
IntentMailBox.content.add(level);
Intent intent = new Intent(LevelsActivity.this, LevelActivity.class);
startActivity(intent);
已调用的活动(请注意,当系统销毁并重新创建活动时,可能会多次调用 onCreate()和 onResume()。
if (IntentMailBox.content.size()>0)
level = (Level) IntentMailBox.content.poll();
else
// Here you reload what you have saved in onPause()
另一种方法是声明要在该类中传递的类的静态字段。它只会用于此目的。不要忘记它在onCreate中可以为null,因为你的app包已经被系统从内存中卸载并在以后重新加载。
请记住,您仍然需要处理活动生命周期,您可能希望将所有数据直接写入共享首选项,因为它具有复杂的数据结构。
答案 23 :(得分:1)
以上答案几乎都是正确的,但对于那些没有找到答案的人来说 Android拥有强大的类 Intent ,在它的帮助下,您不仅可以在Android之间共享数据,还可以在Android的另一个组件之间共享数据(广播接收器,内容服务提供我们使用ContetnResolver类无意图)。 在您的活动中,您构建了意图
Intent intent = new Intent(context,SomeActivity.class);
intent.putExtra("key",value);
startActivity(intent);
在您的接收活动中
public class SomeActivity extends AppCompactActivity {
public void onCreate(...){
...
SomeObject someObject = getIntent().getExtras().getParceable("key");
}
}
您必须在对象上实现Parceable或Serializable接口才能在活动之间共享。在对象上很难实现 Parcealbe 而不是 Serializable 接口,这就是为什么android有插件特别为此。下载并使用它
答案 24 :(得分:0)
在 Android 中有多种方法可以将对象从一个活动传递到另一个活动。但是它们都没有直接选项来简单地通过 Intent 或 Bundle 传递对象。您需要做的就是在 NextActivity 中解码对象,传递作为字符串,编码。示例如下:
Intent i = new Intent(this, nextActivity.class);
i.putExtra("fname", customer.getFirstName());
i.putExtra("lname", customer.getLastName());
i.putExtra("address", customer.getAddress());
startActivity(i);
第二种方法很简单,使用一个静态对象,可以很容易地从所有活动中访问。
第三,最后但并非最不重要的一点,您可以将对象存储到某个常量 Java 文件中,然后从任何活动中读取该对象值。
希望它能回答您的问题并解决问题。如果我的回答对您有用,请不要犹豫点赞。 :)
答案 25 :(得分:0)
我写了一个名为 intentparser
的库它真的很容易使用 将此添加到您的项目 gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
将此添加到您的应用程序gradle
dependencies {
implementation 'com.github.lau1944:intentparser:v$currentVersion'
}
使用扩展方法 putObject 传递对象
val testModel = TestModel(
text = "hello world",
isSuccess = false,
testNum = 1,
textModelSec = TextModelSec("second model")
)
startActivity(
Intent(this, ActivityTest::class.java).apply {
this.putObject(testModel)
}
)
从上一个活动中获取对象
val testModel = intent.getObject(TestModel::class.java)
答案 26 :(得分:0)
不可能序列化任何类型的对象。例如,您不能序列化承载代码而不是数据的委托方法或接口。 因此,我编写了一个'Box'类,您可以用来传递任何类型的数据而无需序列化。
1-用于将数据用于意图:
Intent I = new Intent(this, YourActivity.class);
CustomClass Date = new CustomClass();
Box.Add(I, "Name", Data);
2-用于从Intent检索数据:
CustomClass Data = Box.Get(getIntent(), "Name");
3-(要在使用后删除数据),请将此方法添加到您的活动中:
@Override
protected void onDestroy() {
Box.Remove(getIntent());
super.onDestroy();
}
4-并将此代码添加到您的项目中:
package ir.namirasoft.Utility;
import android.content.Intent;
import java.util.HashMap;
import java.util.Vector;
public class Box {
// Number
private static int Number = 1;
public static int NextNumber() {
return Number++;
}
//
private static String _Intent_Identifier = "_Intent_Identifier";
private static HashMap<Integer, Vector<Integer>> DeleteList = new HashMap<Integer, Vector<Integer>>();
private static HashMap<Integer, HashMap<String, Object>> ObjectList = new HashMap<Integer, HashMap<String, Object>>();
public static int GetIntent_Identifier(Intent I) {
int Intent_Identifier = I.getIntExtra(_Intent_Identifier, 0);
if (Intent_Identifier == 0)
I.putExtra(_Intent_Identifier, Intent_Identifier = NextNumber());
return Intent_Identifier;
}
public static void Add(Intent I, String Name, Object O) {
int Intent_Identifier = GetIntent_Identifier(I);
synchronized (ObjectList) {
if (!ObjectList.containsKey(Intent_Identifier))
ObjectList.put(Intent_Identifier, new HashMap<String, Object>());
ObjectList.get(Intent_Identifier).put(Name, O);
}
}
public static <T> T Get(Intent I, String Name) {
int Intent_Identifier = GetIntent_Identifier(I);
synchronized (DeleteList) {
DeleteList.remove(Intent_Identifier);
}
return (T) ObjectList.get(Intent_Identifier).get(Name);
}
public static void Remove(final Intent I) {
final int Intent_Identifier = GetIntent_Identifier(I);
final int ThreadID = NextNumber();
synchronized (DeleteList) {
if (!DeleteList.containsKey(Intent_Identifier))
DeleteList.put(Intent_Identifier, new Vector<Integer>());
DeleteList.get(Intent_Identifier).add(ThreadID);
}
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(60 * 1000);
} catch (InterruptedException e) {
}
synchronized (DeleteList) {
if (DeleteList.containsKey(Intent_Identifier))
if (DeleteList.get(Intent_Identifier).contains(ThreadID))
synchronized (ObjectList) {
ObjectList.remove(Intent_Identifier);
}
}
}
}).start();
}
}
** Box类是线程安全的。
答案 27 :(得分:0)
将一项活动传递给另一项活动:
startActivity(new Intent(getBaseContext(),GetActivity.class).putExtra("passingkey","passingvalue"));
获取价值观:
String myvalue= getIntent().getExtras("passingkey");
答案 28 :(得分:0)
我们可以将对象从一个活动传递到另一个活动:
SupplierDetails poSuppliersDetails = new SupplierDetails();
在poSuppliersDetails
内,我们有一些价值观。现在我将此对象发送到目标活动:
Intent iPODetails = new Intent(ActivityOne.this, ActivityTwo.class);
iPODetails.putExtra("poSuppliersDetails", poSuppliersDetails);
如何在ACtivityTwo中获取此内容:
private SupplierDetails supplierDetails;
supplierDetails =(SupplierDetails) getIntent().getSerializableExtra("poSuppliersDetails");
答案 29 :(得分:0)
我曾经用Pacelable或Serializable设置对象进行传输,但每当我向对象(模型)添加其他变量时,我必须将其全部注册。这太不方便了。
在活动或片段之间传输对象非常容易。
答案 30 :(得分:0)
将对象从一个活动传递到另一个活动。
(1)来源活动
Intent ii = new Intent(examreport_select.this,
BarChartActivity.class);
ii.putExtra("IntentExamResultDetail",
(Serializable) your List<ArraList<String>> object here);
startActivity(ii);
(2)目的地活动
List<ArrayList<String>> aa = (List<ArrayList<String>>) getIntent()
.getSerializableExtra("IntentExamResultDetail");
答案 31 :(得分:0)
我一直想知道为什么这不像调用其他活动的方法那么简单。我最近写了一个实用程序库,使它几乎就这么简单。你可以在这里查看(https://github.com/noxiouswinter/gnlib_android/wiki/gnlauncher)。
GNLauncher 会将对象/数据从另一个Activity等发送到Activity,就像调用Activity中的一个函数一样简单,并将所需的数据作为参数。它引入了类型安全性并删除了必须序列化的所有任务,使用字符串键附加到intent并在另一端撤消它们。
使用要在要启动的活动上调用的方法定义一个接口。
public interface IPayload {
public void sayHello(String name, int age);
}
在要启动的Activity上实现上面的接口。 当活动准备就绪时也通知GNLauncher。
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);
}
}
在另一个Activity中,获取上述Activity的代理并使用所需参数调用任何方法。
public class Activity_2 extends Activity {
public void onClick(View v) {
((IPayload)GNLauncher.get().getProxy(this, IPayload.class, Activity_1.class)).sayHello(name, age);
}
}
将启动第一个活动,并使用所需参数调用方法。
有关如何添加依赖项的信息,请参阅https://github.com/noxiouswinter/gnlib_android/wiki#prerequisites。
答案 32 :(得分:-1)
大家好,我看到了很多不错的选择,但我想知道为什么没有使用Binding?
传递一个对象的引用对我来说比序列化和消毒对象更有效,但我还没有深入研究,看看幕后是否会发生这种情况。
创建活页夹非常简单......
public class MyBinder extends Binder {
private Object myObject;
public MyBinder(Object object) {
myObject = object;
}
public Object getObject() {
return myObject;
}
}
创建parcelable以使用它并不是那么糟糕的。
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];
}
};
}
这个逻辑真的很酷,因为你实际上是将一个引用从活动传递给了活动。
我建议检查空值,以及Binder的实例是否是MyBinder!
并实现这一点你只是......
发送
Object myObject = "some object";
MyParcelable myParcelable = new MyParcelable();
myParcelable.setObject(myObject);
intent.putExtra("MyParcelable", myParcelable);
取回它
myParcelable = (MyParcelable) getIntent().getExtras().getParcelable("MyParcelable");
myObject = myParcelable.getObject();
哎呀有人可能会变得疯狂,让这个傻瓜成为一个真正的通用。
答案 33 :(得分:-19)
正如评论中所提到的,这个答案打破了封装和tightly couples组件,这很可能不是你想要的。最好的解决方案可能是让您的对象可以Parcelable或Serializable,正如其他响应所解释的那样。话虽如此,解决方案解决了这个问题。所以如果你知道你在做什么:
使用具有静态字段的类:
public class Globals {
public static Customer customer = new Customer();
}
您可以使用的活动内容:
活动自:
Globals.customer = myCustomerFromActivity;
活动目标:
myCustomerTo = Globals.customer;
这是传递活动信息的简便方法。