如何在序列化

时间:2016-02-20 13:15:52

标签: java android listview android-intent serialization

背景
我刚开始使用Android,我已经了解了Intents和ListView。我正在创建一个简单的应用程序,用户输入一些信息,并将该信息添加到ListView中。为此,我在MainActivity类中创建了一个ListView。为名为User的对象创建了一个类,并创建了自定义ArrayAdapter UserAdapter.我的UserUserAdapter都实现了Serializable标记接口。现在,只要有人点击MainActivity类中的按钮添加数据,就会打开一个新的Intent并从该intent获取输入并返回MainActivity意图。我在意图之间传递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,我认为你不需要那个类实现,但如果你愿意,我可以在这里添加。

现在我的第二个Activiy课程 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) 

您无法结帐代码here

同时检查我的Github个人资料中的问题。

1 个答案:

答案 0 :(得分:2)

您无法在意图中传递自定义ArrayAdapter或任何其他BaseAdapter/ArrayAdapter对象。

如您所知,要在意图中传递任何对象,它应该是ParcelableSerializable

根据Serializable接口https://developer.android.com/reference/java/io/Serializable.html

的文档
  

序列化机制对对象的类名称进行编码   它的非瞬态字段(包括非公共字段)和   所有这些领域的价值。

这里,当您实现自定义Serializable类的ArrayAdapter接口时,它实际上不具备序列化功能,因为当您实现Serializable接口时,所有字段都参与序列化过程。

android.widget.ArrayAdapter类本身并未实现Serializable接口。 因此间接从ArrayAdapter继承的自定义android.widget.ArrayAdapter也不是Serializable

考虑到您的示例,如评论中所述,请使用startActivityForResult()调用intent以将对象添加到自定义适配器中。

希望你能理解这一点!

阅读有关序列化过程的更多信息!