Cách truyền đối tượng từ hoạt động này sang hoạt động khác trên Android


779

Tôi đang cố gắng gửi một đối tượng của lớp khách hàng của mình từ một đối tượng Activityvà hiển thị nó trong một đối tượng khác Activity.

Mã cho lớp khách hàng:

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

Tôi muốn gửi đối tượng của nó từ cái này Activitysang cái khác và sau đó hiển thị dữ liệu trên cái kia Activity.

Làm thế nào tôi có thể đạt được điều đó?


1
có lẽ bạn nên thay đổi câu trả lời được chấp nhận theo quan điểm của dư luận.
Rohit Vipin Mathews

Tôi đã từng đặt đối tượng thành Pacelable hoặc serializable, nhưng bất cứ khi nào tôi thêm các biến khác, tôi phải thêm tất cả vào các hàm để lấy và đặt cho Pacelable hoặc serializable. vì vậy tôi đã tạo DataCache để chuyển giữa các hoạt động và các đoạn. github.com/kimkevin/AndroidDataCache Việc chuyển đối tượng siêu dễ dàng.
kimkevin

Câu trả lời:


886

Một tùy chọn có thể cho phép lớp tùy chỉnh của bạn thực hiện Serializablegiao diện và sau đó bạn có thể chuyển các thể hiện đối tượng trong mục đích thêm bằng cách sử dụng putExtra(Serializable..)biến thể của Intent#putExtra()phương thức.

Mã giả :

//To pass:
intent.putExtra("MyClass", obj);

// To retrieve object in second Activity
getIntent().getSerializableExtra("MyClass");

Lưu ý: Đảm bảo rằng mỗi lớp lồng nhau của lớp tùy chỉnh chính của bạn đã triển khai giao diện Nối tiếp để tránh mọi trường hợp ngoại lệ. Ví dụ:

class MainClass implements Serializable {

    public MainClass() {}

    public static class ChildClass implements Serializable {

        public ChildClass() {}
    }
}

126
@OD: Trong phòng thủ của tôi, tôi không bao giờ nói đây là lựa chọn tốt nhất; OP chỉ yêu cầu thay thế và tôi đề nghị một. Dù sao cũng cảm ơn.
Samuh

83
Tại sao serializable không phải là một lựa chọn tốt? Đó là một giao diện nổi tiếng, rất có khả năng các lớp của mọi người có thể đã triển khai nó (ví dụ, ArrayList đã được tuần tự hóa). Tại sao bạn phải thay đổi các đối tượng dữ liệu của mình để thêm mã đơn giản để chuyển chúng từ lớp này sang lớp khác? Đó dường như là một thiết kế tồi. Tôi có thể tưởng tượng có thể có một số tác động hiệu suất ở một mức độ nào đó, nhưng tôi nghĩ rằng trong 99% trường hợp, mọi người đang truyền một lượng nhỏ dữ liệu và họ sẽ không quan tâm. Đơn giản hơn và di động đôi khi cũng tốt hơn.
Nate

16
@Sander: Câu trả lời này ( stackoverflow.com/questions/2139134/ mẹo ) có sai không? Ông nói rằng Parcelable IS được thiết kế đặc biệt cho mục đích đó (và nhanh hơn nhiều Serializable). Tôi là một người bối rối.
Slauma

41
Parcelablecó thể tốt cho tốc độ, nhưng nó rất phức tạp để thực hiện. Điều gì sẽ xảy ra nếu bạn có 8 đối tượng bạn cần chuyển qua lại giữa các hoạt động, bạn sẽ thực hiện từng đối tượng Parcelable? Nó sẽ có ý nghĩa hơn để sử dụng Serializablethay thế. Khi bạn triển khai, Parcelablebạn phải thêm rất nhiều mã vào lớp và sắp xếp các trường theo cách rất cụ thể; Serializablebạn không Cuối cùng, tôi nghĩ nó phụ thuộc vào số lượng đối tượng bạn đang vượt qua và những gì bạn đang cố gắng làm.
BlackHatSamurai

15
Serializablelà một giao diện Java tiêu chuẩn. Bạn chỉ cần đánh dấu một lớp Tuần tự hóa bằng cách cấy vào giao diện và Java sẽ tự động tuần tự hóa nó trong các tình huống nhất định. Parcelablelà một giao diện cụ thể của Android nơi bạn tự thực hiện việc tuần tự hóa. Nó được tạo ra để có khả năng Nối tiếp hiệu quả hơn nhiều và để khắc phục một số vấn đề với sơ đồ tuần tự hóa Java mặc định
Gaurav Arora

311

Thực hiện lớp học của bạn với serializable. Hãy giả sử rằng đây là lớp thực thể của bạn:

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

Chúng tôi đang gửi đối tượng được gọi denetừ hoạt động X đến hoạt động Y. Một nơi nào đó trong hoạt động X;

Deneme dene = new Deneme(4,"Mustafa");
Intent i = new Intent(this, Y.class);
i.putExtra("sampleObject", dene);
startActivity(i);

Trong hoạt động Y chúng ta đang nhận được đối tượng.

Intent i = getIntent();
Deneme dene = (Deneme)i.getSerializableExtra("sampleObject");

Đó là nó.


1
Nó thực sự hữu ích cho tôi. Cảm ơn ... Nhưng khi nhận được đối tượng đã qua, cú pháp phải là [Deneme dene = (Deneme) i.getSerializableExtra ("sampleObject"); ] ... Là nó ???
JibW

1
@ MustafaGüven Nhưng tôi nhận được classCastException: java.lang.Longbằng cách làm như vậy. Bạn có thể vui lòng giải thích tại sao?
Shajeel Afzal

