如何通过序列化在Intent之间传递自定义ArrayAdapter对象 [英] How do I pass custom ArrayAdapter Object between Intents with serialization
问题描述
背景:
我只是从Android入手,我已经了解了Intent和ListView
.我正在创建一个简单的应用程序,用户在其中输入一些信息,并将该信息添加到ListView中.为此,我在MainActivity类中创建了一个ListView.为名为User
的对象创建了一个类,并创建了自定义ArrayAdapter UserAdapter.
.我的已分类User
和UserAdapter
都实现了Serializable
标记接口.现在,只要有人单击MainActivity
类中的按钮以添加数据,就会打开一个新的Intent,并从该intent中获取输入,然后返回到MainActivity
intent.我在意图之间传递了UserAdapter
对象.
问题:
现在,适配器对象显示的问题在下一个Intent中不起作用.
代码:
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//blah blah blah ...
// Main code starts here
ListView listView = (ListView) findViewById(R.id.list);
ArrayList<User> arrayList = new ArrayList<>();
UserAdapter adapter = new UserAdapter(this, arrayList);
listView.setAdapter(adapter);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(v.getContext(), AddUser.class);
intent.putExtra("adapter", adapter);
startActivity(intent);
}
});
}
//blah blah blah ...
}
UserAdapter.java
public class UserAdapter extends ArrayAdapter<User> implements Serializable {
public UserAdapter(Context context, Collection<User> arrayList) {
//call ArrayAdapter's constructor
//context, layout, collection
super(context, 0, (ArrayList<User>)arrayList);
}
@Override
public View getView(int position, View obj, ViewGroup parent) {
User user = getItem(position);
if(obj == null) {
obj = LayoutInflater.from(getContext()).inflate(R.layout.user_layout, parent, false);
}
TextView name = (TextView) obj.findViewById(R.id.user_name);
TextView adress = (TextView) obj.findViewById(R.id.user_address);
name.setText(user.getUserName());
adress.setText(user.getUserAddress());
return obj;
}
}
用户类也实现了Serializable,我认为您不需要该类的实现,但是如果您愿意,我可以在此处添加.
现在我的第二个活动班 AddUser.java
public class AddUser extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_user);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String name = ((EditText) findViewById(R.id.name)).getText().toString();
String address = ((EditText) findViewById(R.id.address)).getText().toString();
String contact = ((EditText) findViewById(R.id.contact)).getText().toString();
String college = ((EditText) findViewById(R.id.college)).getText().toString();
User user = new User(name, address);
user.setCollege(college);
user.setContact(contact);
Intent intent = new Intent(v.getContext(), MainActivity.class);
UserAdapter adapter = (UserAdapter)getIntent().getSerializableExtra("Adapter");
adapter.add(user);
finish();
startActivity(intent);
}
});
}
}
Logcat
02-20 18:35:37.264 12074-12074/com.example.deepanshu.customadapter3 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.deepanshu.customadapter3, PID: 12074
java.lang.RuntimeException: Parcelable encountered IOException reading a Serializable object (name =com.example.deepanshu.customadapter3.UserAdapter)
at android.os.Parcel.readSerializable(Parcel.java:2380)
at android.os.Parcel.readValue(Parcel.java:2203)
at android.os.Parcel.readArrayMapInternal(Parcel.java:2485)
at android.os.BaseBundle.unparcel(BaseBundle.java:221)
at android.os.BaseBundle.getSerializable(BaseBundle.java:988)
at android.os.Bundle.getSerializable(Bundle.java:845)
at android.content.Intent.getSerializableExtra(Intent.java:5256)
at com.example.deepanshu.customadapter3.AddUser$2.onClick(AddUser.java:47)
at android.view.View.performClick(View.java:4789)
at android.view.View$PerformClick.run(View.java:19881)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5292)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
Caused by: java.io.InvalidClassException: android.widget.ArrayAdapter; IllegalAccessException
at java.io.ObjectStreamClass.resolveConstructorClass(ObjectStreamClass.java:712)
at java.io.ObjectStreamClass.newInstance(ObjectStreamClass.java:673)
at java.io.ObjectInputStream.readNewObject(ObjectInputStream.java:1796)
at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:761)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1983)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1940)
at android.os.Parcel.readSerializable(Parcel.java:2378)
at android.os.Parcel.readValue(Parcel.java:2203)
at android.os.Parcel.readArrayMapInternal(Parcel.java:2485)
at android.os.BaseBundle.unparcel(BaseBundle.java:221)
at android.os.BaseBundle.getSerializable(BaseBundle.java:988)
at android.os.Bundle.getSerializable(Bundle.java:845)
at android.content.Intent.getSerializableExtra(Intent.java:5256)
at com.example.deepanshu.customadapter3.AddUser$2.onClick(AddUser.java:47)
at android.view.View.performClick(View.java:4789)
at android.view.View$PerformClick.run(View.java:19881)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5292)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
您无法在此处
签出代码也请在我的Github个人资料中检查问题.
您不能故意传递自定义ArrayAdapter
或任何其他BaseAdapter/ArrayAdapter
对象.
您知道要按意图传递任何对象,它应该是Parcelable
或Serializable
.
根据Serializable接口的文档 https://developer.android.com/reference/java/io/Serializable.html
序列化机制对对象的类名称(即名称)进行编码 它的非瞬态字段(包括非公共字段),以及 所有这些字段的值.
在这里,当您对自定义的ArrayAdapter
类实现Serializable
接口时,实际上并没有获得序列化的能力,因为在实现Serializable
接口时,所有字段都将参与序列化过程.>
但是 android.widget.ArrayAdapter 类本身确实可以无法实现Serializable
界面.
因此,间接继承自android.widget.ArrayAdapter
的自定义ArrayAdapter
也不是Serializable
.
并考虑您的示例(如注释中所述),请使用startActivityForResult()
调用该意图,以将对象添加到您的自定义适配器中.
希望您能理解这一点!
了解有关序列化过程的更多信息!
Background:
I am just starting with Android and I have learned about Intents and ListView
. I have am creating a simple app where a user enter some information and that information is added into ListView. For this I have created a ListView in my MainActivity class. Created a class for Objects named User
and created Custom ArrayAdapter UserAdapter.
Both of my classed User
and UserAdapter
implements Serializable
marker interface. Now whenever someone click on button from MainActivity
class to add data a new Intent opens and takes input from that intent and return back to MainActivity
intent. I am passing UserAdapter
Object between intents.
Problem:
Now the problem Adapter Object is showing is not working in next Intent.
Code:
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//blah blah blah ...
// Main code starts here
ListView listView = (ListView) findViewById(R.id.list);
ArrayList<User> arrayList = new ArrayList<>();
UserAdapter adapter = new UserAdapter(this, arrayList);
listView.setAdapter(adapter);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(v.getContext(), AddUser.class);
intent.putExtra("adapter", adapter);
startActivity(intent);
}
});
}
//blah blah blah ...
}
UserAdapter.java
public class UserAdapter extends ArrayAdapter<User> implements Serializable {
public UserAdapter(Context context, Collection<User> arrayList) {
//call ArrayAdapter's constructor
//context, layout, collection
super(context, 0, (ArrayList<User>)arrayList);
}
@Override
public View getView(int position, View obj, ViewGroup parent) {
User user = getItem(position);
if(obj == null) {
obj = LayoutInflater.from(getContext()).inflate(R.layout.user_layout, parent, false);
}
TextView name = (TextView) obj.findViewById(R.id.user_name);
TextView adress = (TextView) obj.findViewById(R.id.user_address);
name.setText(user.getUserName());
adress.setText(user.getUserAddress());
return obj;
}
}
User class also implements Serializable and I don't think you need that class implementation but if you want I can add that here.
Now My Second Activiy class AddUser.java
public class AddUser extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_user);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String name = ((EditText) findViewById(R.id.name)).getText().toString();
String address = ((EditText) findViewById(R.id.address)).getText().toString();
String contact = ((EditText) findViewById(R.id.contact)).getText().toString();
String college = ((EditText) findViewById(R.id.college)).getText().toString();
User user = new User(name, address);
user.setCollege(college);
user.setContact(contact);
Intent intent = new Intent(v.getContext(), MainActivity.class);
UserAdapter adapter = (UserAdapter)getIntent().getSerializableExtra("Adapter");
adapter.add(user);
finish();
startActivity(intent);
}
});
}
}
Logcat
02-20 18:35:37.264 12074-12074/com.example.deepanshu.customadapter3 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.deepanshu.customadapter3, PID: 12074
java.lang.RuntimeException: Parcelable encountered IOException reading a Serializable object (name =com.example.deepanshu.customadapter3.UserAdapter)
at android.os.Parcel.readSerializable(Parcel.java:2380)
at android.os.Parcel.readValue(Parcel.java:2203)
at android.os.Parcel.readArrayMapInternal(Parcel.java:2485)
at android.os.BaseBundle.unparcel(BaseBundle.java:221)
at android.os.BaseBundle.getSerializable(BaseBundle.java:988)
at android.os.Bundle.getSerializable(Bundle.java:845)
at android.content.Intent.getSerializableExtra(Intent.java:5256)
at com.example.deepanshu.customadapter3.AddUser$2.onClick(AddUser.java:47)
at android.view.View.performClick(View.java:4789)
at android.view.View$PerformClick.run(View.java:19881)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5292)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
Caused by: java.io.InvalidClassException: android.widget.ArrayAdapter; IllegalAccessException
at java.io.ObjectStreamClass.resolveConstructorClass(ObjectStreamClass.java:712)
at java.io.ObjectStreamClass.newInstance(ObjectStreamClass.java:673)
at java.io.ObjectInputStream.readNewObject(ObjectInputStream.java:1796)
at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:761)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1983)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1940)
at android.os.Parcel.readSerializable(Parcel.java:2378)
at android.os.Parcel.readValue(Parcel.java:2203)
at android.os.Parcel.readArrayMapInternal(Parcel.java:2485)
at android.os.BaseBundle.unparcel(BaseBundle.java:221)
at android.os.BaseBundle.getSerializable(BaseBundle.java:988)
at android.os.Bundle.getSerializable(Bundle.java:845)
at android.content.Intent.getSerializableExtra(Intent.java:5256)
at com.example.deepanshu.customadapter3.AddUser$2.onClick(AddUser.java:47)
at android.view.View.performClick(View.java:4789)
at android.view.View$PerformClick.run(View.java:19881)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5292)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
You cannot checkout code here
Also check issue in my Github profile too.
You can't pass your custom ArrayAdapter
or any other BaseAdapter/ArrayAdapter
object in intent.
As you know that to pass any object in intent it should be either Parcelable
or Serializable
.
As per documentation of Serializable interface https://developer.android.com/reference/java/io/Serializable.html
The serialization mechanism encodes an object's class name, the names of its non-transient fields (including non-public fields), and the values of all of those fields.
Here, when you implement Serializable
interface to your custom ArrayAdapter
class, it does not actually gets the ability of Serialization, because when you implement Serializable
interface, all fields takes part in the Serialization process.
But android.widget.ArrayAdapter class itself does not implement Serializable
interface.
So indirectly your custom ArrayAdapter
which inherited from android.widget.ArrayAdapter
, is also not Serializable
.
And considering your example, as mentioned in the comments, please call the intent with startActivityForResult()
to get the object to be added to your custom adapter.
Hope so you can understand this!
Read more about Serialization process!
这篇关于如何通过序列化在Intent之间传递自定义ArrayAdapter对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!