InjectWithAnnotation - JumeiRdGroup/Parceler GitHub Wiki

使用注解做bundle数据注入

框架提供两个注解:@Arg与@Converter.

我们直接以下方为示例代码来做说明:

// 任意的实体类。也可以是抽象类
public class UserInfo {

	// 直接使用于成员变量之上。代表此成员变量数据可被注入
	@Arg 
	String username;
	
	// 指定此成员变量所使用的key
	@Arg(“rename”)
	int age;
	
	// 结合Converter注解做数据匹配兼容。
	@Converter(FastJsonConverter.class)
	@Arg
	Address address
	
	// some codes 
	...
}

在对成员变量使用了注解之后。我们即可对数据进行双向数据注入了(bundle <==> entity)

仍然以上方所定义的class为例

bundle与entity需要均不为null

  1. bundle ==> entity
UserInfo info = getUserInfo();
// 将bundle中的数据注入到info类中被Arg注解了的字段上去
Parceler.toEntity(info, bundle);

等价于:

Parceler.createFactory(bundle)
		.put("username", info.username)
		// 使用了@Arg("rename")做key重命名
		.put("rename", info.age)
		// 使用了Converter显示指定转换器
		.put("address", info.address, FastJsonConverter.class);
  1. entity ==> bundle
UserInfo info = getUserInfo();
// 将info中被Arg注解了的字段值注入到bundle容易中去
Parceler.toBundle(info, bundle);

等价于:

BundleFactory factory = Parceler.createFactory(bundle);
info.username = factory.get("username", String.class);
info.age      = factory.get("rename", int.class);
info.address  = factory.get("address", Address.class, FastJsonConverter.class);

对于等价用法不了解的。请先参考:使用BundleFactory做数据注入

使用场景示例

发起注入操作可放置于基类中进行使用。最常用的即是Activity中进行配置:

// 将注入器配置到基类中。一次配置,所有子类共同使用
public abstract class BaseActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 启动时从intent中读取数据并注入到当前类中。
        Parceler.toEntity(this,getIntent());
    }

    // ============可用以下方式方便的进行数据现场保护==========
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        // 将当前类中的使用注解的成员变量的值注入到outState中进行保存。
        Parceler.toBundle(this,outState);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        // 需要恢复现场时。将数据从saveInstanceState中读取并注入当前类中。恢复现场
        Parceler.toEntity(this,savedInstanceState);
    }
}

然后就可以愉快的在各种子类中方便的进行使用了:

public class UserActivity extends Activity {

	// 直接使用。
	@Arg
	User user;
	@Arg
	Address address;
	@Arg
	int age;
	
	...

}

使用BundleBuilder避免硬编码key值

正常情况下,对类使用了Arg注解后。进行存储的时候,都会需要代码中写死key值。这种硬编码的做法,也很容易引起各种维护性问题。所以Parceler针对此种情况。提供了BundleBuilder注解。扔以上方的 UserActivity为例。要传递对应数据给UserActivity。基本的做法是像下方这样:

Bundle bundle = Parceler.createFactory(new Bundle());
			.put("user", user)
			.put("address", address)
			.put("age", age)
			.getBundle();

如果不想使用key值硬编码。可以在类上添加BundleBuilder注解:

@BundleBuilder
public class UserActivity extends Activity {
	...
}

请注意: BundleBuilder可以使用在任意类之上。并不限于Activity

添加了BundleBuilder后。在编译器将会生成XXXBundleBuilder类提供使用,我们即可使用此类进行Bundle数据存储:

Bundle bundle = UserActivityBundleBuilder.create(bundle)		.setUser(user)
		.setAddress(user)
		.setAge(age)
		.getBundle();

这样就能避免硬编码问题了。然后对于Activity、Service、BroadcastReceiver使用BundleBuilder时。可选择使用IntentLauncher进行简易的组件启动操作,扔以UserActivity生成类为例:

// 创建Builder实例
IBundleBuilder builder = 
		UserActivityBundleBuilder.create(bundle)
						.setUser(user)
						.setAddress(user)
						.setAge(age);
						
// 使用IntentLauncher进行启动
IntentLauncher.create(builder)
		// startActivityForResult
		.setRequestCode(code)
		// 所有其他的额外数据。包括flat/action/category/data等
		.setExtra(intent)
		.start(context);