ฉันต้องส่งการอ้างอิงไปยังคลาสที่ประมวลผลส่วนใหญ่ผ่านบันเดิล
ปัญหาคือมันไม่เกี่ยวข้องกับเจตนาหรือบริบทและมีวัตถุที่ไม่ใช่ดั้งเดิมจำนวนมาก ฉันจะบรรจุคลาสเป็นแบบพัสดุ / ซีเรียลได้และส่งต่อไปยัง a ได้startActivityForResult
อย่างไร
ฉันต้องส่งการอ้างอิงไปยังคลาสที่ประมวลผลส่วนใหญ่ผ่านบันเดิล
ปัญหาคือมันไม่เกี่ยวข้องกับเจตนาหรือบริบทและมีวัตถุที่ไม่ใช่ดั้งเดิมจำนวนมาก ฉันจะบรรจุคลาสเป็นแบบพัสดุ / ซีเรียลได้และส่งต่อไปยัง a ได้startActivityForResult
อย่างไร
คำตอบ:
การคิดว่าจะใช้เส้นทางใดไม่เพียง แต่ต้องตอบคำถามสำคัญของ CommonsWare ที่ว่า "ทำไม" แต่ยังต้องตอบคำถาม "ถึงอะไร" ด้วย คุณผ่านมันไปหรือเปล่า
ความจริงก็คือสิ่งเดียวที่สามารถผ่านบันเดิลได้คือข้อมูลธรรมดาทุกอย่างจะขึ้นอยู่กับการตีความว่าข้อมูลนั้นหมายถึงหรือชี้ไปที่อะไร คุณไม่สามารถผ่านวัตถุได้อย่างแท้จริง แต่สิ่งที่คุณทำได้คือหนึ่งในสามสิ่ง:
1) คุณสามารถแยกออบเจ็กต์ออกเป็นข้อมูลที่สร้างขึ้นและหากสิ่งที่อยู่ในอีกด้านหนึ่งมีความรู้เกี่ยวกับอ็อบเจ็กต์ประเภทเดียวกันก็สามารถรวบรวมโคลนจากข้อมูลที่ต่อเนื่องกันได้ นั่นคือวิธีที่ประเภททั่วไปส่วนใหญ่ส่งผ่านบันเดิล
2) คุณสามารถส่งที่จับทึบแสงได้ หากคุณกำลังส่งผ่านภายในบริบทเดียวกัน (แม้ว่าจะมีคนถามว่าทำไมต้องรำคาญ) นั่นจะเป็นจุดจับที่คุณสามารถเรียกหรือหักล้างได้ แต่ถ้าคุณส่งผ่าน Binder ไปยังบริบทอื่นค่าตามตัวอักษรจะเป็นตัวเลขที่กำหนดเอง (อันที่จริงแล้วตัวเลขเหล่านี้จะนับตามลำดับจากการเริ่มต้น) คุณไม่สามารถทำอะไรได้นอกจากติดตามมันจนกว่าคุณจะส่งกลับไปยังบริบทเดิมซึ่งจะทำให้ Binder เปลี่ยนกลับเป็นแฮนเดิลเดิมทำให้มีประโยชน์อีกครั้ง
3) คุณสามารถส่งที่จับวิเศษเช่นตัวอธิบายไฟล์หรือการอ้างอิงไปยังออบเจ็กต์ระบบปฏิบัติการ / แพลตฟอร์มบางอย่างและหากคุณตั้งค่าแฟล็กที่ถูกต้อง Binder จะสร้างโคลนที่ชี้ไปยังทรัพยากรเดียวกันสำหรับผู้รับซึ่งสามารถใช้งานได้จริง อีกด้านหนึ่ง แต่สิ่งนี้ใช้ได้กับวัตถุบางประเภทเท่านั้น
เป็นไปได้มากว่าคุณกำลังส่งผ่านชั้นเรียนของคุณเพื่อให้ปลายอีกด้านสามารถติดตามและส่งคืนให้คุณในภายหลังหรือคุณกำลังส่งต่อไปยังบริบทที่สามารถสร้างโคลนจากข้อมูลที่เป็นส่วนประกอบแบบอนุกรม ... หรืออื่น ๆ คุณกำลังพยายามทำบางสิ่งที่ไม่ได้ผลและคุณต้องคิดใหม่ทั้งแนวทาง
คุณยังสามารถใช้ Gson เพื่อแปลงวัตถุเป็น JSONObject และส่งต่อไปยังบันเดิล สำหรับฉันเป็นวิธีที่สง่างามที่สุดที่ฉันพบในการทำเช่นนี้ ฉันยังไม่ได้ทดสอบว่ามันมีผลต่อประสิทธิภาพอย่างไร
ในกิจกรรมเริ่มต้น
Intent activity = new Intent(MyActivity.this,NextActivity.class);
activity.putExtra("myObject", new Gson().toJson(myobject));
startActivity(activity);
ในกิจกรรมถัดไป
String jsonMyObject;
Bundle extras = getIntent().getExtras();
if (extras != null) {
jsonMyObject = extras.getString("myObject");
}
MyObject myObject = new Gson().fromJson(jsonMyObject, MyObject.class);
Parcelableอินเตอร์เฟซที่เป็นวิธีที่ดีที่จะผ่านวัตถุที่มีเจตนา
ฉันจะทำให้ออบเจ็กต์แบบกำหนดเองของฉันเป็นพัสดุได้อย่างไร เป็นคำตอบที่ดีในการใช้งานParcelable
นอกจากนี้Google เอกสารอย่างเป็นทางการยังมีตัวอย่าง
คุณสามารถใช้สถานะแอปพลิเคชันส่วนกลาง
ปรับปรุง:
ปรับแต่งแล้วเพิ่มสิ่งนี้ใน AndroidManifest.xml ของคุณ:
<application android:label="@string/app_name" android:debuggable="true" android:name=".CustomApplication"
จากนั้นมีชั้นเรียนในโครงการของคุณดังนี้:
package com.example;
import android.app.Application;
public class CustomApplication extends Application {
public int someVariable = -1;
}
และเนื่องจาก " สามารถเข้าถึงได้ผ่าน getApplication () จากกิจกรรมหรือบริการใด ๆ " คุณจึงใช้สิ่งนี้:
CustomApplication application = (CustomApplication)getApplication();
application.someVariable = 123;
หวังว่าจะช่วยได้
นอกจากนี้คุณยังสามารถทำให้วัตถุของคุณSerializableและใช้ Bundle ของgetSerializableและputSerializableวิธี
แนวทางแก้ไขที่เป็นไปได้:
Bundle bundle = new Bundle();
bundle.putSerializable("key", new CustomObject());
คลาส CustomObject:
class CustomObject implements Serializable{
private SubCustomObject1 sc1;
private SubCustomObject2 sc2;
}
วัตถุที่กำหนดเองย่อย:
class SubCustomObject1 implements Serializable{ }
class SubCustomObject2 implements Serializable{ }
อีกวิธีหนึ่งในการส่งวัตถุผ่านบันเดิลคือการใช้bundle.putByteArray
โค้ดตัวอย่าง
public class DataBean implements Serializable {
private Date currentTime;
public setDate() {
currentTime = Calendar.getInstance().getTime();
}
public Date getCurrentTime() {
return currentTime;
}
}
ใส่ Object ของ DataBean ไว้ใน Bundle:
class FirstClass{
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Your code...
//When you want to start new Activity...
Intent dataIntent =new Intent(FirstClass.this, SecondClass.class);
Bundle dataBundle=new Bundle();
DataBean dataObj=new DataBean();
dataObj.setDate();
try {
dataBundle.putByteArray("Obj_byte_array", object2Bytes(dataObj));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
dataIntent.putExtras(dataBundle);
startActivity(dataIntent);
}
การแปลงวัตถุเป็นไบต์อาร์เรย์
/**
* Converting objects to byte arrays
*/
static public byte[] object2Bytes( Object o ) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream( baos );
oos.writeObject( o );
return baos.toByteArray();
}
รับ Object คืนจาก Bundle:
class SecondClass{
DataBean dataBean;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Your code...
//Get Info from Bundle...
Bundle infoBundle=getIntent().getExtras();
try {
dataBean = (DataBean)bytes2Object(infoBundle.getByteArray("Obj_byte_array"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
วิธีการรับวัตถุจากไบต์อาร์เรย์:
/**
* Converting byte arrays to objects
*/
static public Object bytes2Object( byte raw[] )
throws IOException, ClassNotFoundException {
ByteArrayInputStream bais = new ByteArrayInputStream( raw );
ObjectInputStream ois = new ObjectInputStream( bais );
Object o = ois.readObject();
return o;
}
หวังว่านี่จะช่วยเพื่อนคนอื่น ๆ
1. ตัวอย่างที่ตรงและใช้งานง่ายมากทำให้วัตถุที่จะส่งผ่านไปใช้งาน Serial ได้
class Object implements Serializable{
String firstName;
String lastName;
}
2. ส่งผ่านวัตถุในกลุ่ม
Bundle bundle = new Bundle();
Object Object = new Object();
bundle.putSerializable("object", object);
3. รับอ็อบเจกต์ที่ส่งจากบันเดิลเป็นอนุกรมได้จากนั้นส่งไปยังอ็อบเจ็กต์
Object object = (Object) getArguments().getSerializable("object");
นี่เป็นคำตอบที่ล่าช้ามากสำหรับคำถามของฉันเอง แต่ก็ยังคงได้รับความสนใจอยู่เสมอดังนั้นฉันจึงรู้สึกว่าต้องจัดการกับมัน คำตอบเหล่านี้ส่วนใหญ่ถูกต้องและจัดการกับงานได้อย่างสมบูรณ์แบบ อย่างไรก็ตามขึ้นอยู่กับความต้องการของแอปพลิเคชัน คำตอบนี้จะใช้เพื่ออธิบายวิธีแก้ปัญหานี้สองวิธี
บริการเป็นส่วนประกอบของแอปพลิเคชันที่สามารถดำเนินการในระยะยาวได้ พื้นหลังและไม่มีส่วนติดต่อผู้ใช้บริการมีความเรียบร้อยเนื่องจากมีวงจรชีวิตที่กำหนดไว้มากขึ้นซึ่งง่ายต่อการควบคุม นอกจากนี้หากจำเป็นบริการต่างๆสามารถเรียกใช้แอปพลิเคชันภายนอกได้ (เช่นในการบูต) สิ่งนี้อาจจำเป็นสำหรับบางแอพหรือเป็นเพียงคุณสมบัติที่เรียบร้อย
นี่ไม่ใช่คำอธิบายทั้งหมด แต่ฉันทิ้งลิงก์ไปยังเอกสารสำหรับผู้ที่ต้องการตรวจสอบเพิ่มเติม โดยรวมแล้วสิ่งService
ที่ดีกว่าสำหรับอินสแตนซ์ที่ฉันต้องการคือการเรียกใช้ ServerSocket ไปยังอุปกรณ์ SPP ของฉัน
ฉันเจอคำถามนี้เมื่อฉันกำลังมองหาวิธีส่งผ่านวัตถุ Date ในกรณีของฉันตามที่แนะนำในคำตอบฉันใช้ Bundle.putSerializable () แต่จะใช้ไม่ได้กับสิ่งที่ซับซ้อนตามที่ DataManager อธิบายไว้ในโพสต์ต้นฉบับ
ข้อเสนอแนะของฉันที่จะให้ผลลัพธ์ที่คล้ายกันมากกับการวาง DataManager ดังกล่าวในแอปพลิเคชันหรือทำให้เป็น Singleton คือการใช้ Dependency Injection และผูก DataManager กับขอบเขต Singleton และฉีด DataManager ทุกที่ที่ต้องการ ไม่เพียง แต่คุณจะได้รับประโยชน์จากความสามารถในการทดสอบที่เพิ่มขึ้น แต่คุณยังจะได้รับรหัสที่สะอาดขึ้นโดยไม่ต้องใช้รหัส "ส่งผ่านการอ้างอิงระหว่างชั้นเรียนและกิจกรรม" ทั้งหมด (Robo) Guiceนั้นใช้งานง่ายมากและเฟรมเวิร์กDaggerใหม่ก็มีแนวโน้มที่ดีเช่นกัน
อีกวิธีง่ายๆในการส่งผ่านวัตถุโดยใช้บันเดิล: