First Line of Code 3rd Edition-3rd Chapter (Notes)

Keywords: Java Android Android Studio

Start with what you can see and explore Activity

1.Activity

Activity is a component that can contain an application user interface, mainly for interacting with users.
An application can contain zero or more activities. Although an application can have no activities, it is best to have them, since they are meant to interact with the user and the interaction requires them.

2. Create Activity

You can create a main Activity by default when you create a project
You can also right-click the package name to create an Activity

There are several options for creating an Activity
The first is the name of the Activity
The second is Generate Layout File, choosing whether to add a layout file automatically
The third is the name of the layout file xml, which only happens if the second option is chosen
The fourth is Launcher Activity, whether it is set as the primary activity or not, which is the first activity that the application starts
The fifth one is the package name, which is usually unchanged, because in which package name you created it, you usually created it there.
The sixth is to choose a programming language. There are two kinds, Java and Kotlin. Now we're going to learn the first line of code, so we'll use the Kotlin speaker.

3. Register Activity

Once an activity is created, MainActivity 2 is automatically registered in AndroidManifest, which is how you register an activity. If you choose Launcher Activity when you create an activity, MainActivity will be generated because the two tags inside are used to declare that the activity is the primary activity.

4. Use Toast and Menu in Activity

//Toast
override fun onCreate(savedInstanceState: Bundle?) {
	super.onCreate(savedInstanceState)
	setContentView(R.layout.activity_main)
	val button1 : Button = findViewById(R.id.button1)
	//The first parameter is context, the second parameter is pop-up content, and the third parameter is pop-up time, with LENGTH_SHORT and LENGTH_ Two options for LONG
	button.setOnclickListener {
		Toast.makeText(this, "You clicked Button 1", Toast.LENGTH_SHORT).show()
	}
}

//Create a menu folder under the res folder and an xml file in the menu folder

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/add_item"
        android:title="Add" />
    <item
        android:id="@+id/remove_item"
        android:title="Remove" />
</menu>

Kotlin Small Features

In Java, you set up a simple class that automatically generates Getter and Setter methods that access the fields within the class, such as:

public class Book{
	private int pages;
	public int getPages(){
		return pages;
	}
	public void setPages(int pages){
		this.pages = pages;
	}
}

But in Kotlin, there is a simpler way

val book = Book()
book.pages = 500 //Set pages for book to 500
val bookPages = book.pages //Number of pages to get book pages

So writing in Activity can be abbreviated

//Create talent menu bar
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
	//Here, menuInflater is a shorthand of the object obtained through getMenuInflater()
    menuInflater.inflate(R.menu.main_menu, menu)
    return true
}
//Menu Click Event Listening
override fun onOptionsItemSelected(item: MenuItem): Boolean {
     when(item.itemId){
         R.id.add_item -> Toast.makeText(this, "You Clicked Add", Toast.LENGTH_SHORT).show()
         R.id.remove_item -> Toast.makeText(this, "You Clicked Remove", Toast.LENGTH_SHORT).show()
     }
     return true
    }

5.Intent

Intent is used for interaction and communication, while Intent is used for jumping between activities in an Activity.
Intent is divided into Show Intent and Implicit Intent

5.1 Explicit Intent

The explicit meaning is to tell you exactly who I'm looking for.
Add a Button to the first Activity, set the Button's listening event, and trigger the following code to jump the Activity as soon as you press it

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        btn.setOnClickListener{
        	//The second activity, which indicates where I want to jump, has a very obvious purpose
            val intent = Intent(this, SecondActivity::class.java)
            startActivity(intent)
        }
    }
}

The big guys who take code seriously should know that there is one missing code in my code to initialize Button

val btn: Button = findViewById(R.id.btn1)

I actually added a plugin that Kotlin can automatically help us compile variables with the same name as the layout file
But he actually uses findViewById internally to call

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-android-extensions'
}


However, for now, this plug-in is no longer used by default because it has been abandoned by Google and now the recommended use is ViewBinding

5.2 Implicit Intent

