【问题标题】:How do I pass custom ArrayAdapter Object between Intents with serialization如何通过序列化在 Intent 之间传递自定义 ArrayAdapter 对象
【发布时间】:2016-06-02 02:48:01
【问题描述】:

背景
我刚开始使用 Android,我已经了解了 Intents 和 ListView。我正在创建一个简单的应用程序,用户在其中输入一些信息并将该信息添加到 ListView 中。为此,我在 MainActivity 类中创建了一个 ListView。为名为 User 的对象创建了一个类,并创建了 Custom ArrayAdapter UserAdapter. 我的 UserUserAdapter 都实现了 Serializable 标记接口。现在,每当有人单击 MainActivity 类中的按钮以添加数据时,都会打开一个新 Intent 并从该 Intent 中获取输入并返回到 MainActivity Intent。我在意图之间传递 UserAdapter 对象。

问题:
现在适配器对象显示的问题在下一个意图中不起作用。

代码:
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 类也实现了 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) 

您无法结帐代码here

还要检查我的 Github 个人资料中的问题。

【问题讨论】:

  • 如果您正在打开第二个活动以插入将在活动1中插入适配器的数据,然后启动第二个活动“forResults”并在列表中添加新项目
  • 是的,我可以使用“startActivityForResult()”或 Parcelable,但我想修复上面的代码。
  • 我宁愿建议您在加载 AddUser 意图时使用 startActivityForResult 方法。然后您将仅将新添加的用户对象传递给调用意图。
  • 为另一个活动发送适配器不正确。使用 startActivityForResult 获取您的值,然后调用 result 方法。
  • 所以我们不能发送适配器对象? PS:我有一个带有 startActivityForResult 的工作代码,但我仍然对使用上述代码的工作感兴趣

标签: java android listview android-intent serialization


【解决方案1】:

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

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

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

序列化机制对对象的类名进行编码,名称 其非瞬态字段(包括非公共字段),以及 所有这些字段的值。

这里,当你为你的自定义ArrayAdapter类实现Serializable接口时,它实际上并没有获得序列化的能力,因为当你实现Serializable接口时,所有的字段都参与了序列化过程。

但是android.widget.ArrayAdapter类本身并没有实现Serializable接口。 所以间接地你的自定义ArrayAdapter继承自android.widget.ArrayAdapter,也不是Serializable

考虑到您的示例,如 cmets 中所述,请使用 startActivityForResult() 调用意图以获取要添加到您的自定义适配器的对象。

希望你能理解这一点!

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

【讨论】:

    猜你喜欢
    • 2018-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-22
    • 2011-08-03
    • 1970-01-01
    相关资源
    最近更新 更多