54

カスタム クラスを指定して、パーセルに aorg.example.app.MyClass implements Parcelableを書き込みたいと思います。List<MyClass>私はマーシャリングを行いました

 List<MyClass> myclassList = ...
 parcel.writeList(myclassList);

クラスを非整列化しようとするたびに

 List<MyClass> myclassList = new ArrayList<MyClass>();
 parcel.readList(myclassList, null);

例外があり"BadParcelableException: ClassNotFoundException when unmarshalling org.example.app.MyClass"ます。

ここで何が問題なのですか?クラスが見つからないのはなぜですか?

4

4 に答える 4

110

nullClassLoader 引数として指定するときに使用されるフレームワーク クラス ローダーを使用して、カスタム クラス (つまり、Android フレームワークではなくアプリケーションによって提供されるクラス) をアンマーシャリングしないでください。アプリケーション クラス ローダーを使用します。

parcel.readList(myclassList, getClass().getClassLoader());

Parcel.read*()メソッドが ClassLoader を引数として持ち (例: Parcel.readList(List outVal, ClassLoader loader))、 からアプリケーション クラスを読み取りたい場合は常に、Parcelで取得できるアプリケーション クラス ローダーを使用しますgetClass().getClassLoader()

背景: Android には 2 つのクラス ローダーが付属しています。システム クラス ローダーは、アプリケーションによって提供されるシステム クラスを除くすべてのシステム クラスをロードできます。アプリケーションクラスローダーは、システムクラスローダーを親として設定しているため、すべてのクラスをロードできます。クラス ローダーとして null を指定すると、フレームワーク クラス ローダーが使用され、 ClassNotFoundExceptionが発生します。Parcel.readParcelableCreator()

私を正しい道に導くヒントを提供してくれた alexanderblom に感謝します。

于 2013-08-08T12:38:42.173 に答える
19

これのより正しい形式は次のようになると思います。

List<MyClass> myclassList = new ArrayList<MyClass>();
parcel.readList(myclassList, MyClass.class.getClassLoader());

ここでは、List のジェネリック型に対してクラス ローダーを明示的に使用しているためです。

于 2014-01-29T07:22:02.063 に答える
7

私は同じ問題に直面しており、parcleable の代わりに bundle を使用しました

intent.setExtrasClassLoader(getClassLoader());
/* Send optional extras */
Bundle bundle = new Bundle();
bundle.putParcelable("object", mObject);
bundle.putString("stringVal", stringVal);

intent.putExtra("bundle",bundle);

そして、インテント クラスでは、これを使用して値を取得しました。

Bundle oldBundle = intent.getBundleExtra("bundle");
ResultReceiver receiver = oldBundle.getParcelable("object");
String stringVal = oldBundle.getString("stringVal");
intent.setExtrasClassLoader(getClassLoader());

一部の人にとって役立つことを願っています。

于 2015-09-12T13:31:14.310 に答える