kotlin学习 - Kotlin 循环

1
2
3
4
5
6
7

//从 1 到 10
for (i in 1..10) {
//1,2,3,4,5,6,7,8,9,10
println(i)
}

1
2
3
4
5
6
7

//从 1 到 9
for (i in 1 until 10) {
//1,2,3,4,5,6,7,8,9
println(i)
}

1
2
3
4
5
6
//从 10 到 1
for (i in 10 downTo 1) {
//10,9,8,7,6,5,4,3,2,1
println(i)
}

1
2
3
4
5
6
//从 1 到 10 步长为 2
for (i in 1..10 step 2) {
//1,3,5,7,9
println(i)
}

repeat(count:Int) 一个高阶的循环函数,count代表循环的次数,在函数内,it代表到第几次
注意:it是从0开始计数的

1
2
3
4
5
6
//从 0 到 9
repeat(10) {
//0,1,2,3,4,5,6,7,8,9
println(it)
}

1
2
3
4
5
6
7

val list = arrayListOf<String>("A", "B", "C", "D")
for (str in list) {
//A,B,C,D
println(str)
}

1
2
3
4
5
6
7

val list = arrayListOf<String>("A", "B", "C", "D")
for ((index,str) in list.withIndex()){
//index 从 0 开始
println("第${index}个的元素是$str")
}

kotlin学习 - Kotlin 解构

解构

解构声明 将一个对象 拆解成 若干个变量 分别赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

fun main(args: Array<String>) {
val user = User(12,"zs")
val (age,name,user_data) = user
println("age = ${age}")
println("name = ${name}")
println("user_data = ${user_data}")
}

class User(var age: Int, var name: String) {
//operator 将 一个函数 标记为 重载一个操作符 或实现 一个约定
operator fun component1() = age
operator fun component2() = name
operator fun component3() = "${age} ${name}"
}

自定义解构声明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Book(var name: String, var price: Float) {
operator fun component1(): String {
return name
}

operator fun component2(): Float {
return price
}
}

fun main(args: Array<String>) {
val (name, price) = Book("Kotlin入门", 66.6f)
println(name)
println(price)
}
1
2
3
4
5
6
7
8
9
10
11
12
fun main(args: Array<String>) {
val (name,price) = getBookInfo()
println("name = ${name}")
println("price = ${price}")
}

fun getBookInfo(): Book {
return Book("Kotlin入门", 66.6f)
}

data class Book(var name: String, var price: Float)

Kotlin 中数组,list、map系列集合默认也支持解构声明的功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
fun main(args: Array<String>) {
val array = arrayOf(1, 2, 3)
val (a1, a2, a3) = array
println("$a1")
println("$a2")
println("$a3")

val list = listOf(1, 2, 3)
val (b1, b2, b3) = list
println("$b1")
println("$b2")
println("$b3")

val map = mapOf("key1" to 1, "key2" to 2, "key3" to 3)
for ((key, value) in map) {
println("$key-$value")
}
}

忽略不需要的解构

如果在解构声明中不需要某个变量,那么可以用下划线_取代其名称,这样也就不会调用相应的componentN()操作符函数:

1
val (_, price2) = Book("Kotlin入门", 66.6f)    

Http 学习 v1

HTTP 的定义

⼀种⽹络传输协议,位于 TCP / IP 协议族的最顶层——应⽤层。

Hypertext Transfer Protocol,超⽂本传输协议,和 HTML (Hypertext Markup Language 超⽂本标记语⾔) ⼀起诞⽣,⽤于在⽹络上请求和传输 HTML 内容。

HTTP 的⼯作⽅式

浏览器 :

  • ⽤户输⼊地址后回⻋或点击链接
  • 浏览器拼装 HTTP 报⽂并发送请求给服务器
  • 服务器处理请求后发送响应报⽂给浏览器
  • 浏览器解析响应报⽂并使⽤渲染引擎显示到界⾯

⼿机 App

  • ⽤户点击或界⾯⾃动触发联⽹需求
  • Android 代码调⽤拼装 HTTP 报⽂并发送请求到服务器
  • 服务器处理请求后发送响应报⽂给⼿机
  • Android 代码处理响应报⽂并作出相应处理(如储存数据、加⼯数据、显示数据到界⾯)

URL 和 HTTP 报⽂

URL 格式

三部分:协议类型、服务器地址(和端⼝号)、路径(Path)

协议类型://服务器地址[:端⼝号]路径

http://hencoder.com/users?gender=male

报⽂格式

