Làm cách nào để gửi một đối tượng từ Hoạt động Android này sang Hoạt động khác bằng Ý định?


849

Làm cách nào tôi có thể truyền một đối tượng của loại tùy chỉnh từ Hoạt động này sang Hoạt động khác bằng putExtra()phương thức của lớp Ý định ?


@UMMA - bạn không cần tiếp tục đánh dấu các câu hỏi của mình là "Wiki cộng đồng". Hãy xem tại đây: meta.stackexchange.com/questions/11740/ Kẻ
Dave Webb

1
@Paresh: liên kết bạn cung cấp bị hỏng. bạn có thể cung cấp một sự thay thế?
antiplex



tôi tìm thấy một stackoverflow
lịch.com/a/37774966/6456129

Câu trả lời:


751

Nếu bạn chỉ truyền các đối tượng xung quanh thì Parcelable được thiết kế cho việc này. Nó đòi hỏi một chút nỗ lực để sử dụng hơn là sử dụng tuần tự hóa riêng của Java, nhưng nó nhanh hơn (và ý tôi là, CÁCH nhanh hơn).

Từ các tài liệu, một ví dụ đơn giản cho cách thực hiện là:

// 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();
    }
}

Quan sát rằng trong trường hợp bạn có nhiều hơn một trường để lấy từ một Bưu kiện cụ thể, bạn phải thực hiện việc này theo cùng thứ tự bạn đặt chúng vào (nghĩa là theo cách tiếp cận của FIFO).

Một khi bạn có các đối tượng của bạn thực hiện Parcelablenó chỉ là một vấn đề đưa vào bạn Intents với putExtra () :

Intent i = new Intent();
i.putExtra("name_of_extra", myParcelableObject);

Sau đó, bạn có thể kéo chúng ra ngoài với getParcelableExtra () :

Intent i = getIntent();
MyParcelable myParcelableObject = (MyParcelable) i.getParcelableExtra("name_of_extra");

Nếu Lớp đối tượng của bạn triển khai Parcelable và serializable thì hãy đảm bảo bạn thực hiện theo một trong các cách sau:

i.putExtra("parcelable_extra", (Parcelable) myParcelableObject);
i.putExtra("serializable_extra", (Serializable) myParcelableObject);

14
Làm thế nào điều này sẽ được thực hiện trong đó mData là một đối tượng (ví dụ JSONObject) chứ không phải int?
Peter Ajtai

301
Tại sao không thể vượt qua đối tượng mà không có tất cả điều này? Chúng tôi muốn vượt qua một đối tượng đã có trong bộ nhớ.
ceklock

110
@tecnotron Các ứng dụng beacuse của nó nằm trong các quy trình khác nhau và có không gian địa chỉ bộ nhớ riêng biệt, bạn không thể gửi con trỏ (tham chiếu) đến khối bộ nhớ trong quy trình của mình và hy vọng nó sẽ khả dụng trong quy trình khác.
marcinj

12
Tôi phải làm gì nếu tôi không thể làm cho lớp của đối tượng nối tiếp hoặc có thể di chuyển được?
Amel Jose

11
@ceklock lý do đằng sau điều này là như sau: Khi hoạt động đi phía sau và sau đó bị giết khỏi bộ nhớ, và sau đó khi người dùng mở nó từ menu lõm, nó phải tạo ra Hoạt động nơi nó dừng lại. Nó phải là cùng một giao diện người dùng. Đối tượng không có trong bộ nhớ trong trường hợp này. Nhưng ý định là thế.
tasomaniac

194

Bạn sẽ cần phải tuần tự hóa đối tượng của mình thành một loại biểu diễn chuỗi. Một đại diện chuỗi có thể là JSON và một trong những cách dễ nhất để tuần tự hóa đến / từ JSON trong Android, nếu bạn hỏi tôi, là thông qua Google GSON .

Trong trường hợp đó, bạn chỉ cần đặt giá trị trả về chuỗi từ (new Gson()).toJson(myObject);và lấy giá trị chuỗi và sử dụng fromJsonđể biến nó trở lại đối tượng của bạn.

Tuy nhiên, nếu đối tượng của bạn không quá phức tạp, thì nó có thể không có giá trị chung và bạn có thể xem xét chuyển các giá trị riêng biệt của đối tượng thay thế.


19
Tôi đoán bởi vì câu trả lời của fiXedd giải quyết vấn đề tương tự mà không cần sử dụng các thư viện bên ngoài, theo cách đơn giản là rất thích, rằng không ai có thể có lý do để đi theo giải pháp mà tôi đã cung cấp (lúc đó, không biết giải pháp tuyệt vời của fiXedd)
David Hedlund