It does not indicate who I want to start, but rather lets the system analyze which Activity I want to start by itself through a series of abstract information
SecondActivity has two tags set. Only tags and tags can respond at the same time can intent jump
One is the label, set to respond to com.example.appactivity.ACTION_START
Another is the tag, which contains additional information to more precisely indicate what the current Activity can respond to. There can be multiple tags in an Activity

<activity android:name=".SecondActivity">
      <intent-filter>
          <action android:name="com.example.appactivity.ACTION_START"/>
          <category android:name="android.intent.category.DEFAULT"/>
      </intent-filter>
  </activity>

It's working here, but don't you mean you have to have both tags corresponding? There's a default tag, android.intent.category.DEFAULT.

btn.setOnClickListener{
	val intent = Intent("com.example.appactivity.ACTION_START")
    startActivity(intent)
}

When we added the tag for category and ran it, we found that the error was reported because the system could not find an Activity whose attribute is com.example.appactivity.MY_CATEGORY

btn.setOnClickListener{
	val intent = Intent("com.example.appactivity.ACTION_START")
	intent.addCategory("com.example.appactivity.MY_CATEGORY")
    startActivity(intent)
}

We've added an entry to Second Activity's registration

<activity android:name=".SecondActivity">
      <intent-filter>
          <action android:name="com.example.appactivity.ACTION_START"/>
          <category android:name="android.intent.category.DEFAULT"/>
          <category android:name="com.example.appactivity.My_CATEGORY"/>
      </intent-filter>
  </activity>

5.3 More Implicit Intent s

Activity used to start other programs

val btn : Button = findViewById(R.id.btn)
btn.setOnClickListener{
	//Open Browser
    val intent = Intent(Intent.ACTION_VIEW)
    intent.data = Uri.parse("https://www.baidu.com")
    startActivity(intent)
    //Call
    val intent = Intent(Intent.ACTION_DIAL)
    intent.data = Uri.parse("tel:10086")
    startActivity(intent)
}

5.4 companion object

All methods in this keyword are similar to Java static methods and can be used directly through UIUitl.actionStart().

6.Activity Delivers Data

Activity passes data using Intent's accompanying data. First it builds Intent intent, then it passes data through intent.putExtra() method. The first parameter is data name, the second is data (key-value pair)

//FirstActivity
val btn : Button = findViewById(R.id.btn)
btn.setOnClickListener{
    val data = "Hello SecondActivity"
    val intent = Intent(this, SecondActivity::class.java)
    intent.putExtra("extra_data", data)
    startActivity(intent)
}
//In SecondActivity, data is typically retrieved in onCreate
//Only getStringExtra is used here, corresponding to other getIntExtra, etc., corresponding to the type of data that should be passed
val extraData = intent.getStringExtra("extra_data")

Return data to FirstActivity. That is, SecondActivity returns data to FirstActivity

//FirstActivity Jump
//This is similar to the above, except that startActivity() is used above, and startActivityForResult() is used here, which is just an Activity jump
val btn : Button = findViewById(R.id.btn)
btn.setOnClickListener{
    val data = "Hello SecondActivity"
    val intent = Intent(this, SecondActivity::class.java)
    intent.putExtra("extra_data", data)
    startActivityForResult(intent, 1)
}
//Operation of SecondActivity
btn.setOnClickListener{
    val data = "Hello FirstActivity"
    val intent = Intent()
    intent.putExtra("extra_data", data)
    setResult(2, intent) //Return results
    finish()//Log off the current page before returning to the previous page
}

//Processing of returned data
//Why there are requestCode and resultCode, because a page may have many different jumps, and a page may have many different returns, so that you can know exactly where you came from
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if(requestCode == 1){ //This is the result Code of the send jump
        if(resultCode == 2){ //This is the returned result Code
            //Processing logic, the third data, is the intent that comes with the second page jump, which may contain additional data
        }
    }
}

7.Activity

Status of 7.1 Activity

  • Running state, interactive with users, Activity that the system is least willing to recycle
  • Pause state, can be seen, but can not interact, for example, when a Dialog is popped on an Activity, the Activity is paused, you can see, you cannot interact, all your interactions will be on the Dialog, only when the memory pole is possible to recycle
  • Stop state, can't interact, can't see, Activity is not at the top of the stack, but will save various variables and states, memory is not enough, may be recycled
  • Destroy state, pushed from the task stack, the system will quickly recycle the Activity to ensure sufficient memory