Không có bất kỳ mối quan hệ với câu trả lời của tôi. Đó là điều rất khác bạn đang nhận được. Bạn có thể chia sẻ mã của bạn?
Mustafa Güven

1
Nối tiếp là quá chậm đối với POJO lớn. Sử dụng xe buýt là một mô hình tốt hơn nhiều.
Steven Mark Ford

1
Tại sao tôi phải thêm tiền tố (Serializable)vào đối tượng?
Alston

123
  • Sử dụng các biến tĩnh toàn cầu không phải là thực hành kỹ thuật phần mềm tốt .
  • Chuyển đổi các trường của đối tượng thành các kiểu dữ liệu nguyên thủy có thể là một công việc bận rộn .
  • Sử dụng tuần tự hóa là OK, nhưng nó không hiệu quả trên nền tảng Android.
  • Parcelable được thiết kế dành riêng cho Android và bạn nên sử dụng nó. Dưới đây là một ví dụ đơn giản: Truyền các đối tượng tùy chỉnh giữa các hoạt động của Android

Bạn có thể tạo mã Parcelable cho lớp bạn bằng cách sử dụng trang web này .


4
Nếu đối tượng của tôi chứa Arraylist lồng nhau thì sao?
Tiến sĩ aNdRO

10
Có lẽ nhưng người ta thực sự nên dùng '`hiệu suất' 'với một hạt muối imo. Nếu điều đó có giá của việc triển khai Parcelablethì tôi muốn giữ các lớp POJO của mình không sử dụng và sử dụng Android Serializable.
VH-NZZ

Tôi không đồng ý rằng bạn nên sử dụng Parcelable. Một mô hình BUS đơn giản là hiệu quả hơn nhiều trong thời gian chạy và tiết kiệm rất nhiều thời gian dev.
Steven Mark Ford

15
Theo điểm chuẩn này bitbucket.org/afrishman/androidserializationtest serializable nhanh hơn nhiều so với Parcelable. Hãy ngừng chia sẻ điều vô lý 5 tuổi này về Parcelable.
từ

7
Làm thế nào là các biến tĩnh toàn cầu "thực hành kỹ thuật phần mềm không tốt"? Bạn có thể tạo một cái gì đó như bộ đệm đơn và / hoặc lưới dữ liệu sau đó chuyển qua ID hoặc tương tự. Khi bạn chuyển qua các tham chiếu trong Java, bạn sẽ sử dụng các biến tĩnh toàn cục theo nghĩa nào đó khi chúng trỏ đến cùng một đối tượng.
vỡ

112

Sử dụng gson để chuyển đổi đối tượng của bạn thành JSON và chuyển nó thông qua ý định. Trong Activity mới chuyển đổi JSON thành một đối tượng.

Trong của bạn build.gradle, thêm điều này vào phụ thuộc của bạn

implementation 'com.google.code.gson:gson:2.8.4'

Trong Hoạt động của bạn, chuyển đổi đối tượng thành chuỗi json:

Gson gson = new Gson();
String myJson = gson.toJson(vp);
intent.putExtra("myjson", myjson);

Trong Hoạt động nhận của bạn, chuyển đổi chuỗi json trở lại đối tượng ban đầu:

Gson gson = new Gson();
YourObject ob = gson.fromJson(getIntent().getStringExtra("myjson"), YourObject.class);

Đối với Kotlin, nó khá giống nhau

Truyền dữ liệu

val gson = Gson()
val intent = Intent(this, YourActivity::class.java)
intent.putExtra("identifier", gson.toJson(your_object))
startActivity(intent)

Nhận dữ liệu

val gson = Gson()
val yourObject = gson.fromJson<YourObject>(intent.getStringExtra("identifier"), YourObject::class.java)

3
Đây là một quá mức cần thiết, gson chỉ là một loại tuần tự chuỗi thành json, tốt hơn là thực hiện Nối tiếp hoặc Paracable.
James Roeiter

14
Không cần phải thực hiện tuần tự hóa trong mọi đối tượng và trong mọi dự án (lãng phí thời gian) nếu bạn có thể sử dụng một thư viện (gson) xử lý việc đó. Và về mức độ quá mức, có điện thoại kép và bốn lõi ngoài kia, họ có thể xử lý ngay cả một danh sách theo ý tưởng trả lời này.
sagits

4
Tôi cũng sẽ khuyên bạn nên sử dụng gson vì gson cũng có thể tuần tự hóa danh sách mảng ngoài ở trên.
nurgasemetey

4
Điều đó thật tuyệt! Trong trường hợp của tôi, tôi đang sử dụng một thư viện mà các đối tượng không thực hiện tuần tự hóa hoặc phân lô. Vì vậy, đây là lựa chọn duy nhất của tôi afaik
Chad Bingham

2
Đây là tùy chọn "tốt nhất". Một số lớp rất đơn giản, bạn không cần quá phức tạp việc thực hiện chúng bằng cách triển khai tuần tự hóa
Ojonugwa Jude Ochalifu

98

Trong khi gọi một hoạt động

Intent intent = new Intent(fromClass.this,toClass.class).putExtra("myCustomerObj",customerObj);

Trong toClass.java nhận hoạt động bằng

Customer customerObjInToClass = getIntent().getExtras().getParcelable("myCustomerObj");

Hãy chắc chắn rằng lớp khách hàng thực hiện bưu kiện

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

Adhavan, tôi có một câu hỏi. Khi bạn tạo lớp Intent đầu tiên, bạn chuyển từ fromClass.this thành đối số đầu tiên. Có cách nào để lấy đối tượng này trong lớp hoạt động nhận không?
newman