5
Tôi nghĩ rằng điều đó là đúng. Hơn nữa, JSON là một giao thức thích hợp hơn cho máy khách / máy chủ và không phải là luồng-luồng.
mobibob

16
Không nhất thiết là một ý tưởng tồi, đặc biệt. vì Gson sử dụng đơn giản hơn nhiều so với triển khai có thể phân chia cho tất cả các đối tượng bạn muốn gửi.
uvesten

7
Như tôi đang sử dụng gson trong ứng dụng của mình, đây là một cách thực sự dễ dàng và tốt đẹp!
Lars

16
Câu trả lời hay, mặc dù giải pháp hoàn chỉnh sẽ là String s = (new Gson().toJson(client));và sau đóCli client = new Gson().fromJson(s, Cli.class);
Joaquin Iurchuk

155

Bạn có thể gửi đối tượng tuần tự hóa thông qua ý định

// 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 {
} 

2
bạn cũng có thể gửi các đối tượng Parcelable thông qua ý định.
tony gil

6
"Nối tiếp là chậm về mặt hài hước trên Android. Trên thực tế, biên giới vô dụng trong nhiều trường hợp." nhìn vào stackoverflow.com/questions/5550670/ khăn
Seraphim's

Điều gì xảy ra nếu hoạt động đã chạy, có cần phải thực hiện startActivity (i) không; ? Ý tôi là, tôi có thể thực hiện hoạt động A gọi hoạt động B và trả lại dữ liệu cho hoạt động A không? tôi có bối rối không
Francisco Corrales Morales

3
Hiệu suất của @ Seraphim có vấn đề nếu bạn tuần tự hóa nhiều đối tượng, nhưng người dùng sẽ không chú ý nếu việc xâu chuỗi một đối tượng mất 1 ms hoặc 10 ms. Nếu một mục đích bổ sung đã có Serializablenhưng không Parcelable, nó hiếm khi gây rắc rối để thực hiện nó Parcelable.
Kevin Krumwiede

67

Đối với các tình huống mà bạn biết bạn sẽ truyền dữ liệu trong một ứng dụng, hãy sử dụng "toàn cầu" (như Lớp tĩnh)

Dưới đây là những gì Dianne Hackborn (hackbod - một Kỹ sư phần mềm Google Android) đã nói về vấn đề này:

Đối với các tình huống mà bạn biết các hoạt động đang chạy trong cùng một quy trình, bạn chỉ có thể chia sẻ dữ liệu qua toàn cầu. Ví dụ: bạn có thể có một toàn cầu HashMap<String, WeakReference<MyInterpreterState>> và khi bạn tạo một MyInterpreterState mới sẽ đưa ra một tên duy nhất cho nó và đặt nó vào bản đồ băm; để gửi trạng thái đó đến một hoạt động khác, chỉ cần đặt tên duy nhất vào bản đồ băm và khi hoạt động thứ hai được bắt đầu, nó có thể truy xuất MyInterpreterState từ bản đồ băm với tên mà nó nhận được.


25
vâng tôi thấy lạ là chúng tôi được cung cấp những Ý định này để sử dụng, và sau đó một kỹ sư hàng đầu bảo chúng tôi chỉ sử dụng toàn cầu cho dữ liệu của mình. Nhưng nó là thẳng từ miệng ngựa.
Richard Le Mesurier

1
Sẽ không sự kết hợp yếu ở đây là nạn nhân của việc thu gom rác?
uLYsseus

1
@uLYsseus nghĩ rằng đó là ý tưởng, một khi bạn đã hoàn thành chúng trong các hoạt động ... vì vậy khi các hoạt động liên quan bị phá hủy, nó sẽ cho phép nó hoạt động
Peter Ajtai

1
@RichardLeMesurier Tôi cũng nghĩ như vậy, nhưng sau đó tôi đã xem bài đăng trên Google Groups được giới thiệu ở trên từ Dianne Hackborn và cô ấy đề cập rằng vấn đề thực sự duy nhất với toàn cầu là khi sử dụng ý định ngầm (có thể khởi chạy một hoạt động bên ngoài gói của bạn ). Điều này có ý nghĩa, như Dianne đề cập, bởi vì những hoạt động đó rất có thể không có kiến ​​thức về các loại tùy chỉnh mà bạn đang truyền cho chúng. Khi tôi đọc được điều đó, tôi đã hiểu rõ hơn tại sao toàn cầu có thể không phải là một tuyến đường tồi tệ như vậy trong các tình huống và tôi đoán rằng tôi sẽ chia sẻ trong trường hợp những người khác cũng tò mò
BMB

