507 字
3 分鐘
08行動應用開發筆記

行動應用開發筆記#

Table of Contents#

[TOC]

Android (Jetpack Compose)#

可用套件#

Gson

com.google.code.gson:gson:2.10

OkHttp

com.squareup.okhttp3:okhttp:5.0.0

XML 解析#

fun parseXml(parser: XmlPullParser): List<String> {
var eventType = parser.eventType
val list = mutableListOf<String>()
var item = ""
while (eventType != XmlPullParser.END_DOCUMENT) {
when (eventType) {
XmlPullParser.START_TAG -> { // <xxx>
when (parser.name) {
"xxx" -> item = parser.nextText()
}
}
XmlPullParser.END_TAG -> { // <xxx/>
when (parser.name) {
"xxx" -> list.add(item)
}
}
}
eventType = parser.next()
}
return list
}
parseXml(context.resources.getXml(R.xml.resourceId))

讀res/raw資料#

通常用來讀取靜態JSON

context.resources.openRawResource(R.raw.xxx).bufferedReader().use {
it.readText() }

頁面導航#

因 Navigation 元件需要套件安裝,所以可用下列方法代替 (取自學長)

MainActivity.kt
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
val viewModel by viewModels<MainViewModel>()
setContent {
Crossfade(viewModel.screen, label = "") { screen ->
//若screen為空就退出App
screen?.invoke() ?: finish()
}
// 處理返回鍵
BackHandler(onBack = viewModel::pop)
}
}
}
MainViewModel.kt
class MainViewModel : ViewModel() {
private val screens = mutableStateListOf<@Composable () -> Unit>({ FirstScreen(this) })
// 用getter保持最新
val screen get() = screens.lastOrNull()
fun push(targetScreen: @Composable () -> Unit) {
screens += targetScreen
}
fun pushReplacement(targetScreen: @Composable () -> Unit) {
pop()
screens += targetScreen
}
fun pop() {
screens.removeLastOrNull()
}
}

Drawer#

val drawerState = rememberDrawerState(DrawerValue.Closed) // Closed, Open
ModalNavigationDrawer(
drawerContent = {
ModalDrawerSheet {
NavigationDrawerItem(
icon = { Icon(painterResource..., "") },
label = { Text("...") },
selected = false,
onClick = {}
)
}
},
drawerState = drawerState,
gesturesEnabled = true //右滑打開Drawer的手勢
)
NOTE

drawerState.open() / close() 為 suspend 方法

Pager#

HorizontalPager(水平) 適合用來公告輪播 亦有 VerticalPager (垂直)

val pagerState = rememberPagerState(
initialPage = 0, //Optional
pageCount = { 2 }
)
HorizontalPager(pagerState) { page ->
when (page) {
0 -> ..
}
}

WebView讀取本機HTML#

var webView: WebView? = null
AndroidView(
factory = { context ->
WebView(context).apply {
loadUrl("file:///android_asset/xxx")
webView = this
}
},
)
//返回鍵回到上一頁
BackHandler(onBack = {
webView!!.goBack()
})
NOTE

file://android_asset 指向 assets 資料夾

Gson#

toJson#

OkHttp#

GET#

val client = OkHttpClient().newBuilder().build()
val request = Request.Builder()
.url("http://10.0.2.2:8000/reminders/1")
.addHeader("accept","application/json")
.addHeader("X-API-KEY","KEY1")
.build()
val call = client.newCall(request)
call.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
println(e.message)
}
override fun onResponse(call: Call, response: Response) {
println(response.body.string())
}
})

POST (PATCH)#

val client = OkHttpClient().newBuilder().build()
val request = Request.Builder()
.url("http://10.0.2.2:8000/reminders/1")
.patch(Gson().toJson(
mapOf("enabled" to true)
).toRequestBody("application/json".toMediaType())) //.post() or .patch()
.addHeader("accept","application/json")
.addHeader("X-API-KEY","KEY1")
.build()
val call = client.newCall(request)
call.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
println(e.message)
}
override fun onResponse(call: Call, response: Response) {
println(response.body.string())
}
})
NOTE

可用 call.execute() 做同步請求 (不能在UI線程上)

NOTE

10.0.2.2 指向 Host IP

Flutter#

漸層 Paint#

final paint = Paint()
..strokeWidth = 5
..shader =
LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Color(0x552196F3), Colors.black],
).createShader(
Rect.fromLTRB(0, 0, size.width, size.height),
);
08行動應用開發筆記
https://blog.cpliang.com/posts/08-app-note/
作者
承噗
發佈於
2026-03-22
許可協議
CC BY-NC-SA 4.0