如何通过序列化在Intent之间传递自定义ArrayAdapter对象 [英] How do I pass custom ArrayAdapter Object between Intents with serialization

查看:73
本文介绍了如何通过序列化在Intent之间传递自定义ArrayAdapter对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景:
我只是从Android入手,我已经了解了Intent和ListView.我正在创建一个简单的应用程序,用户在其中输入一些信息,并将该信息添加到ListView中.为此,我在MainActivity类中创建了一个ListView.为名为User的对象创建了一个类,并创建了自定义ArrayAdapter UserAdapter..我的已分类UserUserAdapter都实现了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对象.

您知道要按意图传递任何对象,它应该是ParcelableSerializable.

根据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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