如何使用Intents将对象从一个Android Activity发送到另一个?

UMA*_*MAR 823 android android-intent android-activity

如何使用类Intent的方法将自定义类型的对象从一个Activity传递到另一个ActivityputExtra()

Jer*_*gan 736

如果您只是传递物体,那么Parcelable就是为此设计的.它需要比使用Java的本机序列使用多一点的努力,但它的方式更快(我的意思是这样,WAY更快).

从文档中,一个如何实现的简单示例是:

// simple class that just has one member property as an example
public class MyParcelable implements Parcelable {
    private int mData;

    /* everything below here is for implementing Parcelable */

    // 99.9% of the time you can just ignore this
    @Override
    public int describeContents() {
        return 0;
    }

    // write your object's data to the passed-in Parcel
    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(mData);
    }

    // this is used to regenerate your object. All Parcelables must have a CREATOR that implements these two methods
    public static final Parcelable.Creator<MyParcelable> CREATOR = new Parcelable.Creator<MyParcelable>() {
        public MyParcelable createFromParcel(Parcel in) {
            return new MyParcelable(in);
        }

        public MyParcelable[] newArray(int size) {
            return new MyParcelable[size];
        }
    };

    // example constructor that takes a Parcel and gives you an object populated with it's values
    private MyParcelable(Parcel in) {
        mData = in.readInt();
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果您要从给定的包中检索多个字段,则必须按照放入它们的顺序(即采用FIFO方法)执行此操作.

一旦你的对象实现了Parcelable,只需将它们放入你的Intent with putExtra():

Intent i = new Intent();
i.putExtra("name_of_extra", myParcelableObject);
Run Code Online (Sandbox Code Playgroud)

然后你可以使用getParcelableExtra()将它们拉回来:

Intent i = getIntent();
MyParcelable myParcelableObject = (MyParcelable) i.getParcelableExtra("name_of_extra");
Run Code Online (Sandbox Code Playgroud)

如果您的Object类实现了Parcelable和Serializable,那么请确保您执行以下操作之一:

i.putExtra("parcelable_extra", (Parcelable) myParcelableObject);
i.putExtra("serializable_extra", (Serializable) myParcelableObject);
Run Code Online (Sandbox Code Playgroud)

  • 为什么不能在没有这一切的情况下传递对象?我们想传递一个已经在内存中的对象. (296认同)
  • @tecnotron它的beacuse应用程序在不同的进程中,并且具有单独的内存地址空间,你不能只在你的进程中向内存块发送指针(引用)并期望它在另一个进程中可用. (108认同)
  • 如果mData是一个对象(例如JSONObject)而不是int,它将如何实现呢? (14认同)
  • 如果我不能使对象的类可串行化或Parceable,我该怎么办? (12认同)
  • @ceklock背后的原因如下:当活动落后并且后来从内存中被杀死,然后当用户从最近的菜单中打开它时,它必须创建它停止的活动.它必须是相同的UI.在这种情况下,Object不在内存中.但意图是. (11认同)
  • @Amel你能举个例子吗? (3认同)
  • 糟糕的设计,只是说 (3认同)
  • 可分配的场发生器:www.parcelabler.com来自http://stackoverflow.com/a/26757130/1277350 (2认同)

Dav*_*und 189

您需要将对象序列化为某种字符串表示形式.一个可能的字符串表示是JSON,如果你问我,最简单的方法之一是在Android中序列化到/来自JSON,是通过谷歌GSON.

在这种情况下,您只需输入字符串返回值(new Gson()).toJson(myObject);并检索字符串值,然后使用fromJson它将其重新转换为对象.

但是,如果您的对象不是很复杂,那么开销可能不值得,您可以考虑传递对象的单独值.

  • 我猜是因为fiXedd的答案在没有使用外部库的情况下解决了同样的问题,这种方式非常可取,没有人应该有理由通过我提供的解决方案(当时没有意识到) fiXedd的精彩解决方案) (18认同)
  • 不一定是个坏主意,尤其是 因为Gson比你想要发送的所有对象实现parcelable更简单. (15认同)
  • 很好的答案,虽然完整的解决方案是`String s =(new Gson().toJson(client));`然后`Cli client = new Gson().fromJson(s,Cli.class);` (15认同)
  • 为什么这得到-1?有人可以解释什么是错的吗? (7认同)
  • 因为我在我的应用程序中使用gson这是一个非常简单和好的方式! (7认同)
  • 我认为这是正确的.此外,JSON是一种更适合客户端/服务器而非线程到线程的协议. (5认同)
  • 为了方便起见,在许多应用程序中,如果性能不是优先考虑的话,GSON方法会获胜.它的编码速度更快,可能已经在你的应用程序的其他地方使用,并且更容易理解.代码可维护性增加.所以你的CW答案得到+1. (4认同)
  • +1解决方案.我完全忘记了我已经使用Gson与Retrofit一起使用了,这使得***比每个对象实现`Parcelable`容易了一百万倍.如果您使用Web API /库(如Retrofit)执行*任何*,Gson绝对值得使用,因为它实际上是2行代码来放置或获取`Intent`附加功能.我将添加(@mobibob)JSON只是一种数据交换格式,并且将对象转换为JSON字符串以在线程之间发送(因为`Intent.putExtra()`已经存在),在我看来,或多或少是相同的作为客户/服务器. (4认同)

Sri*_*har 149

您可以通过意图发送可序列化对象

// send where details is object
ClassName details = new ClassName();
Intent i = new Intent(context, EditActivity.class);
i.putExtra("Editing", details);
startActivity(i);


//receive
ClassName model = (ClassName) getIntent().getSerializableExtra("Editing");

And 

Class ClassName implements Serializable {
} 
Run Code Online (Sandbox Code Playgroud)

  • "Serializable在Android上很滑稽.事实上,在许多情况下,Borderline无用." 看看http://stackoverflow.com/questions/5550670/benefit-of-using-parcelable-instead-of-serializing-object (5认同)
  • 如果要序列化许多对象,@ Seraphim的性能很重要,但是用户不会注意到序列化一个对象需要1毫秒还是10毫秒。如果一个额外的意图已经可以“序列化”而不是“可打包的”,那么将其设置为“可打包的”就很麻烦了。 (3认同)
  • 你也可以通过意图发送Parcelable对象. (2认同)

Pet*_*tai 64

对于您知道将在应用程序中传递数据的情况,请使用"globals"(如静态类)

以下Dianne Hackborn(hackbod - 谷歌Android软件工程师)对此事所说的话:

对于您知道活动在同一进程中运行的情况,您可以通过全局变量共享数据.例如,您可以拥有一个全局HashMap<String, WeakReference<MyInterpreterState>> ,当您创建一个新的MyInterpreterState时,它会为它创建一个唯一的名称并将其放入哈希映射中; 要将该状态发送到另一个活动,只需将唯一名称放入哈希映射中,当第二个活动启动时,它可以从哈希映射中检索具有其接收名称的MyInterpreterState.

  • 是的,我觉得很奇怪,我们得到这些意图使用,然后一位顶级工程师告诉我们只使用全局数据.但它直接来自马口. (23认同)

Ped*_*mão 48

您的类应该实现Serializable或Parcelable.

public class MY_CLASS implements Serializable
Run Code Online (Sandbox Code Playgroud)

完成后,您可以在putExtra上发送一个对象

intent.putExtra("KEY", MY_CLASS_instance);

startActivity(intent);
Run Code Online (Sandbox Code Playgroud)

要获得额外的东西你只需要做

Intent intent = getIntent();
MY_CLASS class = (MY_CLASS) intent.getExtras().getSerializable("KEY");
Run Code Online (Sandbox Code Playgroud)