các ý định được áp đảo đến mức mà ý định có thể được chuyển sang một máy tính khác. đó rõ ràng không phải là một cách tốt để làm bất cứ điều gì khi bạn thực sự chỉ có một quá trình bạn đang làm quen. Lý do tại sao nó không tốt: sử dụng bộ nhớ, sử dụng cpu, sử dụng pin. người cuối cùng đặc biệt đưa ra các lựa chọn thiết kế với ý định khá bối rối trong nhận thức muộn màng. có những người khăng khăng rằng họ là một ý tưởng tốt, thường là vì "google đã nói như vậy".
Lassi Kinnunen

49

Lớp học của bạn nên thực hiện Nối tiếp hoặc Parcelable.

public class MY_CLASS implements Serializable

Sau khi hoàn thành, bạn có thể gửi một đối tượng trên putExtra

intent.putExtra("KEY", MY_CLASS_instance);

startActivity(intent);

Để có được tính năng bổ sung, bạn chỉ phải làm

Intent intent = getIntent();
MY_CLASS class = (MY_CLASS) intent.getExtras().getSerializable("KEY");

Nếu lớp của bạn thực hiện Parcelable sử dụng tiếp theo

MY_CLASS class = (MY_CLASS) intent.getExtras().getParcelable("KEY");

Tôi hy vọng nó sẽ giúp: D


6
Lớp của bạn phải thực hiện Serializablelà sai. Các lớp có thể thực hiện Parcelableví dụ.
Marc Plano-Lesay

sự khác biệt giữa Parcelable và serializable @Kernald là gì? về mặt thời gian xử lý thì nó chậm hơn / không thực hành tốt nhất hay sao?
gumuruh

Trong khi Serializablelà một giao diện Java tiêu chuẩn, Parcelablelà dành riêng cho Android. Về hiệu suất, Parcelable hiệu quả hơn: developerphil.com/parcelable-vs-serializable
Marc Plano-Lesay 17/07/14

35

Câu trả lời ngắn gọn cho nhu cầu nhanh

1. Triển khai lớp của bạn để tuần tự hóa.

Nếu bạn có bất kỳ Lớp bên trong nào, đừng quên triển khai chúng để Nối tiếp quá !!

public class SportsData implements  Serializable
public class Sport implements  Serializable

List<Sport> clickedObj;

2. Đặt đối tượng của bạn vào Ý định

 Intent intent = new Intent(SportsAct.this, SportSubAct.class);
            intent.putExtra("sport", clickedObj);
            startActivity(intent);

3. Và nhận đối tượng của bạn trong Lớp Hoạt động khác

Intent intent = getIntent();
    Sport cust = (Sport) intent.getSerializableExtra("sport");


Bạn có thể đạt được điều tương tự bằng cách triển khai giao diện Parcelable. Giao diện Parcelable mất nhiều thời gian hơn để thực hiện so với serializable vì kích thước mã. Nhưng nó thực hiện nhanh hơn serializable và sử dụng ít tài nguyên hơn.
Kwnstantinos Nikoloutsos

27

nếu lớp đối tượng của bạn thực hiện Serializable, bạn không cần phải làm gì khác, bạn có thể truyền một đối tượng tuần tự hóa.
đó là những gì tôi sử dụng.


24

thực hiện tuần tự hóa trong lớp của bạn

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;
        }
}

Sau đó, bạn có thể vượt qua đối tượng này trong ý định

     Intent intent = new Intent(this, SecondAct.class);
     intent.putExtra("PLACE", Place);
     startActivity(intent);

int hoạt động thứ hai bạn có thể nhận được dữ liệu như thế này

     Place place= (Place) getIntent().getSerializableExtra("PLACE");

Nhưng khi dữ liệu trở nên lớn, phương pháp này sẽ chậm.


16

Bạn có thể sử dụng Android BUNDLE để làm điều này.

Tạo một Gói từ lớp của bạn như:

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

    return b;
}

Sau đó vượt qua gói này với INTENT. Bây giờ bạn có thể tạo lại đối tượng lớp của mình bằng cách chuyển gói như

public CustomClass(Context _context, Bundle b) {
    context = _context;
    classMember = b.getString("SomeKey");
}

Khai báo điều này trong lớp Tùy chỉnh của bạn và sử dụng.


1
Thích hợp để thực hiện Parcelable trực tiếp, IMHO. Gói thực hiện Parcelable của chính nó để bạn vẫn có được hiệu suất đạt được trong khi tránh mọi rắc rối khi tự thực hiện nó. Thay vào đó, bạn có thể sử dụng các cặp khóa-giá trị để lưu trữ và truy xuất dữ liệu mạnh mẽ hơn nhiều so với việc chỉ dựa vào đơn hàng.
Risadinha

Parcelable có vẻ phức tạp đối với tôi, trong câu trả lời trên của tôi, tôi đang sử dụng phương thức toBundle từ lớp trên đối tượng của nó để đối tượng được chuyển đổi thành bó và sau đó chúng ta có thể sử dụng hàm tạo để chuyển đổi gói thành đối tượng lớp.
om252345

Giải pháp này chỉ khả thi nếu bạn chuyển một đối tượng thông qua một ý định.
TheIT

Giống như json nhưng json là trọng lượng nhẹ tôi nghĩ.
David

Đối tượng khi tôi truy xuất nó sẽ là cùng một đối tượng hoặc một bản sao?
Markus

16

Có một số cách mà bạn có thể truy cập các biến hoặc đối tượng trong các lớp hoặc Hoạt động khác.

Một cơ sở dữ liệu

B. sở thích chung.

C. Tuần tự hóa đối tượng.

D. Một lớp có thể chứa dữ liệu chung có thể được đặt tên là Tiện ích chung, nó phụ thuộc vào bạn.

E. Truyền dữ liệu qua Ý định và Giao diện Parcelable.

Nó phụ thuộc vào nhu cầu dự án của bạn.

A. Cơ sở dữ liệu

SQLite là một cơ sở dữ liệu nguồn mở được nhúng vào Android. SQLite hỗ trợ các tính năng cơ sở dữ liệu quan hệ tiêu chuẩn như cú pháp SQL, giao dịch và các câu lệnh được chuẩn bị.

Hướng dẫn - http://www.vogella.com/articles/AndroidSQLite/article.html

B. Sở thích được chia sẻ

Giả sử bạn muốn lưu trữ tên người dùng. Vì vậy, bây giờ sẽ có hai thứ Tên người dùng chính , Giá trị giá trị.

Cách bảo quản

 // Create an 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();

Sử dụng putString (), putBoolean (), putInt (), putFloat (), putLong () bạn có thể lưu dtatype mong muốn của mình.

Cách lấy

SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
String userName = sharedPref.getString("userName", "Not Available");

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

C. Tuần tự hóa đối tượng

Tuần tự hóa đối tượng được sử dụng nếu chúng ta muốn lưu trạng thái đối tượng để gửi nó qua mạng hoặc bạn cũng có thể sử dụng nó cho mục đích của mình.

Sử dụng java java và lưu trữ trong đó như một trong các trường của anh ấy và sử dụng getters và setter cho điều đó

JavaBeans là các lớp Java có các thuộc tính. Hãy nghĩ về các thuộc tính như các biến cá nhân. Vì chúng là riêng tư, cách duy nhất chúng có thể được truy cập từ bên ngoài lớp là thông qua các phương thức trong lớp. Các phương thức thay đổi giá trị của thuộc tính được gọi là phương thức setter và phương thức truy xuất giá trị của thuộc tính được gọi là phương thức getter.

public class VariableStorage implements Serializable  {

    private String inString ;

    public String getInString() {
        return inString;
    }

    public void setInString(String inString) {
        this.inString = inString;
    }


}

Đặt biến trong phương thức thư của bạn bằng cách sử dụng

VariableStorage variableStorage = new VariableStorage();
variableStorage.setInString(inString);

Sau đó, sử dụng serialzation đối tượng để tuần tự hóa đối tượng này và trong lớp khác của bạn giải tuần tự hóa đối tượng này.

Trong tuần tự hóa, một đối tượng có thể được biểu diễn dưới dạng một chuỗi các byte bao gồm dữ liệu của đối tượng cũng như thông tin về loại của đối tượng và các loại dữ liệu được lưu trữ trong đối tượng.

Sau khi một đối tượng được tuần tự hóa đã được ghi vào một tệp, nó có thể được đọc từ tệp và được giải tuần tự hóa, đó là thông tin loại và byte đại diện cho đối tượng và dữ liệu của nó có thể được sử dụng để tạo lại đối tượng trong bộ nhớ.

Nếu bạn muốn có một hướng dẫn cho điều này để tham khảo liên kết này

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

Nhận biến trong các lớp khác

D. Khả năng chung

Bạn có thể tự tạo một lớp có thể chứa dữ liệu chung mà bạn thường cần trong dự án của mình.

Mẫu vật

public class CommonUtilities {

    public static String className = "CommonUtilities";

}

E. Truyền dữ liệu qua ý định

Vui lòng tham khảo hướng dẫn này cho tùy chọn truyền dữ liệu này.

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


Hướng dẫn tốt mà bạn đề cập trong (E) về việc truyền dữ liệu qua Ý định.
remrick

15

Cảm ơn sự giúp đỡ có thể phân loại nhưng tôi tìm thấy một giải pháp tùy chọn hơn

 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;
        }
    }

Trong hoạt động một

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);

Nhận dữ liệu trong hoạt động 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());
        }

1
câu trả lời hay, nhưng tăng Tiêu chuẩn mã hóa của bạn ... +1 mặc dù để mang lại khả năng Nối tiếp trong cuộc thi tuy nhiên Parcellables nhanh hơn rất nhiều ...
Amit

13

Tôi sử dụng Gson với api mạnh mẽ và đơn giản của nó để gửi các đối tượng giữa các hoạt động,

Thí dụ

// 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);
    }
}

2 chức năng bạn thêm chúng vào các đối tượng mà bạn muốn gửi

Sử dụng

Gửi đối tượng từ A đến 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);

Nhận trong 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);
}

Tôi sử dụng nó gần như trong mọi dự án tôi làm và tôi không có vấn đề về hiệu suất.


Cảm ơn, điều này đã giúp tôi tiết kiệm hàng giờ đồng hồ.
Hristo Stoyanov

10

Tôi vật lộn với cùng một vấn đề. Tôi đã giải quyết nó bằng cách sử dụng một lớp tĩnh, lưu trữ bất kỳ dữ liệu nào tôi muốn trong HashMap. Trên hết, tôi sử dụng một phần mở rộng của lớp Activity tiêu chuẩn nơi tôi đã ghi đè các phương thức onCreate một onDestroy để thực hiện việc truyền dữ liệu và xóa dữ liệu. Một số cài đặt lố bịch phải được thay đổi, ví dụ như xử lý định hướng.

Chú thích: Không cung cấp các đối tượng chung để chuyển sang Hoạt động khác là đau ở mông. Nó giống như tự bắn vào đầu gối và hy vọng giành được 100 mét. "Có thể di chuyển" không phải là một thay thế đủ. Nó làm tôi cười ... Tôi không muốn triển khai giao diện này cho API không có công nghệ của mình, vì tôi ít muốn giới thiệu một Lớp mới ... Làm sao có thể, chúng ta đang ở trong lập trình di động cách xa mô hình hiện đại ...


9

Trong hoạt động đầu tiên của bạn:

intent.putExtra("myTag", yourObject);

Và trong cái thứ hai của bạn:

myCustomObject myObject = (myCustomObject) getIntent().getSerializableExtra("myTag");

Đừng quên làm cho đối tượng tùy chỉnh của bạn được tuần tự hóa:

public class myCustomObject implements Serializable {
...
}

Parcelable là tốt hơn nối tiếp! Tránh sử dụng serializable trong mã Android của bạn!
Filipe Brito

7

Một cách khác để làm điều này là sử dụng Applicationđối tượng (android.app.Application). Bạn xác định điều này trong AndroidManifest.xmltệp của bạn là:

<application
    android:name=".MyApplication"
    ...

Sau đó, bạn có thể gọi đây từ bất kỳ hoạt động nào và lưu đối tượng vào Applicationlớp.

Trong FirstActivity:

MyObject myObject = new MyObject();
MyApplication app = (MyApplication) getApplication();
app.setMyObject(myObject);

Trong phần thứ hai, hãy thực hiện:

MyApplication app = (MyApplication) getApplication();
MyObject retrievedObject = app.getMyObject(myObject);

Điều này rất hữu ích nếu bạn có các đối tượng có phạm vi cấp ứng dụng tức là chúng phải được sử dụng trong toàn bộ ứng dụng. Các Parcelablephương pháp vẫn là tốt hơn nếu bạn muốn kiểm soát rõ ràng trong phạm vi đối tượng hoặc nếu phạm vi bị giới hạn.

Điều này tránh việc sử dụng Intentshoàn toàn, mặc dù. Tôi không biết nếu họ phù hợp với bạn. Một cách khác mà tôi đã sử dụng là để intnhận dạng các đối tượng gửi qua ý định và truy xuất các đối tượng mà tôi có trong Bản đồ trong Applicationđối tượng.


1
Đây không phải là cách đúng đắn để làm mọi thứ vì các đối tượng có thể thay đổi, bạn có thể làm việc nếu bạn nói về đối tượng tĩnh trong suốt vòng đời của ứng dụng, nhưng đôi khi chúng ta cần các đối tượng truyền qua có thể được tạo bằng dịch vụ web hoặc vì vậy stackoverflow.com / a / 2736612/716865
Muhannad A.Alhariri

Tôi đã sử dụng thành công với các đối tượng được tạo từ dịch vụ web bằng cách có phạm vi ứng dụng Mapnơi các đối tượng được lưu trữ và truy xuất bằng cách sử dụng mã định danh. Vấn đề thực sự duy nhất với cách tiếp cận này là Android sẽ xóa bộ nhớ sau một thời gian để bạn phải kiểm tra null trên onResume của bạn (Tôi nghĩ rằng các Đối tượng được truyền trong ý định vẫn tồn tại nhưng không chắc chắn). Ngoài ra, tôi không thấy điều này là kém hơn đáng kể.
Saad Farooq

