FragmentArgs 3.0


I finally found some time last weekend to work on FragmentArgsand to release a new major version 3.0. Here is an overview of new features and bug fixes.


The good news first: FragmentArgs 3.0 is completely backward compatible to all previous versions (down to 1.0). So basically you have to do nothing. However, I recommend to add the @FragmentWithArgsannotations to your Fragments that contain @Argannotations. Why? See What’s newsection and Bugfixessections.

What’s new? I have added @FragmentWithArgsand you should annotate all Fragment classes with this annotation. For backward compatibility reasons @FragmentWithArgsis not mandatory. However, I strongly recommend to use @FragmentWithArgsbecause in further versions of FragmentArgs this could become mandatory to support more features. @FragmentArgsInheritedis deprecated now. Use @FragmentWithArgs(inherited = true or false)instead. The generated Builder classes are now annotated with @NonNullfrom android support annotations library. This allows LINT to check your builders as well. You can disable that (see “Annotation Processor Options”below) Setter methods: You still have to annotate fields with @Arg(not the setter method itself). FragmentArgs detects the corresponding setter method automatically. This allows you to annotate private or protected fields with @Arg. However, I still recommend to use package (default) visibility for your argument fields: @FragmentWithArgspublic class MyFragment extends Fragment { @Arg int id; @Arg private String mTitle; // private fields requires a setter method // Setter method for private field. // The name must be the "set" prefix concatenated with field name public void setTitle(String title){ this.title = title; }}

FragmentArgs supports hungarian notation for detecting fields (even if your setter method would be called setMTitle()or setmTitle()). Nevertheless, I’m not a fan of the hungarian notation. We are not old school C++ developers living in the 1990’s. We should stop using the hungarian notation on android.

Kotlin support

The kotlin programming language is supported (use kaptinstead of apt). Since FragmentArgs 3.0 now supports setter methods kotlin backing fields are supported out of the box (because backing fields simply generate getter and setters).

@FragmentWithArgsclass KotlinFragment : Fragment() {@Arg var foo: String = "foo"@Arg(required = false) lateinit var bar: String // works also with lateinit for non primitivesoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)FragmentArgs.inject(this)}override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {val view = inflater.inflate(R.layout.fragment_kotlin, container, false)val tv = view.findViewById( as TextViewtv.text = "Foo = ${foo} , bar = ${bar}"return view;}} Annotation Processor Options

The FragmentArgs annotation processor supports some options for customization.

// Hugo Visser's APT pluginapt { arguments { fragmentArgsLib true fragmentArgsSupportAnnotations false fragmentArgsBuilderAnnotations "hugo.weaving.DebugLog" }}// Kotlin Annotation processorkapt { generateStubs = true arguments { arg("fragmentArgsLib", true) arg("fragmentArgsSupportAnnotations", false) arg("fragmentArgsBuilderAnnotations", "hugo.weaving.DebugLog") }} fragmentArgsLib: If you want to use FragmentArgs in android library projects. See github readmefor more informtation. fragmentArgsSupportAnnotations: As default the methods of the generated Builderare annotated with the annotations from support library like @NonNulletc. You can disable that feature by passing false. fragmentArgsBuilderAnnotations: You can add additional annotations to the generated Builderclasses. For example you can add @DebugLogannotation to the Builderclasses to use Jake Wharton’s Hugofor logging in debug builds. You have to pass a string of a full qualified annotation class name. You can supply multiple annotations by using a white space between each one. The sample show above would generate a builder class like this: @hugo.weaving.DebugLog public final class MyFragmentBuilder { ... } Bugfixes: #30: There was a bug when having a Fragment with optional arguments only ( @Arg(required = false)). This has been fixed. #32: It wasn’t possible to generate a builder for a Fragment without any @Argannotation. TL;DR: Use @FragmentWithArgsalso on Fragments with no arguments and the corresponding generated Builderto instantiate an instance. The long story:So why would should you use the FragmentArgs Builder if you don’t have arguments anyway? Imagine you have a Fragment called MyFragment. If it doesn’t have any argument then it’s safe to instantiate the Fragment directly via new MyFragment(). However, you should always use a FragmentArgs builder: Why? The reason is consistency and compile time verification. Imagine that one day in the future MyFragmentneeds an argument. So now you would have to scan all of your code for new MyFragment()calls and replace them with the new MyFragmentBuilder(argument).build(). What if you overlook one new MyFragment()statement. So your code will still compile, but will crash at runtime because the argument is missing. If you would have used new MyFragmentBuilder()instead even for fragments without arguments from the beginning you won’t run into this kind of issue because as soon as you add an argumentby using @Argto MyFragmentclass the Builder will throw an compile error because the argument is required as constructor parameter in new MyFragmentBuilder(argument).