如果你的类实现Parcelable使用next

MY_CLASS class = (MY_CLASS) intent.getExtras().getParcelable("KEY");
Run Code Online (Sandbox Code Playgroud)

我希望它有所帮助:D

  • 你的类必须实现`Serializable`是错误的.例如,该类可以实现`Parcelable`. (6认同)

Sam*_*Sam 34

快速需要的简短回答

1.将您的类实现为Serializable.

如果您有任何内部类,请不要忘记将它们实现为Serializable !!

public class SportsData implements  Serializable
public class Sport implements  Serializable

List<Sport> clickedObj;
Run Code Online (Sandbox Code Playgroud)

2.将您的对象置于Intent中

 Intent intent = new Intent(SportsAct.this, SportSubAct.class);
            intent.putExtra("sport", clickedObj);
            startActivity(intent);
Run Code Online (Sandbox Code Playgroud)

3.在另一个活动类中接收您的对象

Intent intent = getIntent();
    Sport cust = (Sport) intent.getSerializableExtra("sport");
Run Code Online (Sandbox Code Playgroud)


Vla*_*lad 27

如果你的对象类实现了Serializable,你不需要做任何其他事情,你可以传递一个可序列化的对象.
这就是我用的东西.


Ish*_*ndo 19

在你的班级实现序列化

public class Place implements Serializable{
        private int id;
        private String name;

        public void setId(int id) {
           this.id = id;
        }
        public int getId() {
           return id;
        }
        public String getName() {
           return name;
        }

        public void setName(String name) {
           this.name = name;
        }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以在意图中传递这个对象

     Intent intent = new Intent(this, SecondAct.class);
     intent.putExtra("PLACE", Place);
     startActivity(intent);
Run Code Online (Sandbox Code Playgroud)

在第二个活动中你可以获得这样的数据

     Place place= (Place) getIntent().getSerializableExtra("PLACE");
Run Code Online (Sandbox Code Playgroud)

但是当数据变大时,这种方法会很慢.


om2*_*345 16

你可以使用android BUNDLE来做到这一点.

从您的类创建一个Bundle,如:

public Bundle toBundle() {
    Bundle b = new Bundle();
    b.putString("SomeKey", "SomeValue");

    return b;
}
Run Code Online (Sandbox Code Playgroud)

然后使用INTENT传递此包.现在,您可以通过传递bundle来重新创建类对象

public CustomClass(Context _context, Bundle b) {
    context = _context;
    classMember = b.getString("SomeKey");
}
Run Code Online (Sandbox Code Playgroud)

在Custom类中声明并使用.

  • 恕我直言,优于直接 Parcelable 实现。Bundle 本身实现了 Parcelable,因此您仍然可以获得性能增益,同时避免自己实现它的所有麻烦。相反,您可以使用键值对来存储和检索数据,这比仅依赖顺序更强大。 (2认同)

Nik*_*wal 16

您可以通过多种方式访问​​其他类或Activity中的变量或对象.

A.数据库

B.共享偏好.

C.对象序列化.

D.可以保存公共数据的类可以命名为依赖于您的Common Utilities.

E.通过Intents和Parcelable Interface传递数据.

这取决于您的项目需求.

A. 数据库

SQLite是一个嵌入到Android中的开源数据库.SQLite支持标准的关系数据库功能,如SQL语法,事务和预准备语句.

教程 - http://www.vogella.com/articles/AndroidSQLite/article.html

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();
Run Code Online (Sandbox Code Playgroud)

使用putString(),putBoolean(),putInt(),putFloat(),putLong()可以保存所需的dtatype.

如何获取

SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
String userName = sharedPref.getString("userName", "Not Available");
Run Code Online (Sandbox Code Playgroud)

http://developer.android.com/reference/android/content/SharedPreferences.html

C. 对象序列化

如果我们想要保存对象状态以通过网络发送它,或者您也可以将它用于您的目的,则使用对象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;
    }


}
Run Code Online (Sandbox Code Playgroud)