Đây là câu trả lời tốt nhất. Nó cho thấy các hoạt động khác nhau có thể tham chiếu cùng một mô hình dữ liệu. Tôi phải mất rất lâu để khám phá điều này!
Markus

6

trong mô hình lớp (Đối tượng) của bạn triển khai Nối tiếp, ví dụ:

public class MensajesProveedor implements Serializable {

    private int idProveedor;


    public MensajesProveedor() {
    }

    public int getIdProveedor() {
        return idProveedor;
    }

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


}

và hoạt động đầu tiên của bạn

MensajeProveedor mp = new MensajeProveedor();
Intent i = new Intent(getApplicationContext(), NewActivity.class);
                i.putExtra("mensajes",mp);
                startActivity(i);

và Hoạt động thứ hai của bạn (NewActivity)

        MensajesProveedor  mensajes = (MensajesProveedor)getIntent().getExtras().getSerializable("mensajes");

chúc may mắn!!


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];
        }
    };

}

Truyền dữ liệu:

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

Lấy dữ liệu:

Bundle bundle = getIntent().getExtras();
dataList2 = getIntent().getExtras().getParcelableArrayList("data");

5

giải pháp đơn giản nhất tôi tìm thấy là .. để tạo một lớp với các thành viên dữ liệu tĩnh với setters getters.

thiết lập từ một hoạt động và nhận từ một hoạt động khác mà đối tượng.

hoạt động A

mytestclass.staticfunctionSet("","",""..etc.);

hoạt động b

mytestclass obj= mytestclass.staticfunctionGet();

1
hoặc lớp tuần tự hóa creata để chuyển sang hoạt động khác bất cứ điều gì bạn muốn vượt qua.
UMAR

9
Chỉ cần nhớ không đặt các đối tượng lớn chất béo. Tuổi thọ của đối tượng đó sẽ giống như thời gian tồn tại của ứng dụng. Và không bao giờ lưu trữ lượt xem. Phương pháp này cũng đảm bảo rò rỉ bộ nhớ.
Reno

1
Câu trả lời này hữu ích nhưng không phải là giải pháp tốt hơn về mặt tối ưu hóa bộ nhớ và tài nguyên
Atul Bhardwaj

1
Điều này phá vỡ các nguyên tắc OOP bằng cách giới thiệu các biến toàn cầu. Bạn không bao giờ biết, ở trạng thái nào, dù được đặt hay không, chúng được sử dụng bởi nhiều luồng và bạn phải đối phó với sự phức tạp này. Nó thường là một rò rỉ bộ nhớ tốt, bởi vì bạn thậm chí không biết, khi nào giải phóng các biến này. Không phải nói rằng nó giới thiệu khớp nối trực tiếp cứng giữa các mô-đun khác nhau của ứng dụng.
từ

2
WTF? Hai câu trả lời khác rất nhiều.
IcyFlame

4

bạn có thể sử dụng các phương thức putExtra (serializable ..) và getSerializableExtra () để truyền và truy xuất các đối tượng thuộc loại lớp của bạn; bạn sẽ phải đánh dấu lớp của bạn Nối tiếp và đảm bảo rằng tất cả các biến thành viên của bạn cũng được tuần tự hóa ...


4

Tạo ứng dụng Android

Tệp >> Mới >> Ứng dụng Android

Nhập tên dự án: android-pass-object-to-Activity

Pakcage: com.hmkcode.android

Giữ các lựa chọn xác thực khác, đi tiếp cho đến khi bạn đạt đến Kết thúc

Trước khi bắt đầu tạo Ứng dụng, chúng ta cần tạo lớp POJO, người mà chúng ta sẽ sử dụng để gửi đối tượng từ hoạt động này sang hoạt động khác. Lưu ý rằng lớp đang thực hiện giao diện Nối tiếp.

Person.java

package com.hmkcode.android;
import java.io.Serializable;

public class Person implements Serializable{

    private static final long serialVersionUID = 1L;

    private String name;
    private int age;

        // getters & setters....

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }   
}

Hai bố cục cho hai hoạt động

Activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
    <TextView
        android:id="@+id/tvName"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center_horizontal"
        android:text="Name" />

    <EditText
        android:id="@+id/etName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        android:ems="10" >
        <requestFocus />
    </EditText>
</LinearLayout>

<LinearLayout
     android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
<TextView
    android:id="@+id/tvAge"
    android:layout_width="100dp"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:gravity="center_horizontal"
    android:text="Age" />
<EditText
    android:id="@+id/etAge"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:ems="10" />
</LinearLayout>

<Button
    android:id="@+id/btnPassObject"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:text="Pass Object to Another Activity" />

</LinearLayout>

Activity_another.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
 >

<TextView
    android:id="@+id/tvPerson"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent"
    android:layout_gravity="center"
    android:gravity="center_horizontal"
 />

</LinearLayout>

Hai lớp hoạt động

1) ActivityMain.java

package com.hmkcode.android;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends Activity implements OnClickListener {

Button btnPassObject;
EditText etName, etAge;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    btnPassObject = (Button) findViewById(R.id.btnPassObject);
    etName = (EditText) findViewById(R.id.etName);
    etAge = (EditText) findViewById(R.id.etAge);

    btnPassObject.setOnClickListener(this);
}

@Override
public void onClick(View view) {

    // 1. create an intent pass class name or intnet action name 
    Intent intent = new Intent("com.hmkcode.android.ANOTHER_ACTIVITY");

    // 2. create person object
    Person person = new Person();
    person.setName(etName.getText().toString());
    person.setAge(Integer.parseInt(etAge.getText().toString()));

    // 3. put person in intent data
    intent.putExtra("person", person);

    // 4. start the activity
    startActivity(intent);
}

}

2) AnotherActivity.java

package com.hmkcode.android;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;

public class AnotherActivity extends Activity {

TextView tvPerson;

@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_another);

    // 1. get passed intent 
    Intent intent = getIntent();

    // 2. get person object from intent
    Person person = (Person) intent.getSerializableExtra("person");

    // 3. get reference to person textView 
    tvPerson = (TextView) findViewById(R.id.tvPerson);

    // 4. display name & age on textView 
    tvPerson.setText(person.toString());

}
}

4

Sử dụng thư viện Gson của google, bạn có thể chuyển đối tượng sang các hoạt động khác. Thực tế, chúng tôi sẽ chuyển đổi đối tượng dưới dạng chuỗi json và sau khi chuyển sang hoạt động khác, chúng tôi sẽ lại chuyển đổi sang đối tượng như thế này

Hãy xem xét một lớp đậu như thế này

 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;
    }
}

Chúng ta cần truyền đối tượng của lớp Ví dụ

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);

Để đọc, chúng ta cần thực hiện thao tác ngược lại trong 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);

Thêm phụ thuộc này vào lớp

compile 'com.google.code.gson:gson:2.6.2'

3
Intent i = new Intent();
i.putExtra("name_of_extra", myParcelableObject);
startACtivity(i);

3

Tôi biết điều này là muộn nhưng nó rất đơn giản. Tất cả những gì bạn phải làm là để cho lớp của bạn thực hiện Nối tiếp như

public class MyClass implements Serializable{

}

sau đó bạn có thể chuyển đến một ý định như

Intent intent=......
MyClass obje=new MyClass();
intent.putExtra("someStringHere",obje);

Để có được nó, bạn gọi đơn giản

MyClass objec=(MyClass)intent.getExtra("theString");

2

Nếu bạn có một lớp singleton (fx Service) đóng vai trò là cổng vào lớp mô hình của bạn, thì nó có thể được giải quyết bằng cách có một biến trong lớp đó với getters và setters cho nó.

Trong hoạt động 1:

Intent intent = new Intent(getApplicationContext(), Activity2.class);
service.setSavedOrder(order);
startActivity(intent);

Trong hoạt động 2:

private Service service;
private Order order;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_quality);

    service = Service.getInstance();
    order = service.getSavedOrder();
    service.setSavedOrder(null) //If you don't want to save it for the entire session of the app.
}

Phục vụ:

private static Service instance;

private Service()
{
    //Constructor content
}

public static Service getInstance()
{
    if(instance == null)
    {
        instance = new Service();
    }
    return instance;
}
private Order savedOrder;

public Order getSavedOrder()
{
    return savedOrder;
}

public void setSavedOrder(Order order)
{
    this.savedOrder = order;
}

Giải pháp này không yêu cầu bất kỳ sự tuần tự hóa hoặc "bao bì" nào khác của đối tượng được đề cập. Nhưng nó sẽ chỉ có lợi nếu bạn đang sử dụng loại kiến ​​trúc này.


Nhược điểm của phương pháp này là gì? Có vẻ rất hợp lý và mỏng. Tôi luôn đọc bạn không nên làm điều đó nhưng tôi không bao giờ có được một lời giải thích tốt về những gì có thể sai.
Markus

Vì tôi không thể chỉnh sửa nhận xét của mình nữa: Đây không phải là giải pháp khả thi duy nhất để có được một tham chiếu đến một đối tượng thay vì một bản sao? Tôi cần phải truy xuất cùng một obejct và không phải là một bản sao!
Markus