1
Miliu, fromClass fr = (fromClass) getParent (); đây có phải là những gì bạn cần?
Quảng cáo

Adhava, tôi thực sự đã làm điều này, nhưng fr là null. Bất cứ ý tưởng tại sao?
newman

miliu, xin vui lòng chia sẻ dấu vết ngoại lệ của bạn bằng cách chúng tôi có thể xem xét nó.
Quảng cáo

Parcelable có rất nhiều mã nồi hơi không cần thiết và thực sự là một sự lãng phí thời gian. Thay vì sử dụng xe buýt. Xem bài viết của tôi dưới đây.
Steven Mark Ford

89

Theo kinh nghiệm của tôi, có ba giải pháp chính, mỗi giải pháp đều có nhược điểm và ưu điểm:

  1. Thực hiện Parcelable

  2. Triển khai tuần tự hóa

  3. Sử dụng một thư viện xe buýt sự kiện trọng lượng nhẹ nào đó (ví dụ: EventBus của Greenrobot hoặc Otto của Square)

Parcelable - tiêu chuẩn nhanh và Android, nhưng nó có rất nhiều mã soạn sẵn và yêu cầu các chuỗi mã hóa cứng để tham khảo khi kéo các giá trị ra khỏi ý định (không được gõ mạnh).

Tuần tự hóa - gần với số 0, nhưng đó là cách tiếp cận chậm nhất và cũng yêu cầu các chuỗi được mã hóa cứng khi kéo các giá trị ra khỏi ý định (không được gõ mạnh).

Xe buýt sự kiện - không nồi hơi, cách tiếp cận nhanh nhất và không yêu cầu chuỗi mã hóa cứng, nhưng nó yêu cầu một phụ thuộc bổ sung (mặc dù thường nhẹ, ~ 40 KB)

Tôi đã đăng một so sánh rất chi tiết xung quanh ba phương pháp này, bao gồm cả điểm chuẩn hiệu quả.


4
Liên kết đến bài viết đã chết. Vẫn có sẵn trên webarchive: web.archive.org/web/20160917213123/http://...
OlivierH

Thật xấu hổ khi liên kết bị sập :(
Mauker

Vấn đề sử dụng Bus sự kiện là khi Hoạt động đích được tạo lại do xoay vòng chẳng hạn. Trong trường hợp này, Activity không truy cập được vào đối tượng đã qua vì đối tượng này đã được sử dụng từ bus bằng cuộc gọi trước đó.
JuliuszJ

1
Parcelable là nhanh nhất và với trình tạo này ( bưu kiện ), bạn có thể dán lớp của mình và nó có thể tạo mã cho bạn. Đơn giản.
ByWaleed

1
@ByWaleed ... Tôi hoàn toàn đồng ý, tôi luôn sử dụng trang web này, tạo ra các công cụ mà không gặp rắc rối nào. Tuy nhiên, tôi đã có rất nhiều lần thử không thành công, khi tôi cố gắng sử dụng POJO bao gồm một Đối tượng khác. Đối với một số lý do ra nó không thực sự làm việc.
Ứng dụng Yo

42

Tôi tìm thấy một phương pháp đơn giản và thanh lịch:

  • KHÔNG có bưu kiện
  • KHÔNG nối tiếp
  • KHÔNG trường tĩnh
  • Không có xe buýt sự kiện

Phương pháp 1

Mã cho hoạt động đầu tiên:

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

Mã cho hoạt động thứ hai:

    final Object objReceived = ((ObjectWrapperForBinder)getIntent().getExtras().getBinder("object_value")).getData();
    Log.d(TAG, "received object=" + objReceived);

bạn sẽ tìm thấy objSentobjReceivedcó cùnghashCode , vì vậy chúng giống hệt nhau.

Nhưng tại sao chúng ta có thể vượt qua một đối tượng java theo cách này?

Trên thực tế, binder android sẽ tạo tham chiếu JNI toàn cầu cho đối tượng java và phát hành tham chiếu JNI toàn cầu này khi không có tham chiếu cho đối tượng java này. Binder sẽ lưu tham chiếu JNI toàn cầu này trong đối tượng Binder.

* THẬN TRỌNG: phương pháp này CHỈ hoạt động trừ khi hai hoạt động chạy trong cùng một quy trình, nếu không thì ném ClassCastException vào (ObjectWrapperForBinder) getIntent (). GetExtras (). GetBinder ("object_value") *

lớp định nghĩa ObjectWrapperForBinder

public class ObjectWrapperForBinder extends Binder {

    private final Object mData;

    public ObjectWrapperForBinder(Object data) {
        mData = data;
    }

    public Object getData() {
        return mData;
    }
}

Cách 2

  • cho người gửi
    1. sử dụng phương thức gốc tùy chỉnh để thêm đối tượng java của bạn vào bảng tham chiếu toàn cầu JNI (thông qua JNIEnv :: NewGlobalRef)
    2. đặt số nguyên trả về (thực ra là JNIEnv :: NewGlobalRef công việc trả về, là một con trỏ, chúng ta có thể chuyển nó thành int một cách an toàn) cho Intent của bạn (thông qua Intent :: putExtra)
  • cho người nhận
    1. lấy số nguyên từ Intent (thông qua Intent :: getInt)
    2. sử dụng phương thức gốc tùy chỉnh để khôi phục đối tượng java của bạn từ bảng tham chiếu toàn cầu JNI (thông qua JNIEnv :: NewLocalRef)
    3. xóa mục khỏi bảng tham chiếu toàn cầu của JNI (thông qua JNIEnv :: DeleteGlobalRef),

Nhưng Phương thức 2 có một vấn đề nhỏ nhưng nghiêm trọng, nếu người nhận không khôi phục được đối tượng java (ví dụ: một số ngoại lệ xảy ra trước khi khôi phục đối tượng java hoặc Hoạt động của người nhận hoàn toàn không tồn tại), thì đối tượng java sẽ trở thành Trẻ mồ côi hoặc rò rỉ bộ nhớ, Phương pháp 1 không có vấn đề này, vì trình kết nối Android sẽ xử lý ngoại lệ này

Phương pháp 3

Để gọi đối tượng java từ xa, chúng tôi sẽ tạo một hợp đồng / giao diện dữ liệu để mô tả đối tượng java, chúng tôi sẽ sử dụng tệp hỗ trợ

IDataContract.aidl

package com.example.objectwrapper;
interface IDataContract {
    int func1(String arg1);
    int func2(String arg1);
}

Mã cho hoạt động đầu tiên

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

Mã cho hoạt động thứ hai:

thay đổi thuộc tính android: process trong AndroidManifest.xml thành tên quy trình không trống để đảm bảo hoạt động thứ hai chạy trong quy trình khác

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

Theo cách này, chúng ta có thể chuyển giao diện giữa hai hoạt động mặc dù chúng chạy trong quy trình khác nhau và gọi phương thức giao diện từ xa

Phương pháp 4

Phương pháp 3 dường như không đủ đơn giản vì chúng ta phải thực hiện giao diện viện trợ. Nếu bạn chỉ muốn thực hiện tác vụ đơn giản và giá trị trả về của phương thức là không cần thiết, chúng ta có thể sử dụng android.os.Mesbah

Mã cho hoạt động đầu tiên (người gửi):

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

Mã cho hoạt động thứ hai (người nhận):

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

    }
}

