第一行代码:Android 学习笔记
Activity
3.2 Activity的基本用法
-
Activity
- 一个app可以有多个activity
- activity位于app/src/main/java/com.xxx.xxx,是kotlin文件
-
Activity的Layout(布局)
- 逻辑和视图分离,视图用layout
- 一个activity对应一个layout
- layout在app/src/main/res/layout
- layout有LinearLayout,RelativeLayout等多种布局形式
- layout是xml文件
- 在activity(Kotlin)的
onCreate
函数中加入setContentView(R.layout.xxxx)
为activity加载布局
-
Activity中的元素
-
layout中可以有Button,TextView等元素
-
元素的多种属性(在layout文件中,属于布局的样式)
android:id="@+id/id_name"
元素的名字android:layout_width/height="10dp"/"wrap_content"
"10dp"
是直接写出长度,单位有dp,sp,px等"wrap_content"
是适合当前内容长度"match_parent"
是和父元素一样宽
android:text
显示的内容
-
元素的事件(在activity文件中,属于与元素交互的逻辑)
- 首先
findViewById
,将布局文件中的元素在Kotlin代码中声明val button1 :Button = findViewById(R.id.button1)
- 按钮的点击
button1.setOnClickListener { ... }
- Toast底部通知
-
Toast.makeText(this, "...", Toast.LENGTH_SHORT).show()
-
...
为通知的内容 -
先通过
makeText()
构建 一个新的Toast对象,之后调用show()
将其显示 -
第三个参数有默认的
Toast.LENGTH_SHORT
和Toast.LENGTH_LONG
两种val button1 :Button = findViewById(R.id.button1) button1.setOnClickListener { Toast.makeText(this, "You click it!", Toast.LENGTH_SHORT).show() }
-
- 首先
-
-
AndroidManifest 文件
- 位于app/src/main/AndroidManifest.xml
- 所有activity在此注册,新建activity时AS会自动注册
- 可修改如下activity的属性
name
代码中的名字label
运行时在顶栏显示的文字,主activity的label
还是应用程序显示的名称- 是否是主activity
<intent-filter>
action
,category
,data
<activity android:name=".FirstActivity" android:label="This is FirstActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
-
Activity中的Menu
-
menu在app/src/main/res/menu
-
为menu添加item,属于视图部分(xml)。menu中的两个item如下图添加
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/add_item" android:title="Add" /> <item android:id="@+id/remove_them" android:title="Remove" /> </menu>
-
重写
onCreateOptionsMenu()
函数(可以使用Ctrl+O快捷键)override fun onCreateOptionsMenu(menu: Menu?): Boolean { menuInflater.inflate(R.menu.main, menu) return true }
menuInflater
是通过调用父类的getMenuInflater
获得,属于Kotlin的”语法糖“inflater
接受两个参数,第一个是通过哪个文件来创建菜单,第二个是添加到哪一个菜单中- 返回值为
true
时,创建的菜单才能显示
-
重写
onOptionsItemSelected()
函数override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { R.id.add_item -> Toast.makeText(this, "Add!", Toast.LENGTH_SHORT).show() R.id.remove_them -> Toast.makeText(this, "Remove!", Toast.LENGTH_SHORT).show() } return true }
- 对应的id出现对应的通知
-
3.3 使用Intent切换Activity
-
显式intent
button1.setOnClickListener { val intent = Intent(this, SecondActivity::class.java) startActivity(intent) }
- (假设要启动的activity叫
SecondActivity
) - 先以要启动activity的名字__构建__一个intent对象
- 调用函数
startActivity
启动activity
- (假设要启动的activity叫
-
隐式intent
button1.setOnClickListener { val intent = Intent("com.example.firstcode.ACTION_START") intent.addCategory("com.example.firstcode.MY_CATEGORY") startActivity(intent) }
- 以action构建一个intent对象,可以实现这个action的activity将会被启动
- 之后使用添加category的函数
addCategory
,有同时满足两个条件的activity才会启动,否则程序崩溃
-
使用隐式intent调用浏览器,电话
-
调用浏览器
button1.setOnClickListener { val intent = Intent(Intent.ACTION_VIEW) intent.data = Uri.parse("https://www.baidu.com") startActivity(intent) }
Intent.ACTION_VIEW
是浏览器的action,等于"android.intent.action.VIEW"
Uri.parse()
将字符串转为data- AndroidManifest.xml中可以为activity添加
action
,category
,data
- data可以配置
<data android:scheme="https" />
https://xx.xx.xx.xx:xxxx/xxx/xxx/xxxandroid:scheme
协议httpsandroid:host
主机名xx.xx.xx.xxandroid:port
端口:xxxxandroid:path
路径/xxx/xxx/xxxandroid:mimetype
可以处理的数据类型
-
让一个activity以浏览器的形式被调用
- 在AndroidManifest.xml对应的activity处加上
<action android:name="android.intent.action.VIEW"
- 系统会问你选哪个
- 在AndroidManifest.xml对应的activity处加上
-
调用电话
button1.setOnClickListener { val intent = Intent(Intent.ACTION_DIAL) intent.data = Uri.parse("tel:10086") startActivity(intent) }
Intent.ACTION_DIAL
是电话的actionUri.parse
将字符串转化为电话
-
-
activity间传递数据
-
向下一个activity传递数据
-
前一个activity中
button1.setOnClickListener { val intent = Intent(this, SecondActivity::class.java) val data = "Hello SecondActivity" intent.putExtra("extra_data", data) startActivity(intent) }
- 使用
putExtra
函数在intent中添加数据 - 第一个参数是用于取值的键,第二个参数是数据
- 使用
-
后一个activity中
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_second) val extraData = intent.getStringExtra("extra_data") Log.d("Second_Activity", "extra data is $extraData") Toast.makeText(this, "$extraData", Toast.LENGTH_SHORT).show() }
- intent是调用父类的
getIntent()
- 通过
intent.getStringExtra("...")
获得数据 ...是键 - 整数使用
getIntExtra()
,布尔型使用getBooleanExtra()
- intent是调用父类的
-
-
返回数据给上一个activity
-
前一个activity中
button1.setOnClickListener { val intent = Intent(this, SecondActivity::class.java) val data = "Hello SecondActivity" intent.putExtra("extra_data", data) startActivityForResult(intent, 1) }
- 使用
startActivityForResult(intent, 1)
函数- 第二个参数为请求码,请求码是唯一值(为了区分调用的是哪个activity)
- 使用
-
后一个activity中(当按钮2用于结束activity时)(
onBackPressed
为按下返回键结束activity前执行)button2.setOnClickListener { val intent = Intent() intent.putExtra("data_return", "Hello FirstActivity") setResult(RESULT_OK, intent) finish() }
override fun onBackPressed() { val intent = Intent() intent.putExtra("data_return", "Hello FirstActivity") setResult(RESULT_OK, intent) finish() }
- 创建一个intent但不用来调用activity只用来传递信息
- 使用
setResult()
函数- 第一个参数返回处理结果,
RESULT_OK
和RESULT_CANCELED
两种 - 第二个参数通过intent返回数据
- 第一个参数返回处理结果,
-
又是前一个activity
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) when(requestCode) { 1 -> if(resultCode == RESULT_OK) { val returnedData = data?.getStringExtra("data_return") Toast.makeText(this, "$returnedData", Toast.LENGTH_SHORT).show() Log.d("FirstActivity", "returned data is $returnedData") } } }
- 后一个activity销毁后调用
onActivityResult
requestCode
从前一个activity中来,是请求码resultCode
从后一个activity中来,是后一个activity的能否返回数据的处理结果data
是用于返回数据的intent
- 后一个activity销毁后调用
-
-
3.4 Activity的生命周期
- activity使用返回栈管理
- activity有多种状态
- 运行 位于栈顶
- 暂停 不位于栈顶但可见
- 停止 不位于栈顶且不可见
- 销毁 从返回栈中移除
- 函数
onCreate()
onDestory()
创建和销毁时调用onStart()
onStop()
在不可见和可见切换时调用onResume()
onPause()
在是不是栈顶时调用onRestart()
在停止变成运行时调用onStop()
->onRestart()
->onStart()
- 在activity被回收之前保存数据
- 在被回收前一定会调用
onSaveInstanceState()
函数 - 在这个函数携带的
Bundle
类型的参数中putString()
- 在
onCreate()
函数的Bundle
类型的参数中重新取出数据
- 在被回收前一定会调用
3.5 Activity的启动模式
在AndroidManifest中修改
- standard 可以有很多的相同的activity
- singleTop 栈顶只能有一个相同的activity
- singleTask 总共只能有一个相同的activity
- singleInstance 为当前activity创造一个新的栈 /- /-
3.6 Activity的技巧
- 构建BaseActivity类,在其中输出调试信息,并让所有activity都继承于BaseActivity类,可以让每个activity都打印调试信息
- 构建单例类,每次
onCreate()
/onDestory()
调用,用ArrayList
记录,可以随时调用函数将所有activity结束 - 在每个activity中构建类静态函数
actionStart
,在其中构建intent并添加数据,之后调用当前activity。这样做可以使被调用activity需要的数据传递更清晰。
3.7 Kotlin 课堂
-
标准函数
with
run
apply
val xxx = with(obj) { a() b() c() d() // 最后一个是赋给xxx的值 } == val xxx = obj.run { a() b() c() d() // 最后一个是赋给xxx的值 } == val temp = obj.apply { a() b() c() } val xxx = temp.d() == val temp = obj obj.a() obj.b() obj.c() val xxx = temp.d()
-
静态方法
class Util { companion object { fun doAction { ... } } }
- 可以直接调用
Util.doAction()
,但是并非真正静态办法,在Java中无法使用 - 在
companion object
内部加入@JvmStatic
可以编译成真正的静态方法,Java中也可以使用
- 可以直接调用