7.2 Activity Life Cycle

  • onCreate(), which is called when the Activity is first created and is typically used to initialize operations
  • onStart(), called when Activity is not visible, the user is visible but not interactive
  • OnResume(). Called when the Activity is ready to interact with the user. Currently the Activity is at the top of the stack, so it can interact
  • onPause(), called when ready to call or reply to other activities, should release some resources and save some important data
  • The main difference between onStop(), which is called when the activity is completely invisible, and onPause(), is that if you call Activity of a dialog box, the method will not be called
  • onDestroy(), called after the Activity is destroyed money, becomes destroyed and waits to be recycled
  • onRestart(), called when changing from a stop state to a running state, is the restart of the stopped Activity

7.3 Activity Life Cycle Diagram

7.4 Life Cycle

Seven life cycle approaches, corresponding to three lifetimes
Full lifetime: onCreate() and onDestroy(), created to destroy
Visible Lifetime: onStart() and onStop(), the cycle, visible but not necessarily interactive
Foreground lifetime: onResume() and onPause(), which are at the top of the stack and are visible for interaction

7.5 Activity Recycled Issues

In the above life cycle, the Activity may be recycled when it stops. I'm sure you have the same thing: open a page of an App, cut it to the background, and don't delete it, but the next time you come in, the page will restart, because the page is recycled and when you click it again, it will restart the Activity. There's a problem with the data here
So Activity provides an onSaveInstanceState() to hold the data
This method takes a Bundle-type parameter and stores the data

//This method can save parameters
override fun onSaveInstanceState(outState: Bundle, outPersistentState: PersistableBundle) {
    super.onSaveInstanceState(outState, outPersistentState)
    val tempData = "Something you just type"
    outState.putString("data_key", tempData)
}
//The onCreate method passes in saveInstanceState
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    //Here you can tell if there is data, because there is no data when you first enter the activity, but Activity restarted after you saved the data has data
    if(savedInstanceState != null){
        val tempData = savedInstanceState.getString("data_key")
    }
}

8. Activity Startup Mode

Activity starts in four modes

8.1 standard

Default startup mode, as soon as an activity is created, a new activity is added to the top of the stack. Whether or not the activity has created an instance before

FirstActivity starts a Second Activity, SecondActivity starts a FirstActivity, FirstActivity starts a FirstActivity
Stack situation: FirstActivity - FirstActivity - SecondActivity - FirstActivity (from high to low)

//Without any modification, the default is fine
val btn : Button = findViewById(R.id.btn)
btn.setOnClickListener {
    val intent = Intent(this, MainActivity::class.java)
    startActivity(intent)
}

8.2 singleTop

Stack top reuse mode, as long as a new activity instance is created, but the activity instance at the top of the stack is the activity of that class, the activity at the top of the stack will be reused

FirstActivity starts a Second Activity, SecondActivity starts a FirstActivity, FirstActivity starts a FirstActivity
Stack situation: FirstActivity - SecondActivity - FirstActivity (from high to low)

<activity android:name=".MainActivity"
    android:launchMode="singleTop"> 
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

8.3 singleTask

In-stack reuse mode, as long as the created Activity instance exists in the stack, then the instance is set to the top, and all the above pop-ups

FirstActivity starts a SecondActivity, SecondActivity starts a ThirdActivity, and ThirdActivity starts a SecondActivity
Stack case: SecondActivity - FirstActivity (from top to bottom)

<activity android:name=".MainActivity"
    android:launchMode="singleTask"> 
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

8.4 singleInstance

Singleton mode, obviously, uses a stack for a single Activity, which is the only Activity

<activity android:name=".MainActivity"
    android:launchMode="singleInstance"> 
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

9.Kotlin Classroom

9.1 with function

The with() function makes the code simpler when using multiple methods on the same object in a row
The with() function takes two arguments, one for any type of object and the second for a Lambda expression, which provides the context of the first argument object and the last row returned as a return value