Tất cả Messenger.send sẽ thực thi trong Trình xử lý không đồng bộ và tuần tự.

Trên thực tế, android.os.Mesbah cũng là một giao diện hỗ trợ, nếu bạn có mã nguồn Android, bạn có thể tìm thấy một tệp có tên IMesbah.aidl

package android.os;

import android.os.Message;

/** @hide */
oneway interface IMessenger {
    void send(in Message msg);
}

Xin lỗi tôi không thấy rằng bạn có ràng buộc trong câu trả lời của bạn và tôi cảm thấy rằng câu trả lời của bạn cũng rất thanh lịch.
SkidRunner

Wow .... Phương pháp đầu tiên của người đàn ông này là rất lớn ..... Khi bạn có những vật thể có kích thước rất lớn / lớn hơn hoạt động tốt
karan

Tôi sử dụng phương pháp một. Vì vậy, bạn tiết kiệm thời gian của tôi. cảm ơn;
ShweLiam

Cảm ơn rất nhiều về phương pháp ObjectWrapperForBinder, thực sự hữu ích!
Vladimir Tolstikov

40

Bạn cũng có thể ghi dữ liệu của đối tượng vào các chuỗi và int tạm thời và chuyển chúng vào hoạt động. Tất nhiên theo cách đó, bạn có được dữ liệu vận chuyển, nhưng không phải chính đối tượng.

Nhưng nếu bạn chỉ muốn hiển thị chúng, và không sử dụng đối tượng trong một phương thức khác hoặc một cái gì đó tương tự, thì nó là đủ. Tôi đã làm nó giống như cách chỉ hiển thị dữ liệu từ một đối tượng trong hoạt động khác.

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

Bạn cũng có thể chuyển chúng trực tiếp thay vì ngà tạm thời, nhưng theo cách này thì rõ ràng hơn, theo ý kiến ​​của tôi. Ngoài ra, bạn có thể đặt ngà tạm thời thành null để chúng được dọn dẹp bởi GarbageCollector sớm hơn.

Chúc may mắn!

Trên một lưu ý phụ: ghi đè toString () thay vì viết phương thức in của riêng bạn.

Như đã đề cập trong các bình luận bên dưới, đây là cách bạn lấy lại dữ liệu của mình trong một hoạt động khác:

String fName = getIntent().getExtras().getInt("fname");

9
lấy lại dữ liệu của bạn với: String fName = getIntent (). getExtras (). getInt ("fname");
Alister

2
Để lấy lại dữ liệu: Bundle extras = getIntent().getExtras(); String val = extras.getString("fname");
Eric Leschinski

1
Điều này có thể nhanh chóng trở nên không khả thi đối với các POJO lớn. Thay vì sử dụng xe buýt. Xem bài viết của tôi dưới đây.
Steven Mark Ford

như tôi đã đề cập trong câu trả lời của mình, đây là cho các giai đoạn đơn giản mà bạn không cần đối tượng, mà chỉ là một số giá trị của nó. Nó không phải là một sự giải thích cho các giai đoạn phức tạp.
MJB

1
Ý tưởng tốt để vượt qua một đối tượng, nhưng tôi đang cố gắng vượt qua một mảng có kích thước không xác định của đối tượng của mình. Có lẽ giải pháp của bạn không dành cho việc vượt qua các mảng đối tượng.
Muhammad Saqib

25

Tôi đã thực hiện một lớp người trợ giúp đơn lẻ giữ các đối tượng tạm thời.

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

Thay vì đặt các đối tượng của bạn trong Intent, hãy sử dụng IntentHelper:

IntentHelper.addObjectForKey(obj, "key");

Trong Hoạt động mới của bạn, bạn có thể nhận được đối tượng:

Object obj = (Object) IntentHelper.getObjectForKey("key");

Hãy nhớ rằng một khi được tải, đối tượng sẽ bị xóa để tránh các tham chiếu không cần thiết.


