第一行代码Android个人笔记(一)——activity的基本用法

本节内容对应《第一行代码 第三版》:第三章

一、在AndroidManifest中注册

Manifest简介

如果我们创建了一个空的项目(no activity),自己新建了一个FirstActivity,此时需要在Manifest中手动注册。
幸运的是,AS已经为我们写好了以下代码

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.lrgy.activitytest">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".FirstActivity">
        </activity>
    </application>

</manifest>

其中,com.lrgy.activitytest表示应用整体的包名,android:name=".FirstActivity"表示这个application具体注册了com.lrgy.activitytest.FirstActivity这个Activity。
我们需要指定程序运行时首先启动哪个Activity,即在<activity>标签中添加<intent-filter>标签

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

这两个标签指明了应用启动时首先启动该Activity

<intent-filter>的用处

另外,<intent-filter>这个标签还有额外的作用,即在里面添加<action><category><data>标签
· intent介绍见:Intent 和 Intent 过滤器

  • 指定该Activity可以响应com.lrgy.activitytest.ACTION_START这个动作,这个动作名可以自己写,只需要和隐式Intent中val intent = Intent("com.lrgy.activitytest.ACTION_START")传入的参数相同即可
<action android:name="com.lrgy.activitytest.ACTION_START" />
  • 指定详细信息,android.intent.category.DEFAULT表示不设置category(即默认category)时响应
<category android:name="android.intent.category.DEFAULT" />
  • data,如下操作可以响应链接,不过需要在<intent-filter>标签中添加tools:ignore="AppLinkUrlError"
<activity android:name=".ThirdActivity">
            <intent-filter tools:ignore="AppLinkUrlError">
                <action android:name="android.intent.action.VIEW"/>'
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:scheme="https"/>
           	</intent-filter>
</activity>

二、Activity导航

1.显式导航

//构建Intent对象,参数:上下文Context,目的地Activity
val intent = Intent(this, SecondActivity::class.java)

//执行intent
startActivity(intent)

2.隐式Intent

            val intent = Intent("com.lrgy.activitytest.ACTION_START")//传入要响应界面的action值
            intent.addCategory()//传入要响应界面的category值,也可以不设置,即默认
            startActivity(intent)
  • 实现打开浏览器访问百度
            val intent = Intent(Intent.ACTION_VIEW)         //内置动作,跳转至其他应用
            intent.data = Uri.parse("https://baidu.com")    //接受Uri对象,设置目的uri
            startActivity(intent)

3.传递数据

  • 向下一个Activity传递

发送:

intent.putExtra("extra_data", "携带的信息")

接收:

intent.getStringExtra("extra_data")
  • 返回给上一个Activity

接受:

startActivityForResult(intent,10086)//带有返回结果的导航,10086是请求码,在这里设置
//重写onActivityResult方法,requestCode是请求码,resultCode是处理结果如RESULT_OK,data是回传的Intent
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        when(requestCode){
            10086 -> Log.d("mydebug", "收到下层反馈")
        }
    }

发送:

//按下返回键即调用该方法
override fun onBackPressed() {
        super.onBackPressed()
        val intent = Intent()
        intent.putExtra("data_return","返回给上层的数据")
        setResult(RESULT_OK,intent)//第一个参数是向上返回结果,用RESULT_OK就行
        finish()
    }

三、菜单

  1. 创建menu资源,使用<item>指定菜单项
<item
        android:id="@+id/add_item"
        android:title="Add"/>
  1. 重写创建菜单方法
//创建菜单,即在Activity中重写该方法
    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        
        //传入menu资源和要添加至的Menu对象,后者一般用onCreateOptionsMenu中自带参数menu
        menuInflater.inflate(R.menu.main, menu)
        
        //return true才能显示菜单
        return true                                        
    }
  1. 重写菜单选择方法
override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when(item.itemId){

            //使用toast弹出框。参数:上下文上下文Context、显示内容、常量LENGTH_SHORT或Toast.LENGTH_LONG
            R.id.add_item -> Toast.makeText(this,"add item",Toast.LENGTH_SHORT).show()
            R.id.remove_item -> Toast.makeText(this,"remove item",Toast.LENGTH_LONG).show()
        }

        /*关于返回值
          有人说:
        * true表示该方法执行完毕后,点击事件不会再向下一个事件处理方法传递了。
        * false表示执行完该方法后,点击事件继续向下传递。
        * */
        return false
    }