val list = listOf("Apple", "Apple", "Apple", "Apple", "Apple")
val builder = StringBuilder()
builder.append("Start eating fruits.\n")
for(fruit in list){
    builder.append(fruit).append("\n")
}
builder.append("Ate all fruits.")
val result = builder.toString()
println(result)
//After brief with
//StringBuilder() takes a StringBuilder object, passes in a Lambda expression, and returns the object's toString method
val list = listOf("Apple", "Apple", "Apple", "Apple", "Apple")
val result = with(StringBuilder()){
    append("Start eating fruits.\n")
    for(fruit in list){
        append(fruit).append("\n")
    }
    append("Ate all fruits.")
    toString()
}
println(result)

9.2run function

Run is similar to with, but the difference is that run is called through an object with only one parameter: a Lambda expression whose context is the object

val list = listOf("Apple", "Apple", "Apple", "Apple", "Apple")
val result = StringBuilder().run {
    append("Start eating fruits.\n")
    for(fruit in list){
        append(fruit).append("\n")
    }
    append("Ate all fruits.")
    toString()
}
println(result)

9.3 apply function

Apply and run would also like to call through objects, accept only one Lambda object, and provide the object as context in the Lambda expression, but apply does not return a value, but automatically returns the object itself

val list = listOf("Apple", "Apple", "Apple", "Apple", "Apple")
val result = StringBuilder().apply {
    append("Start eating fruits.\n")
    for(fruit in list){
        append(fruit).append("\n")
    }
    append("Ate all fruits.")
}
println(result.toString())

9.4 Static Method

In Java, a static method can be declared in a method by static

//Static method
public class Util{
	public static void doSomething(){
		System.out.println("Hee-hee")
	}
} 
//Usage method
Util.doSomething()

In Kotlin, the concept of static methods is weakened because there is a better way to use them in Kotlin, which is to create a single class.

object Util{
	fun doSomething(){
		println("Hee-hee")
	}
}
//Method of Use
Util.doSomething
//After using object to make a class a singleton class, all methods become the use of class static methods
//The keyword companion object has been around for so long that the only method in this code snippet for this class is the class static method
class Util{
	fun doSomething(){
		println("Hee-hee")
	}
	companion object{
		fun doAction(){
			println("Ha ha ha")
		}
	}
}
//Usage:
doSomething()Method must create an instance of this class to use
doAction()Methods can be invoked using class static methods Util.doAction()

The companion object keyword actually creates an accompanying class inside the class, and the doAction() method defines the instance method inside the accompanying class, while Kotlin guarantees that the class has only one accompanying class object, so the call to the Util.doAction() method is actually the call to the doAction() method of the accompanying class.

True static method creation: annotations and top-level methods
Notes:
If a method in a singleton class or companion object is annotated with @JvmStatic, the method is compiled into a static method. Note: If you add comments to other common methods, you will get an error

class Util{
	fun doSomething(){
		println("Hee-hee")
	}
	companion object{
		@JvmStatic
		fun doAction(){
			println("Ha ha ha")
		}
	}
}

Top-level method
Create a Kotlin file, define a method directly inside, without creating a class, which is the top-level method

//Create a Test.kt file with only the package name + three lines below
package com.example.text
fun doAction(){
	println("Ha ha ha")
}

doAction() can then be used directly anywhere without any modification

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    doAction()
}

Kotlin automatically compiles the Test.kt file into a Java class for TestKt, so it can also be used in Java:

public void test(){
	TestKt.doAction()
}

Best practices for 9.5 intent

If you want to jump to SecondActivity, this is usually the call, so it's OK, but it's recommended that you write on top of the SecondActivity as a class static method and use the upper apply function at the same time:

//Original:
 val intent = Intent(this, MainActivity::class.java)
 intent.putExtra("data1", "text")
 intent.putExtra("data2", 10086)
 startActivity(intent)
 //Updated, straightforward
 class SecondActivity: AppCompatActivity() {
	companion object{
		val intent = Intent(context, SecondActivity::class.java).apply{
			putExtra("data1", "text")
			putExtra("data2", 10086)
		}
		context.startActivity(intent)
	}
}

Posted by lostincoding on Thu, 25 Nov 2021 09:52:58 -0800