Chapter 3 explores activities

  1. Use the Menu

    1. Create menu file (menu_activity.xml) in SRC /main/res/menu folder

      
                
      <menu xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:app="http://schemas.android.com/apk/res-auto">
          <item
              android:id="@+id/app_bar_search"
              android:icon="@drawable/ic_search_black_24dp"
              android:title="Search"
              app:showAsAction="ifRoom"
              app:actionViewClass="android.widget.SearchView" />
          <item
              android:id="@+id/add_item"
              android:title="Add" />
      </menu>
      Copy the code
    2. Override the onCreateOptionsMenu() method

      override fun onCreateOptionsMenu(menu: Menu?).: Boolean {
          menuInflater.inflate(R.menu.menu_activity, menu)
          return true
      }
      Copy the code
    3. Override the onOptionsItemSelected() method

      override fun onOptionsItemSelected(item: MenuItem): Boolean {
          Toast.makeText(this."$item.title was clicked", Toast.LENGTH_SHORT).show()
          return super.onOptionsItemSelected(item)
      }
      Copy the code
  2. Intent

    1. Explicit Intent

      startActivity(Intent(this, MenuActivity::class.java))
      Copy the code
    2. An implicit Intent

      1. action

        <activity android:name=".chapter3.MenuActivity">
            <intent-filter>
                <action android:name="com.youngly.firstlineofcode.ACTION_START"/>
            </intent-filter>
        </activity>
        Copy the code
        startActivity(Intent("com.youngly.firstlineofcode.ACTION_START"))
        Copy the code
      2. category

        <activity android:name=".chapter3.MenuActivity">
            <intent-filter>
                <action android:name="com.youngly.firstlineofcode.ACTION_START"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <! -- When adding a category, the default category needs to be added -->
                <category android:name="com.youngly.firstlineofcode.MENU_CATEGORY"/>
            </intent-filter>
        </activity>
        Copy the code
        val intent = Intent("com.youngly.firstlineofcode.ACTION_START")
        intent.addCategory("com.youngly.firstlineofcode.MENU_CATEGORY")
        startActivity(intent)
        Copy the code
      3. data

        val intent = Intent(Intent.ACTION_VIEW)
        intent.data = Uri.parse("https://www.baidu.com")
        startActivity(intent)
        Copy the code
        • Android: Scheme is used to specify the protocol part of the data, in this case the HTTPS part

        • Android :host is used to specify the host part of the data, in this example www.baidu.com

        • Android :port Specifies the port portion of the data, usually immediately after the hostname

        • Android :path is used to specify the part after the host name and port, such as the domain name in a web address

        • Android :mimeType is used to specify the type of data that can be processed, allowing the use of wildcards

          Expand deeklink
          <activity
              android:name=".chapter3.DeeplinkActivity"
              android:label="deeplinkActivity">
              <intent-filter>
                  <action android:name="android.intent.action.VIEW" />
          
                  <category android:name="android.intent.category.DEFAULT" />
                  <category android:name="android.intent.category.BROWSABLE" />
          
                  <data
                      android:host="link"
                      android:scheme="fl" />
              </intent-filter>
          </activity>
          Copy the code
          val intent = Intent(Intent.ACTION_VIEW)
          intent.data = Uri.parse("fl://link")
          startActivity(intent)
          Copy the code
    3. Return the data

      val intent = Intent(this, ReturnResultActivity::class.java)
      startActivityForResult(intent, 1)
      
      
      override fun onActivityResult(requestCode: Int, resultCode: Int.data: Intent?). {
          super.onActivityResult(requestCode, resultCode, data)
          val s = "requestCode = $requestCode, resultCode = $resultCode, data.string = ${ data? .getStringExtra("data_return")}"
          Toast.makeText(this, s, Toast.LENGTH_SHORT).show()
      }
      Copy the code
      override fun onBackPressed(a) {
          val intent = Intent()
          intent.putExtra("data_return"."hello")
          setResult(RESULT_OK, intent)
          super.onBackPressed()
      }
      Copy the code
  3. The life cycle

    1. State of the Activity

      1. Running state, top of stack
      2. Pause state, such as pop-up dialog
      3. Stopped, not at the top of the stack, and completely invisible
      4. Destroy state, removed from the stack
    2. The life cycle

      1. OnCreate (), the first creation call that does the initialization, such as loading the layout and binding events
      2. OnStart (), called when not visible
      3. OnResume (), at the top of the stack, is running.
      4. OnPause () is called when starting or resuming another Activity to release cpu-consuming resources and save critical data. Do not perform time-consuming operations that will affect the use of new top-stack activities
      5. OnStop (), called when completely invisible
      6. OnDestory (), called before it is destroyed
      7. OnRestart (), called before the stop state switches to the running state
  4. Boot mode

    When you press the multi-task key, you see tasks (stacks of tasks), and tasks seen in the multi-task are not necessarily alive.

    Different tasks can be stacked. Task stacking only applies to foreground tasks. Multiple tasks stacked by the foreground will be disassembled as soon as they enter the background.

    There are two ways for tasks to go from the foreground to the background:

    1. Press the home button to return to the desktop

    2. Press the Recent Task button to view the latest task

    Properties: android: allowTaskReparenting = “true”

    Properties: android: taskAffinity = “”

    By default, the Activity’s taskAffinity is taken from the Application’s taskAffinity, which is the package name by default. Each Task also has taskAffinity, which is taken from the Activity’s taskAffinity at the bottom of the stack.

    • By default, the Activity goes directly to the current Task
    • However, for an Activity with Android :launchMode=”singleTask”, the system first compares the taskAffinity between the Activity and the current Task
      • If they are the same, they are normally pushed
      • If not, the Activity will find the same Task as its taskAffinity and stack it. If it cannot find it, the system will create a new Task for it

    TaskAffinity and recent task list

    • The recent Task list lists existing tasks
      • Their taskAffinity is different
      • When multiple tasks have the same taskAffinity (launchMode=”singleInstance”), the most recent Task list will only display the most recently displayed Task.
    1. standard

      By default, every new Activity started is placed at the top of the stack. If you start the same Activity in different tasks, multiple activities will be created and placed in each Task. For example, a phone App provides a contact add interface. When an App adds a contact, it adds the new contact add interface to its stack.

    2. singleTop

      When a new page is launched, the Activity’s onNewIntent() method is called when the target Activity is at the top of the current stack, but no new instance is created.

    3. singleTask

      When an Activity starts with singleTask, it first checks the system to see if there is a task stack whose attribute value affinity is equal to its own attribute value taskAffinity. If such a task stack exists, it will be started in that stack, otherwise it will be started in a new stack. Therefore, if we want an Activity with a singleTask launch mode to be launched in the new task stack, we need to set a separate taskAffinity property value for it. If the Activity whose startup mode is set to singleTask is not started in a new task stack, it checks to see if an Activity instance already exists in the existing task stack. If so, it terminates all other activities on that Activity instance. The Activity instance ends up at the top of the task stack.

      For example, an email app provides an Activity to edit emails. If an app creates an Activity to edit emails, it will create a task and put the Activity into it. In this case, the page switching animation is an inter-application switching animation.

    4. singleInstance

      SingleInstance is globally stack unique, in contrast to singleTask.

      It is mostly open to external apps for shared use

  5. Kotlin classroom

    1. Standard functions

      1. with

        val with = with(StringBuilder()) {
            append("start eating fruit\n")
            for (s in listOf) {
                append("$s    ")
            }
            append("\nate all fruit")
          	/ / the return value
            toString()
        }
        Copy the code
      2. run

        val run = StringBuilder().run {
            append("start eating fruit\n")
            for (s in listOf) {
                append("$s    ")
            }
            append("\nate all fruit")
          	/ / the return value
            toString()
        }
        Copy the code
      3. apply

        val apply = StringBuilder().apply {
            append("start eating fruit\n")
            for (s in listOf) {
                append("$s    ")
            }
            append("\nate all fruit")
          	// No return value
        }
        Copy the code
    2. Defining static methods

      1. Singleton class

        object DisplayUtil {
            fun dp2Px(dp: Float) = TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP,
                dp,
                Resources.getSystem().getDisplayMetrics()
            )
        }
        Copy the code
      2. Associated class

        class SingleTopActivity : AppCompatActivity() {...companion object {
                fun actionStartSelf(context: Context) {
                    val intent = Intent(context, SingleTopActivity::class.java)
                    context.startActivity(intent)
                }
            }
        }
        Copy the code

        Solutions 1 and 2 only provide syntactic features to support writing something like static method calls. If you really need to define truly static methods, Kotlin offers two ways to do it: annotations and top-level methods

      3. annotations

        The @jVMStatic annotation can only be loaded on methods of a singleton class or associated class

        object DisplayUtil {
            @JvmStatic
            fun dp2Px(dp: Float) = TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP,
                dp,
                Resources.getSystem().getDisplayMetrics()
            )
        }
        Copy the code
      4. The top method

        Create the Kotlin file

        fun dp2Px(dp: Float) = TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP,
            dp,
            Resources.getSystem().getDisplayMetrics()
        )
        Copy the code