Home > Net >  supportActionBar is getSupportActionBar?
supportActionBar is getSupportActionBar?

Time:11-08

I'm currently learning Kotlin and I'm trying to understand something. The tutorial I'm following is making a toolbar. We made the toolbar in the layout xml file then used setSupportActionBar() to find it. I can see that setSupportActionBar() is part of the AppCompatActivity class.

We then use supportActionBar.setNavigationOnClickListener{}. What I'm confused about is where is this supportActionBar variable coming from? It's not defined in any of the code on the course. When I highlight it tells me it comes from androidx.appcompat.app.ActionBar but that it is actually "getSupportActionBar()". When I ctrl click the variable, it shows me getSupportActionBar() in AppCompatActivity.

But for the life of me I can't figure out where this "supportActionBar" object is coming from. I can't find it in the android docs or anywhere. I can see the ActionBar class has the getSupportActionBar() method and the setSupportActionBar is coming from AppCompatActivity. But where does this variable come from? How am I supposed to know if such things exist if they aren't in the docs?

Not sure if this makes any sense. Here is the code, please ignore the note ExerciseActivity.kt

package com.example.a7minutesworkout

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.a7minutesworkout.databinding.ActivityExerciseBinding
import com.example.a7minutesworkout.databinding.ActivityMainBinding

class ExerciseActivity : AppCompatActivity() {

private var binding : ActivityExerciseBinding? = null

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    binding = ActivityExerciseBinding.inflate(layoutInflater)

    setContentView(binding?.root)

    setSupportActionBar(binding?.toolbarExercise)

    if(supportActionBar != null){
        supportActionBar?.setDisplayHomeAsUpEnabled(true)
    }

    binding?.toolbarExercise?.setNavigationOnClickListener {
        onBackPressed()
    }
}}

the layout xml file, activity_exercise:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ExerciseActivity">

<androidx.appcompat.widget.Toolbar
    android:id="@ id/toolbarExercise"
    android:layout_width="match_parent"
    android:theme="@style/ToolbarTheme"
    android:layout_height="?android:attr/actionBarSize"
    android:background="@color/white"
    app:titleTextColor="@color/colorPrimary"/>

 </RelativeLayout>

I might be able to understand if i was having to catch the output of getSupportActionBar() in a variable something like:

var supportActionBar = getSupportActionBar()

But that isn't in the code on the course. This "supportActionBar" variable seems to just magically exist. I feel like I'm missing some key thing about kotlin. I have learned java before and I feel like I'm missing some big piece to the kotlin puzzle. I'm not even sure if "supportActionBar" is a variable? It just has the lower case camel case so I assume it is. Can anyone fill me in?

Thanks

CodePudding user response:

As mentioned in Calling Java from Kotlin,

Methods that follow the Java conventions for getters and setters (no-argument methods with names starting with get and single-argument methods with names starting with set) are represented as properties in Kotlin.

Which means that the Kotlin compiler will generate a synthetic supportActionBar property for AppCompatActivity if it notices that this type has getSupportActionBar() and setSupportActionBar() methods.

CodePudding user response:

Java has the concept of getters and setters to hide the internal workings of a class from an external caller. This is generally a good practice, but with the way Java implemented it, it creates lots of boilerplate code which takes up useless space on your screen. Kotlin hides this by replacing getSupportActionBar() and setSupportActionBar() with a variable called supportActionBar. Behind the scenes, it actually calls setSupportActionBar() when you do supportActionBar = something and getSupportActionBar() when you do val myVar = supportActionBar.

A very helpful thing to understand the inner workings of Kotlin is to convert your Kotlin code to Java. You can do that with "Tools" -> "Kotlin" -> "Show Kotlin Bytecode" -> "Decompile". For instance, if I do this in Kotlin:

class StackOverflowDemo {
    var test: String = ""
}

class CallingClass{
    fun myFunction() {
        val demo = StackOverflowDemo()
        val myVariable = demo.test
        demo.test = "Another string"
    }
}

it transpiles to this in Java (metadata and imports removed for conciseness):

public final class StackOverflowDemo {
   @NotNull
   private String test = "";

   @NotNull
   public final String getTest() {
      return this.test;
   }

   public final void setTest(@NotNull String var1) {
      Intrinsics.checkNotNullParameter(var1, "<set-?>");
      this.test = var1;
   }
}

public final class CallingClass {
   public final void myFunction() {
      StackOverflowDemo demo = new StackOverflowDemo();
      String myVariable = demo.getTest();
      demo.setTest("Another string");
   }
}

Here are the appropriate Kotlin docs if you want to learn more.

  • Related