四、Activity的生命周期

详解见:Android Activity生命周期详解

五、 在Activity被回收时保存数据

fun onSaveInstanceState(outState: Bundle, outPersistentState: PersistableBundle)这个函数将会在Activity被回收前调用,我们可以把数据存放在outState: Bundle中。

override fun onSaveInstanceState(outState: Bundle, outPersistentState: PersistableBundle) {
        super.onSaveInstanceState(outState, outPersistentState)
        val tempData = "something you want to save"
        outState.putString("data_key",tempData)
    }

然后在onCreate中使用savedInstanceState: Bundle?取出数据

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        savedInstanceState?.let {
            Log.d(tag,it.getString("data_key"))
        }
    }

PS:关于手机屏幕旋转导致Activity重建的问题,我们有更优雅的解决方法,在13.2节

六、Activity的启动模式

通过在AndroidManifest.xml中的<activity>标签可以指定启动方式

<activity
      android:name=".FirstActivity"
      android:launchMode="standard">
      
</activity>
  1. standard
    即默认启动模式,不断创建新的FirstActivity实例
  2. singleTop
    若FirstActivity在返回栈的顶端,则不创建新的实例
  3. singleTask
    保持应用只有一个FirstActivity实例
  4. singleInstance
    创建新的返回栈,放入新的栈中

七、kotlin标准函数with/run/apply

  • 原生:
val list = listOf<String>("apple", "banana", "pear", "orange")
    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)
  • with
val result2 = with(StringBuilder()){
        append("start eating fruits...\n")
        for (fruit in list){
            append(fruit).append("\n")
        }
        append("ate all fruits.")
        toString()
    }
    println(result2)
  • run
val result3 = StringBuilder().run{
        append("start eating fruits...\n")
        for (fruit in list){
            append(fruit).append("\n")
        }
        append("ate all fruits.")
        toString()
    }
    println(result3)
  • apply
val result4 = StringBuilder().apply{
        append("start eating fruits...\n")
        for (fruit in list){
            append(fruit).append("\n")
        }
        append("ate all fruits.")
    }
    println(result4.toString())

八、Kotlin中的静态方法

  1. 使用单例类(伪静态方法,会创建单例类)
object Util {
    fun doAction(){
        println("do action")
    }
}
  1. 使用companion object(伪静态方法,会创建单例类)
class Util {
    companion object{
        fun doAction(){
            println("do action")
        }
    }
}
  1. 使用companion object加注解JvmStatic(真静态方法)
class Util {
    companion object{
        @JvmStatic
        fun doAction(){
            println("do action")
        }
    }
}
  1. 使用顶层方法,即没有类的方法
package com.lrgy.activitytest

fun doAction(){
    println("do action")
}

在Kotlin中直接用方法名调用,JAVA中用文件名Kt.方法名调用

九、Activity的最佳启动方法

1、使用一个静态方法:

companion object{
        fun actionStart(context: Context, title: String, content: String){
            val intent = Intent(context, NewsContentActivity::class.java).apply {
                putExtra("news_title", title)
                putExtra("news_content", content)
            }
            context.startActivity(intent)
        }
    }

这样可以在启动其他Activity时只使用一行代码进行启动,一目了然。
请给你的每个Activity都添加这样的启动方法

2、随时随地退出程序

  1. 建立ActivityCollector方便管理所有的Activity
//单例类,伪静态方法
object ActivityCollector {

    private val activities = ArrayList<Activity>()

    fun addActivity(activity: Activity){
        activities.add(activity)
    }

    fun removeActivity(activity: Activity){
        activities.remove(activity)
    }

    fun finishAll(){
        //finish所有activity
        for (activity in activities){
            if (!activity.isFinishing){
                activity.finish()
            }
        }
        activities.clear()//将集合中的所有activity元素清空
    }

}
  1. 建立BaseActivity类,使得所有activity都可以被ActivityCollector控制
/*该项目中所有Activity的父类*/
//添加open才可以被继承
open class BaseActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d("BaseActivity", javaClass.simpleName)//javaClass相当于java中的getClass方法,获取当前类的对象
        ActivityCollector.addActivity(this)
    }
    override fun onDestroy() {
        super.onDestroy()
        ActivityCollector.removeActivity(this)
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值