Kotlin+Jetpack Compose+Volley+ViewModel Android开发

2022-8-22 16:40:39 星期一

刚开始接触 kotlin + Jetpack Compose 开发 Android应用, 这里记录下自己的理解

 

建议看官方中文文档: 

https://developers.google.cn/codelabs/jetpack-compose-basics#0

https://developer.android.google.cn/codelabs/jetpack-compose-state#0

 

1. 概念

1.1 Jetpack Compose 是Android中一个取代xml的UI框架, 与Kotlin语法配合使用, Compose隶属于Jetpack

1.2 Volley 是一个轻量级的Http请求库, 谷歌官方的, 使用起来比较简单(听说适合纯数据请求, 不太适合图片请求)

1.3 ViewModel 保存数据用, 用来把volley从服务端请求的数据, 传递给compose在页面中显示出来

1.4 ViewModel + Compose的最佳实践是, 将数据的获取逻辑和UI的渲染分开在两个文件中编写, 数据有变化, UI自动变化

1.5 Json解析使用了官方的 json.org 库, 没有使用gson

 

2. 细节

2.1 Compose:

2.1.1 用Android Studio 创建应用的时候, 要选择 "Compose Activity", 这样才能使用Compose相关特性

2.1.2 Compose 中列表UI是 Column(){} 其中小括号中声明这个列表的样式, 花括号中写子控件(其他UI控件也是这个规律), 比如列表中有文本控件(Text(){}) 或 按钮控件(Button(){}) 或 行控件(Row(){})

2.1.3 可以将不同的控件写在一个函数中, 在MainActivity::onCreate()中被调用, 这个函数前边必须用 @Composable 注解

2.1.4 代码举例

 1 @Composable
 2 fun Greeting(name: String) {
 3    
 4     Column(
 5         modifier = Modifier
 6             .fillMaxHeight()
 7             .fillMaxWidth()
 8             .background(Color.LightGray)
 9             .padding(5.dp)
10         , verticalArrangement = Arrangement.Top
11         , horizontalAlignment = Alignment.CenterHorizontally
12     ) {
13         Text(text = "Hello $name! 111", Modifier.padding(5.dp).background(Color.White).border(1.dp, Color.Green, RoundedCornerShape(4.dp)))
14         Text(text = name, Modifier.padding(5.dp), fontSize = 18.sp, maxLines = 2, overflow = TextOverflow.Ellipsis, fontWeight = FontWeight.Bold)
15         Divider(color = Color.Black)
16 
17         Button(onClick = {}) {
18             Text(text = "点击")
19         }
20     }
21 }

 

 

2.2 Volley

2.2.1 他获取数据的时候, 必须传入上下文, 所以要在 MainActivity中调用并把 this传给他 (不知道还有没有其他调用方式)

2.2.2 用他获取数据, 处理数据的代码最好是写在ViewModel类中

 

2.3 ViewModel

2.3.1 需要新建一个MyxxxModel 继承自 ViewModel; 注意Kotlin继承的两种写法 (1. calss MyModel : ViewModel {} 2. class MyModel : ViewModel() {}  一个有小括号, 一个没有, 没有小括号, 就得手工调用父类的构造方法) 

2.3.2 用来存储服务端数据的成员变量(假如叫: data)要定义为 MutableStat 或 MutableStatList 前一个不是列表, 后一个可以放列表数据, 这样当这个数据改变的时候, UI才会跟着改变

2.3.3 代码举例: 

 1 public class NewsListModel : ViewModel() {
 2 
 3     public var data = mutableStateListOf<News>(); //UI中的数据来源
 4 
 5     public fun setData(ctx: Context) { 
 6         val url = "https://xxx.com/json_data";
 7         val queue = Volley.newRequestQueue(ctx);
 8         val stringRequest = StringRequest(
 9             url,
10             Response.Listener<String>{ response ->
11                 val obj = JSONObject(response)
12                 //Log.i("111-msg", obj.getString("msg"))
13                 //Log.i("111-msg", obj.getString("code"))
14                 val arr = obj.getJSONArray("data");
15                 for (i in 0 until arr.length()) {
16                     val item = arr.getJSONObject(i);
17                     data.add(News(item.getString("title"), item.getString("desc"))); //News类的定义在下边
18                 }
19             },
20             Response.ErrorListener { Log.i("1111", "error") }
21         )
22         queue.add(stringRequest); //通过volley获得服务端数据
23     }
24 
25 }
26 
27 data class News(val title:String, val desc:String); //就这样写, 不用写花括号

 

2.3.4 在在MainActivity中使用ViewModel单例, 这样写: 

1 class MainActivity : xxxx () {
2     override fun onCreate(xxx) {
3         .....
4         val vm:MyxxxModel = viewModel(); //单例写法
5         vm.setData(this) //这个方法用Volley去请求服务端数据, 然后给vm.data赋值
6         .....
7     }
8 }

 

2.4 UI控件中使用ViewModel

 1 @Composable
 2 fun NewsList(vm:NewsListModel = viewModel()) {
 3     Column() {
 4         vm.data.forEach { 
 5             Row() {
 6                 Text(text = "${it.title} : ${it.desc}")
 7             }
 8         }
 9     }
10 }

2.4.1 此方法会在MainActivity中setContent()直接或间接调用, 调用时, 不用传入viewModel参数, 系统会自动实例化vm

2.4.2 调用了被@Composable注解的方法也必须有@Composable注解

2.4.3 其中的it, 是forEach这个lamda方法的默认参数, 代指循环中的每一个item

posted @ 2022-08-22 17:37  myD  阅读(274)  评论(0编辑  收藏  举报