使用在邮件方法中设置变量

VariableStorage variableStorage = new VariableStorage();
variableStorage.setInString(inString);
Run Code Online (Sandbox Code Playgroud)

然后使用对象序列化来序列化此对象,并在其他类中反序列化此对象.

在序列化中,对象可以表示为包含对象数据的字节序列,以及有关对象类型和对象中存储的数据类型的信息.

将序列化对象写入文件后,可以从文件中读取并反序列化,即表示对象及其数据的类型信息和字节可用于在内存中重新创建对象.

如果您想要这方面的教程,请参阅此链接

http://javawithswaranga.blogspot.in/2011/08/serialization-in-java.html

在其他类中获取变量

D. CommonUtilities

您可以自己创建一个类,它可以包含您在项目中经常需要的常用数据.

样品

public class CommonUtilities {

    public static String className = "CommonUtilities";

}
Run Code Online (Sandbox Code Playgroud)

E. 通过意图传递数据

有关传递数据的此选项,请参阅本教程.

http://shri.blog.kraya.co.uk/2010/04/26/android-parcel-data-to-pass-between-activities-using-parcelable-classes/


use*_*237 15

感谢您提供帮助,但我找到了一个可选的解决方案

 public class getsetclass implements Serializable {
        private int dt = 10;
    //pass any object, drwabale 
        public int getDt() {
            return dt;
        }

        public void setDt(int dt) {
            this.dt = dt;
        }
    }
Run Code Online (Sandbox Code Playgroud)

在活动一中

getsetclass d = new getsetclass ();
                d.setDt(50);
                LinkedHashMap<String, Object> obj = new LinkedHashMap<String, Object>();
                obj.put("hashmapkey", d);
            Intent inew = new Intent(SgParceLableSampelActivity.this,
                    ActivityNext.class);
            Bundle b = new Bundle();
            b.putSerializable("bundleobj", obj);
            inew.putExtras(b);
            startActivity(inew);
Run Code Online (Sandbox Code Playgroud)

获取活动2中的数据

 try {  setContentView(R.layout.main);
            Bundle bn = new Bundle();
            bn = getIntent().getExtras();
            HashMap<String, Object> getobj = new HashMap<String, Object>();
            getobj = (HashMap<String, Object>) bn.getSerializable("bundleobj");
            getsetclass  d = (getsetclass) getobj.get("hashmapkey");
        } catch (Exception e) {
            Log.e("Err", e.getMessage());
        }
Run Code Online (Sandbox Code Playgroud)


MBH*_*MBH 14

我使用Gson的强大而简单的api来在活动之间发送对象,

// This is the object to be sent, can be any object
public class AndroidPacket {

    public String CustomerName;

   //constructor
   public AndroidPacket(String cName){
       CustomerName = cName;
   }   
   // other fields ....


    // You can add those functions as LiveTemplate !
    public String toJson() {
        Gson gson = new Gson();
        return gson.toJson(this);
    }

    public static AndroidPacket fromJson(String json) {
        Gson gson = new Gson();
        return gson.fromJson(json, AndroidPacket.class);
    }
}
Run Code Online (Sandbox Code Playgroud)

将您添加到要发送的对象的2个函数

用法

将对象从A发送到B.

    // Convert the object to string using Gson
    AndroidPacket androidPacket = new AndroidPacket("Ahmad");
    String objAsJson = androidPacket.toJson();

    Intent intent = new Intent(A.this, B.class);
    intent.putExtra("my_obj", objAsJson);
    startActivity(intent);
Run Code Online (Sandbox Code Playgroud)

收到B

@Override
protected void onCreate(Bundle savedInstanceState) {        
    Bundle bundle = getIntent().getExtras();
    String objAsJson = bundle.getString("my_obj");
    AndroidPacket androidPacket = AndroidPacket.fromJson(objAsJson);

    // Here you can use your Object
    Log.d("Gson", androidPacket.CustomerName);
}
Run Code Online (Sandbox Code Playgroud)