1
Ý tưởng tốt! Ngoài ra, bạn có thể tạo một lớp bổ sung ObjectContainer {Object, obj; boolean vĩnh viễn; ....} Ý tưởng là, bạn có thể vượt qua phương thức boolean trong add nếu bạn cần giữ đối tượng liên tục và không xóa khi chúng ta gọi get. Nó sẽ giúp giữ một số đối tượng toàn cầu. Like có thể là kết nối bluetooth mở, v.v.
Umair

1
Dễ thương nhưng không phát minh lại bánh xe. Mẫu xe buýt thanh lịch và mạnh mẽ hơn. Xem bài viết của tôi dưới đây.
Steven Mark Ford

@StevenMarkFord vậy mô hình Bus có còn đúng đến ngày hôm nay không? Tôi đang cố gắng cải thiện một cơ sở mã với mã như thế này để truy cập dữ liệu giữa các hoạt động: BookActivity.getInstance().recommendationResponsetrongRoomsActivity
Woppi

Khi Hoạt động nhận được tạo lại (ví dụ: xoay màn hình) objsẽ trở thành null. Để tránh điều này, objnên được lưu trữ ở đâu đó để lấy lại. Thật vậy, giải pháp Json lưu trữ dữ liệu đối tượng trong Ý định.
Salvador

25

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

B. Sở thích chung

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

Cách bảo quản

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

Sử dụng putString (), putBoolean (), putInt (), putFloat () và 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

Việc serl 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 các hạt 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 đố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 hướng dẫn cho điều này tham khảo:

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 Android - Dữ liệu bưu kiện để chuyển giữa các Hoạt động bằng cách sử dụng các lớp Parcelable cho tùy chọn truyền dữ liệu này.


22

Tạo lớp của riêng bạn Customernhư sau:

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

}

Trong onCreate()phương pháp của bạn

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

Trong xyz activitylớp bạn cần sử dụng đoạn mã sau:

Intent intent=getIntent();
Customer cust=(Customer)intent.getSerializableExtra("bundle");
textViewName.setText(cust.getName());
textViewCity.setText(cust.getCity());

..Kiểm tra mã của bạn, bạn đang chuyển "gói" làm khóa để đặt quyền giám sát và nhận từ "lớp" ..pls sử dụng một khóa hoặc "lớp" hoặc "gói" ..
AK Joshi

Tôi phải đối mặt với Lỗi: Parcelable gặp phải đối tượng viết tuần tự IOException
Arul Mani

15

Cách tốt nhất là có một lớp (gọi nó là Control) trong ứng dụng của bạn sẽ giữ một biến tĩnh loại 'Khách hàng' (trong trường hợp của bạn). Khởi tạo biến trong Hoạt động A. của bạn

Ví dụ:

Control.Customer = CustomerClass;

Sau đó đi đến Hoạt động B và tìm nạp nó từ lớp Control. Đừng quên gán null sau khi sử dụng biến, nếu không bộ nhớ sẽ bị lãng phí.


4
@aez Bởi vì nó cẩu thả từ quan điểm thiết kế và sẽ phá vỡ khủng khiếp nếu Ý định đang ở trong một quy trình khác.

7
Bạn sẽ gặp vấn đề khi tiếp tục ứng dụng của mình vào Hoạt động B. Vì Hoạt động có thể bị Android hủy và đối tượng sẽ không được lưu.
Ryan R

15
public class MyClass implements Serializable{
    Here is your instance variable
}

Bây giờ bạn muốn truyền đối tượng của lớp này trong startActivity. Đơn giản chỉ cần sử dụng này:

Bundle b = new Bundle();
b.putSerializable("name", myClassObject);
intent.putExtras(b);

Điều này hoạt động ở đây vì MyClass thực hiện Serializable.


bạn có thể vui lòng giải thích hoặc giải thích thêm
Amitsharma

Bài tập về nhàData bài tập về nhàData = homeWorksList.get (vị trí); Mục đích ý định = ý định mới (c, HomeWorkActivitydetail. Class); Gói b = Gói mới (); b.putSerializable ("CompleteData", homeworkData); aim.putExtras (b); c.startActivity (ý định); tại thời điểm thêm đối tượng, cho tôi một số lỗi khi thêm các phần tử đối tượng, chúng ta không thể vượt qua đối tượng hoàn chỉnh với điều này
Amitsharma

bên trong bài tập về
nhàData

12

Nếu bạn chọn sử dụng cách Samuh mô tả, hãy nhớ rằng chỉ có thể gửi các giá trị nguyên thủy. Đó là, các giá trị là parcable. Vì vậy, nếu đối tượng của bạn chứa các đối tượng phức tạp thì những đối tượng này sẽ không tuân theo. Ví dụ: các biến như Bitmap, HashMap, v.v ... Đây là những mẹo khó để vượt qua ý định.

Nói chung tôi sẽ tư vấn cho bạn để gửi các kiểu dữ liệu nguyên thủy chỉ đóng vai phụ, như String, int, boolean vv Trong trường hợp của bạn nó sẽ là: String fname, String lname, int age, vàString address .

Ý kiến ​​của tôi: Các đối tượng phức tạp hơn được chia sẻ tốt hơn bằng cách triển khai ContentProvider , SDCard , v.v. Cũng có thể sử dụng biến tĩnh , nhưng điều này có thể nhanh chóng dẫn đến mã dễ bị lỗi ...

Nhưng một lần nữa, đó chỉ là ý kiến ​​chủ quan của tôi.


8

Tôi đang sử dụng bưu kiện để gửi dữ liệu từ hoạt động này sang hoạt động khác. Đây là mã của tôi hoạt động tốt trong dự án của tôi.

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