请求报⽂

  • 请求报文格式:请求行、Headers、Body
  • 请求行:Method、Path、HTTP version
  • Method:GET、POST、PUT、DELETE …
  • Headers:请求的 meta data
  • Body:要发送给服务器的内容

响应报⽂

  • 响应报文格式:状态行、Headers、Body
  • 状态行:HTTP version、Status Code、Status Message
  • Status Code: 1xx(信息)、2xx(成功)、3(重定向)、4(客户端错误)、5(服务器错误)

Request Method 请求⽅法

GET

  • ⽤于获取资源
  • 对服务器数据不进⾏修改
  • 不发送 Body
1
2
GET /users/1 HTTP/1.1
Host: api.github.com

对应 Retrofit 的代码:

1
2
@GET("/users/{id}")
Call<User> getUser(@Path("id") String id, @Query("gender") String gender);

POST

  • ⽤于增加或修改资源
  • 发送给服务器的内容写在 Body ⾥⾯
1
2
3
4
5
POST /users HTTP/1.1
Host: api.github.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 13
name=rengwuxian&gender=male

对应 Retrofit 的代码:

1
2
3
4
@FormUrlEncoded
@POST("/users")
Call<User> addUser(@Field("name") String name, @Field("gender") String
gender);

PUT

  • ⽤于修改资源
  • 发送给服务器的内容写在 Body ⾥⾯
1
2
3
4
5
PUT /users/1 HTTP/1.1
Host: api.github.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 13
gender=female

对应 Retrofit 的代码:

1
2
3
4
@FormUrlEncoded
@PUT("/users/{id}")
Call<User> updateGender(@Path("id") String id, @Field("gender") String
gender);

DELETE

  • ⽤于删除资源
  • 不发送 Body
1
2
DELETE /users/1 HTTP/1.1
Host: api.github.com

对应 Retrofit 的代码:

1
2
@DELETE("/users/{id}")
Call<User> getUser(@Path("id") String id, @Query("gender") String gender);

HEAD

  • 和 GET 使⽤⽅法完全相同
  • 和 GET 唯⼀区别在于,返回的响应中没有 Body

可以在下载文件时,先获取文件长度,是否这次断点续传等

Status Code 状态码

  • 1xx:临时性消息。如:100 (继续发送)、101(正在切换协议)
  • 2xx:成功。最典型的是 200(OK)、201(创建成功)。
  • 3xx:重定向。如 301(永久移动)、302(暂时移动)、304(内容未改变)。
  • 4xx:客户端错误。如 400(客户端请求错误)、401(认证失败)、403(被禁⽌)、404(找不到内容)。
  • 5xx:服务器错误。如 500(服务器内部错误)。

Header

作⽤:HTTP 消息的元数据( metadata )。

Host

⽬标主机。注意:不是在⽹络上⽤于寻址的,⽽是在⽬标服务器上⽤于定位⼦服务器的。

Content-Type

指定 Body 的类型。主要有四类:

1. text/html

请求 Web ⻚⾯是返回响应的类型,Body 中返回 html ⽂本。

1
2
3
4
5
6
7
8
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 853
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
......

2. x-www-form-urlencoded

Web ⻚⾯纯⽂本表单的提交⽅式

1
2
3
4
5
POST /users HTTP/1.1
Host: api.github.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 27
name=rengwuxian&gender=male

对应 Retrofit 的代码:

1
2
3
4
@FormUrlEncoded
@POST("/users")
Call<User> addUser(@Field("name") String name, @Field("gender") String
gender);

3. multitype/form-data

Web ⻚⾯含有⼆进制⽂件时的提交⽅式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST  /users  HTTP/1.1
Host: hencoder.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Length: 2382

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="name"

rengwuxian
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="avatar"; filename="avatar.jpg"
Content-Type: image/jpeg

JFIFHHvOwX9jximQrWa......
------WebKitFormBoundary7MA4YWxkTrZu0gW--

对应 Retrofit 的代码:

1
2
3
4
5
6
7
8
9
10
@Multipart
@POST("/users")
Call<User> addUser(@Part("name") RequestBody name, @Part("avatar")
RequestBody avatar);
...
RequestBody namePart = RequestBody.create(MediaType.parse("text/plain"),
nameStr);
RequestBody avatarPart = RequestBody.create(MediaType.parse("image/jpeg"),
avatarFile);
api.addUser(namePart, avatarPart);

4. application/json , image/jpeg , application/zip …

单项内容(⽂本或⾮⽂本都可以),⽤于 Web Api 的响应或者 POST / PUT 的请求