我几乎在我做的每个项目中使用它,我没有性能问题.


小智 9

我在同样的问题上挣扎.我通过使用静态类来解决它,在HashMap中存储我想要的任何数据.最重要的是,我使用标准Activity类的扩展,我已经覆盖了onCreate onDestroy上的方法来隐藏数据传输和数据清除.一些荒谬的设置必须改变,例如方向处理.

注释:不提供要传递给另一个活动的一般对象是痛苦的屁股.这就像在膝盖上射击并希望赢得100米."Parcable"不是一个充分的替代品.它让我开怀大笑...我不想将这个界面实现到我的无技术API,因为我想要引入一个新的图层......怎么可能,我们在移动编程中离目标太远了现代范式......


Rud*_*udi 9

在您的第一个活动中:

intent.putExtra("myTag", yourObject);
Run Code Online (Sandbox Code Playgroud)

在你的第二个:

myCustomObject myObject = (myCustomObject) getIntent().getSerializableExtra("myTag");
Run Code Online (Sandbox Code Playgroud)

不要忘记使自定义对象可序列化:

public class myCustomObject implements Serializable {
...
}
Run Code Online (Sandbox Code Playgroud)


Saa*_*ooq 7

另一种方法是使用Application对象(android.app.Application).您可以在AndroidManifest.xml文件中将其定义为:

<application
    android:name=".MyApplication"
    ...
Run Code Online (Sandbox Code Playgroud)

然后,您可以从任何活动中调用它并将对象保存到Application类中.

在FirstActivity中:

MyObject myObject = new MyObject();
MyApplication app = (MyApplication) getApplication();
app.setMyObject(myObject);
Run Code Online (Sandbox Code Playgroud)

在SecondActivity中,执行:

MyApplication app = (MyApplication) getApplication();
MyObject retrievedObject = app.getMyObject(myObject);
Run Code Online (Sandbox Code Playgroud)

如果您具有具有应用程序级别范围的对象,即在整个应用程序中必须使用它们,这将非常方便.Parcelable如果要显式控制对象范围或范围有限,则该方法仍然更好.

但这Intents完全避免了使用.我不知道他们是否适合你.我使用它的另一种方法是int通过意图发送对象的标识符,并检索对象中Maps中的Application对象.


Dav*_*kro 6

在您的类模型(Object)中实现Serializable,例如:

public class MensajesProveedor implements Serializable {

    private int idProveedor;


    public MensajesProveedor() {
    }

    public int getIdProveedor() {
        return idProveedor;
    }

    public void setIdProveedor(int idProveedor) {
        this.idProveedor = idProveedor;
    }


}
Run Code Online (Sandbox Code Playgroud)

和你的第一个活动

MensajeProveedor mp = new MensajeProveedor();
Intent i = new Intent(getApplicationContext(), NewActivity.class);
                i.putExtra("mensajes",mp);
                startActivity(i);
Run Code Online (Sandbox Code Playgroud)

和你的第二个活动(NewActivity)

        MensajesProveedor  mensajes = (MensajesProveedor)getIntent().getExtras().getSerializable("mensajes");
Run Code Online (Sandbox Code Playgroud)

祝好运!!


Adn*_*aki 6

public class SharedBooking implements Parcelable{

    public int account_id;
    public Double betrag;
    public Double betrag_effected;
    public int taxType;
    public int tax;
    public String postingText;

    public SharedBooking() {
        account_id = 0;
        betrag = 0.0;
        betrag_effected = 0.0;
        taxType = 0;
        tax = 0;
        postingText = "";
    }

    public SharedBooking(Parcel in) {
        account_id = in.readInt();
        betrag = in.readDouble();
        betrag_effected = in.readDouble();
        taxType = in.readInt();
        tax = in.readInt();
        postingText = in.readString();
    }