Trong hoạt độngA sử dụng nó như thế này:

Bundle bundle = new Bundle();
bundle.putParcelableArrayList("channel",(ArrayList<Channel>) channels);
Intent intent = new Intent(ActivityA.this,ActivityB.class);
intent.putExtras(bundle);
startActivity(intent);

Trong ActivityB sử dụng nó như thế này để lấy dữ liệu:

Bundle getBundle = this.getIntent().getExtras();
List<Channel> channelsList = getBundle.getParcelableArrayList("channel");

7

Bạn có thể thử sử dụng lớp đó. Hạn chế là nó không thể được sử dụng ngoài một quy trình.

Một hoạt động:

 final Object obj1 = new Object();
 final Intent in = new Intent();
 in.putExtra(EXTRA_TEST, new Sharable(obj1));

Hoạt động khác:

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

6

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

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

Lấy lại dữ liệu trên mộ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 ở giữa hoạt động. Bạn cần phải tuần tự hóa nó trước.

Ở đâ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);

TypeToken <> không được dùng nữa. Cái gì thay thế?
Ragavendra M

6

Câu hỏi này cũng được thảo luận trong một câu hỏi khác về Stack Overflow. Vui lòng xem giải pháp Truyền dữ liệu thông qua ý định sử dụng Nối tiếp . Điểm chính là về việc sử dụng Bundleđối tượng lưu trữ dữ liệu cần thiết bên trong Intent.

 Bundle bundle = new Bundle();

 bundle.putSerializable(key1, value1);
 bundle.putSerializable(key2, value2);
 bundle.putSerializable(key3, value3);

 intent.putExtras(bundle);

Để trích xuất các giá trị:

 Bundle bundle = new Bundle();

 for (String key : bundle.keySet()) {
 value = bundle.getSerializable(key));
 }

Ưu điểm Serializablelà sự đơn giản của nó. Tuy nhiên, bạn nên cân nhắc sử dụng Parcelablephương thức nếu bạn cần chuyển nhiều dữ liệu, vì Parcelableđược thiết kế riêng cho Android và nó hiệu quả hơn Serializable. Bạn có thể tạo Parcelablelớp bằng cách sử dụng:

  1. một công cụ trực tuyến - bưu kiện
  2. một plugin cho Android Studio - Trình tạo mã Parcelable của Android

5

Một lớp giống như lớp đậu và thực hiện Serializablegiao diện. Sau đó, chúng ta có thể chuyển nó qua intentphương thức, ví dụ:

intent.putExtra("class", BeanClass);

Sau đó lấy nó từ hoạt động khác, ví dụ:

BeanClass cb = intent.getSerializableExtra("class");

5

Tạo hai phương thức trong Lớp tùy chỉnh của bạn như thế này

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

Bây giờ trong hoạt động người gửi của bạn làm như thế này

Qabir q= new Qabir(22,"KQ");    
Intent in=new Intent(this,SubActivity.class);
in.putExtra("obj", q.toJSON());
startActivity( in);

Và trong hoạt động nhận của bạn

Qabir q =new Qabir();
q.initilizeWithJSONString(getIntent().getStringExtra("obj"));

3

Vâng, sử dụng một đối tượng tĩnh là cách dễ nhất để làm điều này với các đối tượng không nối tiếp tùy chỉnh.


Vâng, tôi nghĩ rằng tôi thực sự đồng ý với bạn. Làm cho các đối tượng đó staticlà cách giải quyết tốt hơn nếu đơn giản là không thực tế để tiếp tục gọi putExtra()cho mọi tài sản bạn muốn truyền lại. Ví dụ, ngay bây giờ, tôi muốn vượt qua một ArrayListcó chứa các đối tượng. Tôi cũng có thể tạo ArrayList của tôi staticthay thế.
Matthew Quiros

3

Các đối tượng Hoạt động của Android có thể bị hủy và hoàn nguyên. Vì vậy, bạn sẽ cần sử dụng một cách tiếp cận khác để xem chúng - hoặc bất kỳ đối tượng nào chúng tạo ra !!! - lên. Nghĩa là, bạn có thể chuyển dưới dạng tham chiếu lớp tĩnh nhưng sau đó xử lý đối tượng (Java gọi đây là "tham chiếu", cũng như SmallTalk; nhưng chúng không phải là tham chiếu theo nghĩa C hoặc lắp ráp) sẽ có thể không hợp lệ sau này vì "tính năng" của Android OE là bất kỳ Hoạt động nào cũng có thể bị hủy và hoàn nguyên sau đó.

Câu hỏi ban đầu hỏi "Làm thế nào để chuyển đối tượng từ hoạt động này sang hoạt động khác trong Android" và không ai trả lời được điều đó. Để chắc chắn, bạn có thể tuần tự hóa (Nối tiếp, Parcelable, đến / từ JSON) và truyền một bản sao dữ liệu của đối tượng và một đối tượng mới có cùng dữ liệu có thể được tạo; nhưng nó sẽ KHÔNG có cùng tham chiếu / xử lý. Ngoài ra, nhiều người khác đề cập bạn có thể lưu trữ tài liệu tham khảo trong một cửa hàng tĩnh. Và điều đó sẽ hoạt động trừ khi Android quyết định onDestroy Hoạt động của bạn.

