Kotlin java converter and nullable method arguments

I had a case where the Java converter in Kotlin hardly knocked me down without marking the method arguments as nullable.

Example: tracking activity life cycle using registerActivityLifecycleCallbacks :

 registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) {} @Override public void onActivityStarted(Activity activity) {} @Override public void onActivityResumed(Activity activity) {} // ... other overriden methods }); 

Paste this code into Kotlin results:

 registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks { override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle) {} override fun onActivityStarted(activity: Activity) {} override fun onActivityResumed(activity: Activity) {} override fun onActivityPaused(activity: Activity) {} // ... other overriden methods (all with non-nullable parameters) }) 

The problem is that the savedInstanceState argument savedInstanceState is Bundle , where should it be the Bundle? because this value may be null .

In this case, we will get the following exception when an Activity is created without an instance state:

 java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter savedInstanceState 

Note that the reason for this may be the onActivityCreated documentation does not mention that the Bundle may be null , while the onCreate documentation allows you to explain why a simple onCreate conversion works as expected:

 // Java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } // Kotlin override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } 

My question is: how do I know which arguments should be nullified to prevent such problems? The @Nullable annotation does not help here.

+5
source share
1 answer

If annotations don't help, I don't think there is a way to find out if the argument is null or not.

As for your published code, I think I know what is going on:

onCreate IS activity is marked as @Nullable :

 @Override protected void onCreate(@Nullable Bundle savedInstanceState) { final AppCompatDelegate delegate = getDelegate(); delegate.installViewFactory(); delegate.onCreate(savedInstanceState); . . 

Although the methods of the ActivityLifecycleCallbacks interface are not : (See Application.java )

 public interface ActivityLifecycleCallbacks { void onActivityCreated(Activity activity, Bundle savedInstanceState); void onActivityStarted(Activity activity); void onActivityResumed(Activity activity); void onActivityPaused(Activity activity); void onActivityStopped(Activity activity); void onActivitySaveInstanceState(Activity activity, Bundle outState); void onActivityDestroyed(Activity activity); } 

Therefore, apparently, the Kotlin translator processes annotations, but uses Non-Null as the default value, which in my humble opinion is not usual, since it makes sense to consider non-annotated Nullable parameters. However, I can understand this solution in order to get developers to pay attention to the translated code and explicitly decide whether the parameter is Nullable or not.

By the way, remember that there are several annotations @NonNull and @Nullable (javax, android, jetbrains ...) I won’t be surprised if the translator Kotlin recognizes only some of them (but this is just an assumption)

Also, with regard to your code, Java Lint should have given you a warning about your overridden onCreate , stating that you are overriding a method with annotated parameters, and you did not annotate it.

+3
source

Source: https://habr.com/ru/post/1272474/


All Articles