Android experience

Initialize Widgets in Kotlin

This is how to initialize variables, outside of DataBinding. There’re 3 ways.

class MyClass : AppCompatActivity() {
	// worst. needs to be 'var', nullable and be initialized
	private var button: Button? = null
	
	// a bit better. stills need to be 'var' and later be initialized
	private lateinit var result: EditText
	
	// best. is 'val' a doesn't need to be initialized
	//	  	 it will be initialized when first used. it is thread-safe
	private val operation by lazy { findViewById<TextView>(R.id.operation) }
	
	override fun onCreate(...) {
		button = findViewById<Button>(R.id.button)
		result = findViewById<EditText>(R.id.result)
	}
}

Synthetic properties

From our class, when we know the activity that we’re gonna use, we type import kotlinx.android.synthetic.main.activity_main.*
This way we can use widgets just as any other properties without the need for findViewById().

Activities

An app is made up of activities, which can launch other activities to perform different tasks. These are normally launched when the user clicks a button or activates a menu option.

Android keeps track of which activities you’ve used, and when you tap the back button, it closes the current activity and displays the previous one on the screen.

Inflate a Layout

To inflate a layout just really means that Android takes our xml definition for the layout, then creates all the widgets that we’ve defined in it. It then positions it on screen, taking note of all the constraints, margins and other settings that we’ve defined.

Constraints

They fix widgets in place. Without them, the widget willa appear on the top left corner when you run the app.

The best way is to constraint top elements to the edges of the app and constraint other widgets relatively to other widgets. This way they form groups and the general app layout doesn’t change when the screen size does.

Types of widget constraining

Wrap Content Causes the widget to become as wide or high as it needs to be. No more, no less.
Fixed You set the dp manually.
Match Constraints Expands the widget, as much as needed, to match the constraints.

Baseline Constraints

It’s possible to set a constraint to the baseline of text, on the widgets that support this to another widget. It needs to be manually activated.

Chains

They serve on how to centre a group of widgets. They’re not always appropiate.

We constrain chains to guidelines. Guidelines don’t always show when created, but if you search for them at the component tree, they’re there. Guidelines have properties just as other widgets but they don’t have height or width. A vertical guideline has 0 width and the height from their parent.

You can use them to center elements. If you put a guideline just at the center of the screen, you can then attach elements to it and they’ll be centered at their half of the screen.

Bundle

Bundle is an object that can be used to pass data around, within the Android framework.

When onCreate(savedInstanceState: Bundle?) method starts, it’s given a bundle containing all the data needed to restore it to the state it was in, when it was destroyed. When Android destroys the activity as a result of rotating the device or for a number of other reasons, the InstanceState of the activity is automatically saved before the activity is detroyed.

All of that is taken care of by the activity or AppCompactActivity classes, so because our MainActivity extends AppCompatActivity, we get the advantage of that behaviour.

The contents of the EditText are saved for us, because the contents of any editable widget form part of the activities InstanceState. This only applies to editable word widgets.

Save App State

The methods we need to Override to store state are onSaveInstanceState() and onRestoreInstanceState().

State can be restored in either onCreate() or onRestoreInstanceState() but it’d be a better idea to use the former, to keep things easier to understand.

override fun onSaveInstanceState(outState: Bundle?) {
	super.onSaveInstanceState(outState)
	outState?.putString("MY_STRING", "oh no!")
}

override fun onRestoreInstanceState(savedInstanceState: Bundle) {
	super.onRestoreInstanceState(savedInstance)
	val state: String = savedInstanceState.getString("MY_STRING")
}

Resources folder

Resources in this folder cannot have capital letters in them.

This is because Windows doesn’t make a difference between capital and normal letters for images. So this.jpg and This.jpg would be the same picture.

Permissions

By default, an app has no permissions to anything at all. The first time we run an App, we have to give it the permissions it needs to run. After that first time, the App has to ask for permissions each time it’s run, but instead of the User, the Android system will answer with the granted permissions unless the user has revoked them.

Permissions are sepparated in normal vs dangerous permissions. For normal permissions, we just need to declare them at the manifest and Android will automatically given them to us. For dangerous permissions, we need the explicit confirmation from the user.

Reference(s)

https://developer.android.com/guide