Tôi nghĩ rằng điều này có phần nản lòng vì tính khớp nối cao mà nó dẫn đến. Nhưng vâng, theo như tôi thấy, cách tiếp cận này là khả thi nhất nếu bạn cần đối tượng thực tế. Như mọi khi trong lập trình, bạn có thể làm bất cứ điều gì bạn muốn, bạn chỉ muốn làm nó một cách cẩn thận. Giải pháp này hiệu quả với tôi và tôi thích nó vì dù sao tôi cũng sử dụng kiến ​​trúc đó.
Kitalda

Trên thực tế, tôi đã kết thúc việc mở rộng lớp Ứng dụng và lưu trữ dữ liệu của mình ở đó. Trong Ý định tôi chỉ chuyển tiếp ID của các đối tượng dữ liệu có thể được sử dụng để truy xuất đối tượng gốc từ lớp Ứng dụng. Ngoài ra, lớp ứng dụng mở rộng thông báo cho tất cả các đối tượng sử dụng datamodel nếu nó thay đổi thông qua một khái niệm trình nghe chuẩn. Tôi biết rằng điều này chỉ phù hợp với trường hợp của tôi khi tôi cần chia sẻ một mô hình dữ liệu trên toàn bộ ứng dụng nhưng đối với trường hợp đó, nó hoàn hảo và không cần các lớp và trường tĩnh!
Markus

2

Cho đến nay cách dễ nhất IMHO để các đối tượng bưu kiện. Bạn chỉ cần thêm một thẻ chú thích phía trên đối tượng bạn muốn làm cho bưu kiện.

Một ví dụ từ thư viện bên dưới https://github.com/johncarl81/parceler

@Parcel
public class Example {
    String name;
    int age;

    public Example(){ /*Required empty bean constructor*/ }

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

    public String getName() { return name; }

    public int getAge() { return age; }
}

2

Lần đầu tiên thực hiện Parcelable trong lớp của bạn. Sau đó vượt qua đối tượng như thế này.

SendActivity.java

ObjectA obj = new ObjectA();

// Set values etc.

Intent i = new Intent(this, MyActivity.class);
i.putExtra("com.package.ObjectA", obj);

startActivity(i);

NhậnActivity.java

Bundle b = getIntent().getExtras();
ObjectA obj = b.getParcelable("com.package.ObjectA");

Chuỗi gói không cần thiết, chỉ cần chuỗi giống nhau trong cả hai Hoạt động

TÀI LIỆU THAM KHẢO


2

Bắt đầu một hoạt động khác từ hoạt động này vượt qua các tham số thông qua Bundle Object

Intent intent = new Intent(getBaseContext(), YourActivity.class);
intent.putExtra("USER_NAME", "xyz@gmail.com");
startActivity(intent);

Truy xuất hoạt động khác (YourActivity)

String s = getIntent().getStringExtra("USER_NAME");

Điều này là ok cho loại dữ liệu đơn giản. Nhưng nếu bạn muốn truyền dữ liệu phức tạp vào giữa hoạt động thì trước tiên bạn cần phải tuần tự hóa nó.

Ở đây chúng tôi có Mô hình nhân viên

class Employee{
    private String empId;
    private int age;
    print Double salary;

    getters...
    setters...
}

Bạn có thể sử dụng lib Gson do google cung cấp để tuần tự hóa dữ liệu phức tạp như thế này

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);

2

Ở Koltin

Thêm phần mở rộng kotlin trong build.gradle của bạn.

apply plugin: 'kotlin-android-extensions'

android {
    androidExtensions {
        experimental = true
   }
}

Sau đó tạo lớp dữ liệu của bạn như thế này.

@Parcelize
data class Sample(val id: Int, val name: String) : Parcelable

Vượt qua đối tượng với ý định

val sample = Sample(1,"naveen")

val intent = Intent(context, YourActivity::class.java)
    intent.putExtra("id", sample)
    startActivity(intent)

Lấy đối tượng với ý định

val sample = intent.getParcelableExtra("id")

Nó vẫn còn thử nghiệm chứ?
ShadowToD

2

Cách làm dễ nhất và java là: triển khai tuần tự hóa trong lớp pojo / model của bạn

Đề xuất cho Android để xem hiệu suất: làm cho mô hình có thể phân chia


1

Đơn giản nhất là chỉ sử dụng các mục sau trong đó mục là một chuỗi:

intent.putextra("selected_item",item)

Để nhận lại:

String name = data.getStringExtra("selected_item");

3
Nó chỉ dành cho chuỗi, số nguyên và vv nhưng tôi muốn đối tượng và sử dụng đối tượng tĩnh chỉ có thể.
UMAR
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.