Vì vậy, để thực sự giải quyết câu hỏi ban đầu, bạn sẽ cần một tra cứu tĩnh cộng với mỗi đối tượng sẽ cập nhật tham chiếu của nó khi / nếu nó được tạo lại. Ví dụ: mỗi Hoạt động của Android sẽ tự tồn tại nếu onCreate của nó được gọi. Bạn cũng có thể thấy cách một số người sử dụng danh sách tác vụ để tìm kiếm một Hoạt động theo tên. (hệ thống đang tạm thời hủy bỏ phiên bản hoạt động này để tiết kiệm dung lượng..getRastyT Nhiệm vụ, danh sách nhiệm vụ thực sự là một danh sách chuyên biệt về phiên bản đối tượng gần đây nhất của mỗi Hoạt động).

Để tham khảo:

Đã dừng: "Hoạt động bị che khuất hoàn toàn bởi một hoạt động khác (hoạt động hiện đang ở" nền "). Một hoạt động bị dừng vẫn còn tồn tại ( đối tượng Activity được giữ lại trong bộ nhớ , nó duy trì tất cả thông tin trạng thái và thành viên, nhưng không gắn liền với trình quản lý cửa sổ). Tuy nhiên, nó không còn hiển thị cho người dùng nữa và nó có thể bị hệ thống giết chết khi cần bộ nhớ ở nơi khác. "

onDestroy "hệ thống đang tạm thời phá hủy phiên bản hoạt động này để tiết kiệm không gian."

Vì vậy, Message Bus là một giải pháp khả thi. Về cơ bản nó là "punts". Thay vì cố gắng có các tài liệu tham khảo đến các đối tượng; sau đó bạn tái kiến ​​trúc thiết kế của bạn để sử dụng MessagePassing thay vì SequentialCode. Khó khăn hơn theo cấp số nhân; nhưng nó cho phép bạn bỏ qua những cách hiểu về Môi trường hoạt động. Thực tế, mỗi lần truy cập phương thức đối tượng được đảo ngược để người gọi đăng một Thông báo và chính đối tượng xác định một trình xử lý cho thông báo đó. Nhiều mã hơn nhưng có thể làm cho nó mạnh mẽ hơn với các hạn chế OE của Android.

Nếu tất cả những gì bạn muốn là Hoạt động hàng đầu (điều điển hình trong các ứng dụng Android do "Bối cảnh" là cần thiết ở mọi nơi), thì bạn chỉ có thể để mỗi Hoạt động liệt kê chính nó là "hàng đầu" trong không gian toàn cầu tĩnh bất cứ khi nào onResume được gọi. Sau đó, AlertDialog của bạn hoặc bất cứ thứ gì cần bối cảnh đều có thể lấy nó từ đó. Ngoài ra, hơi khó để sử dụng toàn cầu nhưng có thể đơn giản hóa việc chuyển một Ngữ cảnh lên xuống ở mọi nơi và chắc chắn, khi bạn sử dụng MessageBus thì dù sao thì IT IS cũng là toàn cầu.


Otto có khả năng chạy nó bên ngoài chỉ trong một ứng dụng Java cũ đơn giản. Vì vậy, tốt cho dev và thử nghiệm mà không phải gặp rắc rối với Android. Otto có đường cong học tập lớn và hầu hết những gì nó giải quyết được đã được giải quyết theo cách của Android (phát sóng địa phương, v.v.) hoặc trong các phương pháp tiếp cận ứng dụng thông thường (bạn có thể viết một tra cứu toàn cầu đơn giản hơn nhiều so với tra cứu toàn cầu của Otto, các cách tiếp cận thông thường rất nhiều dễ tiếp cận hơn cho vectơ / F3 thông qua mã và để từng bước gỡ lỗi).
TimJowers2

2
  1. Tôi biết rằng tĩnh là xấu, nhưng dường như chúng ta buộc phải sử dụng nó ở đây. Vấn đề với parceabled / seriazables là hai hoạt động có các phiên bản trùng lặp của cùng một đối tượng = lãng phí bộ nhớ và CPU.

    public class IntentMailBox {
        static Queue<Object> content = new LinkedList<Object>();
    }

Hoạt động gọi điện

IntentMailBox.content.add(level);
Intent intent = new Intent(LevelsActivity.this, LevelActivity.class);
startActivity(intent);

Hoạt động được gọi (lưu ý rằng onCreate ()onResume () có thể được gọi nhiều lần khi hệ thống phá hủy và tạo lại các hoạt động)

if (IntentMailBox.content.size()>0)
    level = (Level) IntentMailBox.content.poll();
else
    // Here you reload what you have saved in onPause()
  1. Một cách khác là khai báo một trường tĩnh của lớp mà bạn muốn vượt qua trong chính lớp đó. Nó sẽ chỉ phục vụ cho mục đích này. Đừng quên rằng nó có thể là null trong onCreate, vì gói ứng dụng của bạn đã được hệ thống tải khỏi bộ nhớ và tải lại sau đó.

  2. Lưu ý rằng bạn vẫn cần xử lý vòng đời hoạt động, bạn có thể muốn ghi tất cả dữ liệu vào các tùy chọn chia sẻ, đau đớn với các cấu trúc dữ liệu phức tạp như hiện tại.


1

Các câu trả lời trên hầu hết đều đúng nhưng đối với những người không hủy bỏ những câu trả lời đó, Android có lớp Ý định mạnh mẽ với sự giúp đỡ của bạn, bạn chia sẻ dữ liệu giữa không chỉ hoạt động mà cả các thành phần khác của Android (máy thu phát rộng, phục vụ cho nội dung cung cấp chúng tôi sử dụng lớp ContetnResolver không có ý định ). Trong hoạt động của bạn, bạn xây dựng ý định

Intent intent = new Intent(context,SomeActivity.class);
intent.putExtra("key",value);
startActivity(intent);

Trong hoạt động tiếp nhận của bạn, bạn có

public class SomeActivity extends AppCompactActivity {

