質問がありますか? StackOverflow で質問してください。
問題が見つかりましたか?報告してください。
Android では、Parcelable はコンテキスト間で Java オブジェクトをシリアル化する優れた方法です。従来のシリアル化と比較して、Parcelables ではシリアル化と逆シリアル化の両方にかかる時間が 10 分の 1 程度短くなります。ただし、Parcelables には大きな欠陥があります。 Parcelable には大量の定型コードが含まれています。 Parcelable を実装するには、同じ順序で Parcel への読み取りと書き込みが行われるように、 writeToParcel()
とcreateFromParcel()
メソッドをミラーリングする必要があります。また、Android インフラストラクチャがシリアル化コードを利用できるようにするには、Parcelable でpublic static final Parcelable.Creator CREATOR
定義する必要があります。
Parceler は、Android Parcelable ボイラープレート ソース コードを生成するコード生成ライブラリです。 Parcelable インターフェイス、 writeToParcel()
またはcreateFromParcel()
またはpublic static final CREATOR
実装する必要はなくなりました。 POJO に@Parcel
のアノテーションを付けるだけで、残りの作業は Parceler が行います。 Parceler は Java JSR-269 アノテーション プロセッサを使用するため、Parcelable コードを生成するためにツールを手動で実行する必要はありません。 Java Bean にアノテーションを付けてコンパイルするだけで完了です。デフォルトでは、Paceler はインスタンスのフィールドを直接シリアル化します。
@ Parcel
public class Example {
String name ;
int age ;
public Example () {}
public Example ( int age , String name ) {
this . age = age ;
this . name = name ;
}
public String getName () { return name ; }
public int getAge () { return age ; }
}
デフォルトのフィールドシリアル化戦略を使用する場合は、リフレクションによるパフォーマンスの低下が生じるため、プライベート フィールドを使用しないように注意してください。
生成されたコードを使用するには、生成されたクラスを直接参照するか、 Parcels
ユーティリティ クラスを介して参照できます。
Parcelable wrapped = Parcels . wrap ( new Example ( "Andy" , 42 ));
@Parcel
逆参照するには、 Parcels.unwrap()
メソッドを呼び出すだけです。
Example example = Parcels . unwrap ( wrapped );
example . getName (); // Andy
example . getAge (); // 42
もちろん、ラップされたParcelable
Android バンドルに追加して、アクティビティからアクティビティに転送することもできます。
Bundle bundle = new Bundle ();
bundle . putParcelable ( "example" , Parcels . wrap ( example ));
そして、 onCreate()
メソッドで逆参照されます。
Example example = Parcels . unwrap ( getIntent (). getParcelableExtra ( "example" ));
このラッピングとラッピング解除の手法は、Intent Factory パターンとうまく連携します。さらに、Paceler は次のライブラリでもサポートされています。
Transfuse - @Parcel
アノテーション付き Bean を@Extra
インジェクションで使用できるようにします。
FragmentArgs - ParcelerArgsBundler
アダプターを使用して、 @Parcel
アノテーション付き Bean をフラグメント パラメーターでラップおよびラップ解除します。
Dart - @Parcel
アノテーション付き Bean を自動検出し、 @InjectExtra
使用するときにそれらを自動的にアンラップします。
AndroidAnnotations - @Parcel
アノテーション付き Bean を自動検出し、 @Extra
、 @FragmentArg
、 @InstanceState
およびその他のBundle
関連アノテーションを使用するときにそれらを自動的にラップ/ラップ解除します。
ActivityStarter - アクティビティ、フラグメント、サービスなどへの引数として Parceler オブジェクトをネイティブにサポートします。
Remoter - @Remoter インターフェイスの引数として Parceler オブジェクトをネイティブにサポートします。
@Parcel
クラスの属性として使用できるのは、選択された数のタイプのみです。次のリストには、マップされたタイプが含まれています。
byte
double
float
int
long
char
boolean
String
IBinder
Bundle
マップされたタイプのSparseArray
*
SparseBooleanArray
ObservableField
マップされたタイプのList
、 ArrayList
およびLinkedList
*
マップされたタイプのいずれかのMap
、 HashMap
、 LinkedHashMap
、 SortedMap
、およびTreeMap
*
Set
、 HashSet
、 SortedSet
、 TreeSet
、 LinkedHashSet
のいずれかのマップされたタイプ*
Parcelable
Serializable
マップされた型の配列
@Parcel
アノテーションが付けられたその他のクラス
*汎用パラメータがマップされていない場合、Parcel はエラーになります。
Parceler は、上記のタイプのいずれも直接サポートします。これは、 @Parcel
の注釈が付けられたクラスのコレクションを扱う場合に特に便利です。
Parcelable listParcelable = Parcels . wrap ( new ArrayList < Example >());
Parcelable mapParcelable = Parcels . wrap ( new HashMap < String , Example >());
Parceler は継承階層をアンラップしないため、多態性フィールドは基本クラスのインスタンスとしてアンラップされることに注意してください。これは、Paceler がデータのすべての部分に対して.getClass()
をチェックするのではなく、パフォーマンスを選択するためです。
@ Parcel
public class Example {
public Parent p ;
@ ParcelConstructor Example ( Parent p ) { this . p = p ; }
}
@ Parcel public class Parent {}
@ Parcel public class Child extends Parent {}
Example example = new Example ( new Child ());
System . out . println ( "%b" , example . p instanceof Child ); // true
example = Parcels . unwrap ( Parcels . wrap ( example ));
System . out . println ( "%b" , example . p instanceof Child ); // false
多態性フィールドの操作例については、「カスタム シリアル化」セクションを参照してください。
Parceler では、上記のフィールドベースのシリアル化に加えて、オブジェクトをシリアル化および逆シリアル化する方法についていくつかの選択肢が提供されます。
Parceler は、ゲッター メソッドとセッター メソッド、および空ではないコンストラクターを使用してシリアル化するように構成できます。さらに、 @ParcelProperty
アノテーションを使用して、フィールド、メソッド、およびコンストラクター パラメーターを関連付けることができます。これにより、不変性や従来のゲッター/セッター Bean など、多くの Bean 戦略がサポートされます。
デフォルトのメソッドのシリアル化を構成するには、 @Parcel
アノテーションをSerialization.BEAN
で構成するだけです。
@ Parcel ( Serialization . BEAN )
public class Example {
private String name ;
private int age ;
private boolean enabled ;
public String getName () { return name ; }
public void setName ( String name ) { this . name = name ; }
public int getAge () { return age ; }
public void setAge ( int age ) { this . age = age ; }
public boolean isEnabled () { return enabled ; }
public void setEnabled ( boolean enabled ) { this . enabled = enabled ; }
}
シリアル化でコンストラクターを使用するには、目的のコンストラクターに@ParcelConstructor
アノテーションを付けます。
@ Parcel ( Serialization . BEAN )
public class Example {
private final String name ;
private final int age ;
private boolean enabled ;
@ ParcelConstructor
public Example ( int age , String name , boolean enabled ) {
this . age = age ;
this . name = name ;
this . enabled = enabled ;
}
public String getName () { return name ; }
public int getAge () { return age ; }
public boolean isEnabled () { return enabled ; }
}
空のコンストラクターが存在する場合、別のコンストラクターに注釈が付けられていない限り、Parceler はそのコンストラクターを使用します。
@ParcelProperty
アノテーションを使用して、シリアル化手法を組み合わせて使用することもできます。次の例では、 firstName
とlastName
コンストラクターを使用して Bean に書き込まれますが、 firstName
はフィールドを使用して Bean から読み取られ、 lastName
getLastName()
メソッドを使用して読み取られます。パラメータfirstName
とlastName
パラメータ名"first"
と"last"
によってそれぞれ調整されます。
@ Parcel
public class Example {
@ ParcelProperty ( "first" )
String firstName ;
String lastName ;
@ ParcelConstructor
public Example ( @ ParcelProperty ( "first" ) String firstName , @ ParcelProperty ( "last" ) String lastName ){
this . firstName = firstName ;
this . lastName = lastName ;
}
public String getFirstName () { return firstName ; }
@ ParcelProperty ( "last" )
public String getLastName () { return lastName ; }
}
Parceler でシリアル化する必要のない属性の場合、属性フィールド、ゲッター、またはセッターに@Transient
の注釈が付けられる場合があります。
Parceler は、POJO を中心としたさまざまなスタイルをサポートしています。これにより、 @Parcel
アノテーション付きクラスを、次のような他の POJO ベースのライブラリで使用できるようになります。
GSON
レルム
戸棚
単純な XML
DBフロー
コンストラクターを直接使用する代わりに、Parceler は、アノテーション付きの Static Factory を使用して、指定されたクラスのインスタンスを構築することをサポートしています。このスタイルは、不変 Bean を生成するための Google の AutoValue アノテーション プロセッサ/コード生成ライブラリをサポートします。 Parceler は@ParcelFactory
アノテーションを介して AutoValue とインターフェースし、静的ファクトリ メソッドをアノテーション付きの@Parcel
シリアル化にマップします。
@ AutoValue
@ Parcel
public abstract class AutoValueParcel {
@ ParcelProperty ( "value" ) public abstract String value ();
@ ParcelFactory
public static AutoValueParcel create ( String value ) {
return new AutoValue_AutoValueParcel ( value );
}
}
AutoValue は、アノテーションが付けられた@Parcel
とは異なるクラスを生成するため、Parceler がどのクラスをParcels
ユーティリティ クラスで構築するかを指定する必要があります。
Parcelable wrappedAutoValue = Parcels . wrap ( AutoValueParcel . class , AutoValueParcel . create ( "example" ));
そして逆シリアル化するには:
AutoValueParcel autoValueParcel = Parcels . unwrap ( wrappedAutoValue );
@Parcel
は、特別なシリアル化が必要な場合に備えて手動シリアライザーParcelConverter
含めるオプションのパラメーターが含まれています。これにより、Parcelable クラスを手動で実装するよりもクリーンなオプションを使用できるようになります。
次のコードはParcelConverter
使用して、逆シリアル化中に継承階層のラップを解除する方法を示しています。
@ Parcel
public class Item {
@ ParcelPropertyConverter ( ItemListParcelConverter . class )
public List < Item > itemList ;
}
@ Parcel public class SubItem1 extends Item {}
@ Parcel public class SubItem2 extends Item {}
public class ItemListParcelConverter implements ParcelConverter < List < Item >> {
@ Override
public void toParcel ( List < Item > input , Parcel parcel ) {
if ( input == null ) {
parcel . writeInt (- 1 );
}
else {
parcel . writeInt ( input . size ());
for ( Item item : input ) {
parcel . writeParcelable ( Parcels . wrap ( item ), 0 );
}
}
}
@ Override
public List < Item > fromParcel ( Parcel parcel ) {
int size = parcel . readInt ();
if ( size < 0 ) return null ;
List < Item > items = new ArrayList < Item >();
for ( int i = 0 ; i < size ; ++ i ) {
items . add (( Item ) Parcels . unwrap ( parcel . readParcelable ( Item . class . getClassLoader ())));
}
return items ;
}
}
Parceler には、API のorg.parceler.converter
パッケージの下にあるコレクション変換を容易にする一連の基本クラスもパッケージ化されています。これらの基本クラスは、null チェックや収集の反復など、コレクションを処理するさまざまな困難または冗長なジョブを処理します。たとえば、上記のParcelConverter
、「ArrayListParcelConverter」を使用して作成できます。
public class ItemListParcelConverter extends ArrayListParcelConverter < Item > {
@ Override
public void itemToParcel ( Item item , Parcel parcel ) {
parcel . writeParcelable ( Parcels . wrap ( item ), 0 );
}
@ Override
public Item itemFromParcel ( Parcel parcel ) {
return Parcels . unwrap ( parcel . readParcelable ( Item . class . getClassLoader ()));
}
}
対応する Java ソースが利用できないクラスの場合は、 @ParcelClass
アノテーションを使用してクラスを Parcel として含めることができます。このアノテーションは、コンパイルされたソース内の都合の良い場所で宣言できます。たとえば、Android アプリケーションと一緒に@ParcelClass
を含めることができます。
@ ParcelClass ( LibraryParcel . class )
public class AndroidApplication extends Application {
//...
}
@ParcelClasses
アノテーションを使用して、複数の@ParcelClass
アノテーションを宣言できます。
さらに、 @ParcelClass
によって参照されるクラスは、 @Parcel
アノテーションを使用して構成できます。これにより、分析するシリアル化手法やクラスなど、 @Parcel
アノテーションで使用可能な任意のパラメーターを使用してシリアル化設定を行うことができます。
便利な手法の 1 つは、型のグローバル カスタム コンバーターを定義できることです。
@ ParcelClass (
value = LibraryParcel . class ,
annotation = @ Parcel ( converter = LibraryParcelConverter . class ))
class SomeClass {}
これにより、直接変更できないクラスをきめ細かく制御できるようになります。
一部のライブラリでは、基本クラスを拡張するために Bean を必要とするのが一般的です。これは最適なケースではありませんが、Parceler は、analyze パラメーターを介して継承階層内のどのクラスを分析するかを構成できるようにすることで、このプラクティスをサポートします。
@ Parcel ( analyze = { One . class , Three . class })
class One extends Two {}
class Two extends Three {}
class Three extends BaseClass {}
この例では、 One
クラスとThree
クラスのフィールドのみがシリアル化され、 BaseClass
とTwo
クラスのパラメーターの両方が回避されます。
Parcels ユーティリティ クラスは、クラスごとにラップするために指定されたクラスを検索します。パフォーマンス上の理由から、これはスーパークラスと基本クラスの両方の継承を無視します。この問題には 2 つの解決策があります。まず、 implementations
パラメータを介して、特定の型に関連付ける追加の型を指定できます。
class ExampleProxy extends Example {}
@ Parcel ( implementations = { ExampleProxy . class })
class Example {}
ExampleProxy proxy = new ExampleProxy ();
Parcels . wrap ( proxy ); // ExampleProxy will be serialized as a Example
次に、 Parcels.wrap()
メソッドを使用するときにクラス タイプを指定することもできます。
ExampleProxy proxy = new ExampleProxy ();
Parcels . wrap ( Example . class , proxy );
Proguard を構成するには、proguard 構成ファイルに次の行を追加します。これらは、 Parcels
ユーティリティ クラスとParcelable
CREATOR
インスタンスに関連するファイルを保持します。
# パーセラーライブラリ -keep インターフェイス org.parceler.Parcel -keep @org.parceler.Parcel クラス * { *; } -keep クラス **$$Parcelable { *; }
Parceler を Maven 依存関係としてダウンロードできます。
< dependency >
< groupId >org.parceler</ groupId >
< artifactId >parceler</ artifactId >
< version >1.1.12</ version >
< scope >provided</ scope >
</ dependency >
< dependency >
< groupId >org.parceler</ groupId >
< artifactId >parceler-api</ artifactId >
< version >1.1.12</ version >
</ dependency >
またはグラドル:
implementation ' org.parceler:parceler-api:1.1.12 '
annotationProcessor ' org.parceler:parceler:1.1.12 '
または Maven Central から。
著作権 2011-2015 ジョン エリクセン Apache License バージョン 2.0 (「ライセンス」) に基づいてライセンスされています。 ライセンスに準拠する場合を除き、このファイルを使用することはできません。 ライセンスのコピーは次の場所で入手できます。 http://www.apache.org/licenses/LICENSE-2.0 適用される法律で義務付けられている場合または書面による同意がない限り、ソフトウェア ライセンスに基づいて配布される場合は、「現状のまま」で配布されます。 明示的か黙示的かを問わず、いかなる種類の保証や条件もありません。 特定の言語を管理する権限については、「ライセンス」を参照してください。 ライセンスに基づく制限。