1
2
3
4
5
6
7
//请求中提交 JSON

POST /users HTTP/1.1
Host: hencoder.com
Content-Type: application/json; charset=utf-8
Content-Length: 38
{"name":"rengwuxian","gender":"male"}

对应 Retrofit 的代码:

1
2
3
4
5
@POST("/users")
Call<User> addUser(@Body("user") User user);
...
// 需要使⽤ JSON 相关的 Converter
api.addUser(user);
1
2
3
4
5
6
7
8
//响应中返回 JSON
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
content-length: 234
[{"login":"mojombo","id":1,"node_id":"MDQ6VXNl
cjE=","avatar_url":"https://avatars0.githubuse
rcontent.com/u/1?v=4","gravat......

1
2
3
4
5
6
7
8
//请求中提交⼆进制内容

POST /user/1/avatar HTTP/1.1
Host: hencoder.com
Content-Type: image/jpeg
Content-Length: 1575
JFIFHH9......

对应 Retrofit 的代码:

1
2
3
4
5
6
@POST("users/{id}/avatar")
Call<User> updateAvatar(@Path("id") String id, @Body RequestBody avatar);
...
RequestBody avatarBody = RequestBody.create(MediaType.parse("image/jpeg"),
avatarFile);
api.updateAvatar(id, avatarBody)

相应中返回⼆进制内容

1
2
3
4
HTTP/1.1 200 OK
content-type: image/jpeg
content-length: 1575
JFIFHH9......

Content-Length

指定 Body 的⻓度(字节)

Transfer: chunked (分块传输编码 Chunked Transfer Encoding)

⽤于当响应发起时,内容⻓度还没能确定的情况下。和 Content-Length 不同时使⽤。⽤途是尽早给出响应,减少⽤户等待。

1
2
3
4
5
6
7
8
9
10
HTTP/1.1 200 OK
Content-Type: text/html
Transfer-Encoding: chunked
4
Chun
9
ked Trans
12
fer Encoding
0

Location

指定重定向的⽬标 URL

User-Agent

⽤户代理,即是谁实际发送请求、接受响应的,例如⼿机浏览器、某款⼿机 App。

Range / Accept-Range

按范围取数据

  • Accept-Range: bytes 响应报⽂中出现,表示服务器⽀持按字节来取范围数据
  • Range: bytes=- 请求报⽂中出现,表示要取哪段数据
  • Content-Range:-/total 响应报⽂中出现,表示发送的是哪段数据

作⽤:断点续传、多线程下载。

其他 Headers

  • Accept: 客户端能接受的数据类型。如 text/html
  • Accept-Charset: 客户端接受的字符集。如 utf-8
  • Accept-Encoding: 客户端接受的压缩编码类型。如 gzip
  • Content-Encoding:压缩类型。如 gzip

Cache

作⽤:在客户端或中间⽹络节点缓存数据,降低从服务器取数据的频率,以提⾼⽹络性能。

REST

REST HTTP 即正确使⽤ HTTP。
* 使⽤资源的格式来定义 URL
* 规范地使⽤ method 来定义⽹络请求操作
* 规范地使⽤ status code 来表示响应状态
* 其他符合 HTTP 规范的设计准则

kotlin学习 - Jave 与 Kotlin 注意事项

java中使用kotlin的顶层方法

1
2
3
4
5
//Test.kt

fun echo(name: String) {
System.out.println(name)
}
1
2
3
4
5
6
7
8
//Test.java

class TestDemo {
public static void main(String[] args) {
//java 中使用 kotlin文件中的方法,默认写法是 xxKt.echo("hello")
TestKt.echo("hello");
}
}

java中使用kotlin的方法 ( 自定义 kt 文件类名 )

1
2
3
4
5
6
7
8
9
10
//Test.kt

//自定义编译后生成的文件名
@file:JvmName("TestDemoCode")
//编译后会强制性的把多个文件内容合并在一起
@file:JvmMultifileClass
package com.jetpack.compose.demo.test
fun echo(name: String) {
System.out.println(name)
}
1
2
3
4
5
6
7
8
9

//Test.java

class TestDemo {
public static void main(String[] args) {
TestDemoCode.echo("hello");
}
}

java文件 kotlin文件 中的 class 使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
fun main() {
// TestDemoJave.java
testClass(TestDemoJave::class.java)
testKClass(TestDemoJave::class)
// TestDemoKotlin.java
testKotlinClass(TestDemoKotlin::class)
}

fun testClass(clazz: Class<TestDemoJave>) {
println(clazz.simpleName)
}

fun testKClass(clazz: KClass<TestDemoJave>) {
println(clazz.simpleName)
}

fun testKotlinClass(clazz: KClass<TestDemoKotlin>) {
println(clazz.simpleName)
}

Kotlin 没有静态变量与 静态方法

1
2
3
4
5
6
7
8
9
10
11
12
//TestDemoKotlin.kt

object TestDemoKotlin {
@JvmStatic
fun sayMessageStatic(msg: String) {
println(msg)
}

fun sayMessage(msg: String) {
println(msg)
}
}
1
2
3
4
5
6
7
8
9
10
11
//TestDemoJave.java

public class TestDemoJave {
public static void main(String[] args) {
//静态方法
TestDemoKotlin.sayMessageStatic("hello");

TestDemoKotlin.INSTANCE.sayMessage("hello");
}
}

函数嵌套

用途 :  在某些条件下触发递归的函数,不希望被外部函数访问到的函数
1
2
3
4
5
6
7
8
9
10
11
fun function() {
val str = "hello world"
//函数嵌套
fun say(count: Int = 10) {
println(str)
if (count > 0) {
say(count - 1)
}
}
say()
}

在Java中使用Kotlin中的扩展函数

1
2
3
4
5
//TestDemoKotlin.kt

fun String?.isNoEmpty(): Boolean {
return this != null && this.length > 0
}
1
2
3
4
5
6
//TestDemoJave.java

String str = "hello word";
//使用kotlin中的扩展函数 (第一个参数 必须是 扩展类的对象)
// xxKt.isNoEmpty(str)
TestDemoKotlinKt.isNoEmpty(str);

lambda 在 kotlin 中 最多只支持22个参数(Function22)

1
2
3
4
5
6
7
8
* Function23.java


package kotlin;

public interface Function23<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, R> extends Function<R> {
R invoke(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10, P11 p11, P12 p12, P13 p13, P14 p14, P15 p15, P16 p16, P17 p17, P18 p18, P19 p19, P20 p20, P21 p21, P22 p22, P23 p23);
}
1
2
3
4
5
6
7
8
9

val lambdaA = { a: Int, b: Int, c: Int, d: Int, e: Int, f: Int, g: Int, h: Int,i: Int, j: Int, k: Int, l: Int, m: Int, n: Int, o: Int, p: Int, q: Int, r: Int, s: Int, t: Int, u: Int, v: Int, w: Int ->
println("zhang tao")
}

fun main(args: Array<String>) {
// print("hello")
lambdaA(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
}

inline 将内联函数的函数体复制到调用处实现内联 ( 内联可能导致生成的代码增加 )

1
inline fun <T> lock(lock: Lock, body: () -> T): T { …… }

noinline 标记不希望内联的函数参数

1
inline fun foo(inlined: () -> Unit, noinline notInlined: () -> Unit) { …… }

Kotlin 可见性修饰符

修饰符 同类 同模块 子类 其他
public(公开,默认)
internal(模块) - -
protected(受保护) - -
private(私有) - - -

Java 访问控制修饰符

修饰符 同类 同包 子类 不同包
public(公开)
protected(受保护) -
没有修饰符(默认) - -
private(私有) - - -

单例 例子

1
2
3
4
5
6
7
8
9
10
11
class Single private constructor() {
companion object {
fun get(): Single {
return Holder.instance
}
}

private object Holder {
val instance = Single()
}
}

kotlin 封闭类(枚举类)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
sealed class SuperCommand {
object A : SuperCommand()
object B : SuperCommand()
object C : SuperCommand()
object D : SuperCommand()
class E(var name: String) : SuperCommand()
}

fun exec(superCommand: SuperCommand) =
when (superCommand) {
SuperCommand.A -> {
}
SuperCommand.B -> {
}
SuperCommand.C -> {
}
SuperCommand.D -> {
}
is SuperCommand.E -> {

}
}

Jetpack Compose学习 -------- Divider 分割线

Divider 分割线 基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

@Composable
fun ComposableSample() {
Column(Modifier.fillMaxWidth()) {
Text("Hello Word Hello Word Hello Word")
//分割线
Divider(
//颜色
color = Color.Blue,
//线的高度
thickness = 1.dp,
//距离开始的间距
startIndent = 10.dp
)
Text("Hello Word")
//分割线
Divider(
Modifier
.fillMaxWidth()
.height(1.dp)
.padding(start = 10.dp, end = 10.dp),
//颜色
color = Color.Green,
)
Text("Hello Word Hello Word")
Text("Hello Word Hello Word Hello Word")
}
}