    public int getAccount_id() {
        return account_id;
    }
    public void setAccount_id(int account_id) {
        this.account_id = account_id;
    }
    public Double getBetrag() {
        return betrag;
    }
    public void setBetrag(Double betrag) {
        this.betrag = betrag;
    }
    public Double getBetrag_effected() {
        return betrag_effected;
    }
    public void setBetrag_effected(Double betrag_effected) {
        this.betrag_effected = betrag_effected;
    }
    public int getTaxType() {
        return taxType;
    }
    public void setTaxType(int taxType) {
        this.taxType = taxType;
    }
    public int getTax() {
        return tax;
    }
    public void setTax(int tax) {
        this.tax = tax;
    }
    public String getPostingText() {
        return postingText;
    }
    public void setPostingText(String postingText) {
        this.postingText = postingText;
    }
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(account_id);
        dest.writeDouble(betrag);
        dest.writeDouble(betrag_effected);
        dest.writeInt(taxType);
        dest.writeInt(tax);
        dest.writeString(postingText);

    }

    public static final Parcelable.Creator<SharedBooking> CREATOR = new Parcelable.Creator<SharedBooking>()
    {
        public SharedBooking createFromParcel(Parcel in)
        {
            return new SharedBooking(in);
        }
        public SharedBooking[] newArray(int size)
        {
            return new SharedBooking[size];
        }
    };

}
Run Code Online (Sandbox Code Playgroud)

传递数据:

Intent intent = new Intent(getApplicationContext(),YourActivity.class);
Bundle bundle = new Bundle();
i.putParcelableArrayListExtra("data", (ArrayList<? extends Parcelable>) dataList);
intent.putExtras(bundle);
startActivity(intent);
Run Code Online (Sandbox Code Playgroud)

检索数据:

Bundle bundle = getIntent().getExtras();
dataList2 = getIntent().getExtras().getParcelableArrayList("data");
Run Code Online (Sandbox Code Playgroud)


UMA*_*MAR 5

我发现最简单的解决方案是创建一个带有getter setter的静态数据成员的类.

从一个活动设置并从另一个活动获取该对象.

活动A.

mytestclass.staticfunctionSet("","",""..etc.);
Run Code Online (Sandbox Code Playgroud)

活动b

mytestclass obj= mytestclass.staticfunctionGet();
Run Code Online (Sandbox Code Playgroud)

  • 记住不要放大胖物.该对象的生命周期与应用程序的生命周期相同.永远不会存储视图.此方法还可以保证内存泄漏. (9认同)
  • WTF?其他两个答案要好得多。 (2认同)

Jin*_*cis 5

使用google的Gson库,你可以将对象传递给另一个活动。实际上,我们将以json字符串的形式转换对象,在传递给其他活动后,我们将再次重新转换为这样的对象

考虑这样的 bean 类

 public class Example {
    private int id;
    private String name;

    public Example(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
Run Code Online (Sandbox Code Playgroud)

我们需要传递Example类的对象

Example exampleObject=new Example(1,"hello");
String jsonString = new Gson().toJson(exampleObject);
Intent nextIntent=new Intent(this,NextActivity.class);
nextIntent.putExtra("example",jsonString );
startActivity(nextIntent);
Run Code Online (Sandbox Code Playgroud)

为了读取,我们需要在 NextActivity 中进行相反的操作

 Example defObject=new Example(-1,null);
    //default value to return when example is not available
    String defValue= new Gson().toJson(defObject);
    String jsonString=getIntent().getExtras().getString("example",defValue);
    //passed example object
    Example exampleObject=new Gson().fromJson(jsonString,Example .class);
Run Code Online (Sandbox Code Playgroud)

在gradle中添加这个依赖

compile 'com.google.code.gson:gson:2.6.2'
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

589910 次

最近记录:

6 年,3 月 前