    public void onCreate(...){
    ...
          SomeObject someObject = getIntent().getExtras().getParceable("key");
    }

}

Bạn phải triển khai giao diện có thể điều chỉnh hoặc nối tiếp trên đối tượng của mình để chia sẻ giữa các hoạt động. Thật khó có thể thực hiện Parcealbe hơn là Serializable giao diện trên đối tượng đó là lý do tại sao android đã cắm đặc biệt đối với this.Download nó và sử dụng nó


0

Tôi đã luôn tự hỏi tại sao điều này không thể đơn giản như gọi vào một phương thức của hoạt động khác. Gần đây tôi đã viết một thư viện tiện ích làm cho nó gần như đơn giản như vậy. Bạn có thể kiểm tra nó ở đây ( https://github.com/noxiouswinter/gnlib_android/wiki/gnlauncher ).

GNLauncher làm cho việc gửi các đối tượng / dữ liệu đến một Hoạt động từ một Hoạt động khác, v.v ... dễ dàng như gọi một hàm trong Hoạt động với dữ liệu được yêu cầu làm tham số. Nó giới thiệu loại an toàn và loại bỏ tất cả sự vội vàng của việc phải tuần tự hóa, gắn với mục đích bằng cách sử dụng các phím chuỗi và hoàn tác tương tự ở đầu kia.

Sử dụng

Xác định giao diện với các phương thức bạn muốn gọi trên Activity để khởi chạy.

public interface IPayload {
    public void sayHello(String name, int age);
}

Thực hiện giao diện trên trên Activity để khởi chạy vào. Đồng thời thông báo cho GNLauncher khi hoạt động đã sẵn sàng.

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

Trong Hoạt động khác, nhận proxy cho Hoạt động trên và gọi bất kỳ phương thức nào có tham số mong muốn.

public class Activity_2 extends Activity {
    public void onClick(View v) {
        ((IPayload)GNLauncher.get().getProxy(this, IPayload.class, Activity_1.class)).sayHello(name, age);
    }
}

Hoạt động đầu tiên sẽ được khởi chạy và phương thức được gọi với các tham số cần thiết.

Điều kiện tiên quyết

Vui lòng tham khảo https://github.com/noxiouswinter/gnlib_android/wiki#prerequisites để biết thông tin về cách thêm phụ thuộc.


0

Truyền đối tượng từ hoạt động này sang hoạt động khác.

(1) hoạt động nguồn

Intent ii = new Intent(examreport_select.this,
                    BarChartActivity.class);

            ii.putExtra("IntentExamResultDetail",
                    (Serializable) your List<ArraList<String>> object here);
            startActivity(ii);

(2) tính nhạy cảm đích

List<ArrayList<String>> aa = (List<ArrayList<String>>) getIntent()
            .getSerializableExtra("IntentExamResultDetail");

0

Tôi đã từng đặt đối tượng với Pacelable hoặc serializable để chuyển, nhưng bất cứ khi nào tôi thêm các biến khác vào đối tượng (mô hình), tôi phải đăng ký tất cả. Nó rất tiện lợi.

Thật dễ dàng để chuyển đối tượng giữa các hoạt động hoặc các mảnh.

Dữ liệu Android


0

Chúng ta có thể chuyển đối tượng từ hoạt động này sang hoạt động khác:

SupplierDetails poSuppliersDetails = new SupplierDetails();

Bên trong poSuppliersDetailschúng tôi có một số giá trị. Bây giờ tôi đang gửi đối tượng này đến hoạt động mục tiêu:

Intent iPODetails = new Intent(ActivityOne.this, ActivityTwo.class);
iPODetails.putExtra("poSuppliersDetails", poSuppliersDetails);

Làm thế nào để có được điều này trong ACtivityTwo:

private SupplierDetails supplierDetails;
    supplierDetails =(SupplierDetails) getIntent().getSerializableExtra("poSuppliersDetails");

0

Truyền một hoạt động này sang hoạt động khác:

startActivity(new Intent(getBaseContext(),GetActivity.class).putExtra("passingkey","passingvalue"));

Nhận giá trị:

String myvalue= getIntent().getExtras("passingkey");

-1

Xin chào tất cả tôi thấy rất nhiều lựa chọn tốt nhưng tôi đã tự hỏi tại sao Binding không được sử dụng?

Chuyển một tài liệu tham khảo đến một đối tượng có vẻ hiệu quả hơn đối với tôi so với việc tuần tự hóa và khử trùng các đối tượng, nhưng tôi đã không thực hiện một cuộc lặn sâu để xem liệu đó có phải là những gì đang diễn ra sau hậu trường không.

Tạo Binder đủ đơn giản ...

public class MyBinder extends Binder {

    private Object myObject;

    public MyBinder(Object object) {
        myObject = object;
    }

    public Object getObject() {
        return myObject;
    }

}

Và tạo ra các bưu kiện để sử dụng nó không phải là ether xấu.

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

    };
}

Logic này thực sự thú vị bởi vì bạn thực sự đang chuyển một tài liệu tham khảo từ hoạt động này sang hoạt động khác.

Tôi sẽ khuyên bạn nên kiểm tra null và nếu Binder dụ là MyBinder!

và để thực hiện điều này, bạn chỉ cần ...

Gửi đi

Object myObject = "some object";
MyParcelable myParcelable = new MyParcelable();
myParcelable.setObject(myObject);

intent.putExtra("MyParcelable", myParcelable);

Lấy lại

myParcelable = (MyParcelable) getIntent().getExtras().getParcelable("MyParcelable");
myObject = myParcelable.getObject();

Heck ai đó có thể nhận được tất cả điên rồ và làm cho kẻ hút này là một chung chung thực sự.

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.