简体   繁体   中英

Is there way to teach java-> kotlin converter in Android Studio to not use `as` operator when converting findViewById?

For example

((MyView)view.findViewById(R.id.my_view)).doSomething()

it converts into

(view.findViewById(R.id.my_view) as MyView).doSomething()

While I want it to be

view.findViewById<MyView>(R.id.my_view).doSomething()

Java to Kotlin converter works correctly, it produces equivalent code. Your Java code contains explicit casts, Kotlin code will include them too.

If you want the described behavior, first move to the Android 9 generic syntax of findViewById .

Then this Java code

// Old
final TextView view0 = (TextView)activity.findViewById(id);
// New
final View     view1 = activity.findViewById(id);
final TextView view2 = activity.findViewById(id);
// Not useful
final View     view3 = activity.<TextView>findViewById(id);

will convert to this Kotlin code

val view0 = activity.findViewById<View>(id) as TextView
val view1 = activity.findViewById<View>(id)
val view2 = activity.findViewById<TextView>(id)
val view3 = activity.findViewById<TextView>(id)

You can turn on the warning for code like this.

Go to (Settings -> Editor -> Inspections -> Kotlin Android -> Cast can be converted to findViewById with type parameter) and switch severity to warning.

I don't think that conventer itself can be taught that this specific cast should be converted to something other. And in fact, I would say that it's expected behavior.

Note, that above Android SDK 28 you don't need that cast even in java:

public void hideChildTextView(View parent, @IdRes int id) {
    TextView view = parent.findViewById(id);
    view.setVisibility(View.GONE);
}

That code would be translated to:

fun hideChildTextView(parent: View, @IdRes id: Int) {
    val view = parent.findViewById<TextView>(id)
    view.visibility = View.GONE
}

It's because the type can be obtained from filed type and there is no cast needed (or it's actually casted by library).

So, let's check other code in SDK below 28:

public void hideChildTextView2(View parent, @IdRes int id) {
    TextView view = (TextView) parent.findViewById(id);
    view.setVisibility(View.GONE);
}

This would be converted to:

fun hideChildTextView2(parent: View, @IdRes id: Int) {
    val view = parent.findViewById(id) as TextView
    view.visibility = View.GONE
}

So, why is that? method findViewById below android 28 returns just View (so we need to cast it to proper type), but above returns <T extends View> , so compiler is able to make autocast.

So, what I would suggest? Update your compile/target SDK to 28+, clean the code in Java and then it would be working as you want. ;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM