Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
KtRssReader 的奇幻旅程
Search
Ivan
March 23, 2021
120
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
KtRssReader 的奇幻旅程
Ivan
March 23, 2021
More Decks by Ivan
See All by Ivan
Kotlin Flow Application and Testing on Android
ivanw
0
330
Kotlin Flow Application and Testing on Android
ivanw
1
470
A Step-by-Step Guide to Kotlin Flow 手把手帶你認識 Kotlin Flow
ivanw
0
240
Coroutines Made Easy
ivanw
1
200
All About KotlinConf 2019
ivanw
0
130
Writing Tests in Kotlin
ivanw
0
360
Using Kotlin in Android
ivanw
0
120
Featured
See All Featured
The Curse of the Amulet
leimatthew05
1
13k
The #1 spot is gone: here's how to win anyway
tamaranovitovic
2
1.1k
Typedesign – Prime Four
hannesfritz
42
3.1k
A Soul's Torment
seathinner
6
3k
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
320
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.1k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Utilizing Notion as your number one productivity tool
mfonobong
4
320
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.5k
GraphQLとの向き合い方2022年版
quramy
50
15k
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
2
400
Facilitating Awesome Meetings
lara
57
7k
Transcript
KtRssReader 的奇幻旅程 Ivan & 小汪 1
• 為什麼要做 KtRssReader ? • KtRssReader 簡介與用法 • 實作方式 •
程式碼發佈方式 • 未來方向 Outline 2
Rss Feed 為什麼要做KtRssReader ? 3
<?xml version="1.0"?> <rss version="2.0"> <channel> <image> <link>http://channel.image.link</link> <title>channel image title</title>
<url>http://channel.image.url</url> <description>channel image description</description> <height>32</height> <width>96</width> </image> </channel> </rss> RSS 2.0 4
<?xml version="1.0" encoding="UTF-8"?> <rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0"> <channel> <itunes:image href="https://channel.image.itunes" />
<image> <link>http://channel.image.link</link> <title>channel image title</title> <url>http://channel.image.url</url> <description>channel image description</description> <height>32</height> <width>96</width> </image> </channel> </rss> iTunes 5
<?xml version="1.0"?> <rss xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0"> <channel> <googleplay:image href="http://channel.image" />
<itunes:image href="https://channel.image" /> <image> <link>http://channel.image</link> <title>channel image title</title> <url>http://channel.image.url</url> <description>channel image description</description> <height>32</height> <width>96</width> </image> </channel> </rss> Mixing 6
<?xml version="1.0"?> <rss xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0"> <channel> <itunes:image href="https://channel.image.itunes" />
<image> <link>http://channel.image.link</link> <title>channel image title</title> <url>http://channel.image.url</url> <description>channel image description</description> <height>32</height> <width>96</width> </image> </channel> </rss> 遇到的情況 7
8
9
• 每則 Rss Feed 提供的 Tag 資訊不一 • 自己制定自己想要讀取順序,減少開發成本 問題總結
10
◦ Easy-to-use API ◦ Fetches feed for you ◦ Database
cache and custom cache valid time ◦ Supports RSS 2.0 standard, iTunes, and Google Play tags ◦ Customizes output data with annotations KtRssReader 簡介 11
MainScope().launch { val rssData = withContext(Dispatchers.IO) { Reader.coRead<ITunesChannelData>(url) { useCache
= true expiredTimeMillis = 3.days.toLongMilliseconds() charset = Charsets.UTF_8 } } print(rssData) } • Reader.read() • Reader.flowRead() 基礎使用 12
• RssStandardChannelData • ITunesChannelData • GoogleChannelData • AutoMixChannelData ( RssStandard
> iTunes > GooglePlay ) Channel Data 13
annotation class RssTag( val name: String = "", val order:
Array<OrderType> = [OrderType.RSS_STANDARD, OrderType.ITUNES, OrderType.GOOGLE] annotation class RssRawData(val rawTags: Array<String>) RssTag 14
@RssTag(name = "channel") data class CustomChannelData( @RssTag(name="title",order = [OrderType.GOOGLE, OrderType.ITUNES,
OrderType.RSS_STANDARD]) val rssTitle: String?, @RssRawData(["itunes:summary", "googleplay:description", "googleplay:summary"]) val description: String?, ) : Serializable Custom RSS Data 15
• Parser 實作面向 ◦ 標準 TAG Parser ▪ RSS 2.0
▪ Google ▪ iTunes ▪ Auto Mixed (All together) ◦ 自定義 Parser ▪ Annotation ▪ KAPT 實作方式 16
• Kotlin Parser ◦ 使用 DOM Parser ▪ 方便跨層尋找 TAG
• 可以處理 TAG 內夾帶 HTML 碼的情況 ▪ RSS 檔案大的時候,比較耗記憶體 ▪ 若有相同 TAG 且多筆資料,需判斷他的父節點 ◦ 實作 ▪ RssStandardParser.kt, GoolgeParser.kt, ITunesParser.kt , AutoMixParser.kt 標準 TAG Parser 17
• Android Parser ◦ 使用 Android 原生 XmlPullParser ▪ 比
DOM parser 省記憶體 ▪ 速度比 SAX 快 ▪ Event Stream 方式載入 TAG ◦ 實作 ▪ AndroidRssStandardParser.kt, AndroidGoogleParser.kt, AndroidITunesParser.kt, AndroidAutoMixParser.kt 標準 TAG Parser 18
哇,是自定義 Parser ? 19
• Annotation ◦ @RssTag ◦ @RssAttribute ◦ @RssValue ◦ @RssRawData
自定義 Parser 20
• 這樣訂的好處 ◦ 可以知道使用者想爬到的資料結構長怎樣 ◦ 用不同的 Annotation 知道資料的類型,像是 Tag、Attribute、Value等 ◦
如果資料的 TAG 長得很特別也可以用 @RssRawData 爬 ▪ <yoyoyo:checkitout> 自定義 Parser 21
• Annotation Processor ◦ KAPT, Kotlin annotation processing tool ◦
讓我們可以讀到 annotation 標記的 class、method、variable 等 • Kotlin Poet ◦ 用來產生 Kotlin 程式碼的程式庫 ◦ 用簡單易懂的語法在 building 的時候就可以產生程式碼 ▪ 支援 Control flow ▪ 有各種 Type 和 Class 的表達式 自定義 Parser 22
• 新增一個 module 放 annotation • 新增一個 module 放 processor
apply plugin: 'kotlin-kapt' dependencies { implementation 'com.squareup:kotlinpoet:1.6.0' implementation "com.google.auto.service:auto-service:1.0-rc6" } Annotation Processor 23
• 在 processor/src/main/resources/META-INF/services/ 下 ◦ 新增 javax.annotation.processing.Processor 檔案 ◦ 裡面寫你的
processor 的 package name 完整路徑 Annotation Processor 24
• 開始寫屬於你的 processor @AutoService(Processor::class) class RssAnnotationProcessor : AbstractProcessor() { override
fun getSupportedAnnotationTypes(): MutableSet<String> { return mutableSetOf( RssTag::class.java.canonicalName, RssRawData::class.java.canonicalName, RssAttribute::class.java.canonicalName, RssValue::class.java.canonicalName ) } override fun process(typeElementSet: MutableSet<out TypeElement>?, roundEnvironment: RoundEnvironment?): Boolean { ... } } https://github.com/ivanisidrowu/KtRssReader/blob/master/processor/src/main/java/tw/ktrssreader/processor/RssAnnotationProcessor.kt Annotation Processor 25
• 如果我要做多個不同用途的 annotation processor ,該怎麼辦? ◦ 創不同的 module ▪ 分包讓使用者
load 進去 ◦ 有共用邏輯的話,可以用 kapt arguments kapt { arguments { arg("pureKotlinParser", true) } } val isPureKotlinParser = processingEnv.options["pureKotlinParser"]?.toBoolean() ?: false Annotation Processor 26
• 實作各種不同的 generator ◦ Kotlin ▪ KotlinParserGenerator.kt ▪ KotlinExtensionGenerator.kt ◦
Android ▪ AndroidReaderGenerator.kt ▪ AndroidParserGenerator.kt ▪ AndroidExtensionGenerator.kt Annotation Processor 27
• Processor 給的 javax.lang.model.element.Element ◦ 包含的節點資訊 ▪ Name ▪ Annotation
▪ 鄰居節點資訊 ▪ Type ▪ Tag 資訊 (tag, attribute, value 等) Annotation Processor 28
• 我們處理節點資訊的步驟 a. 從 Element 獲取資訊 b. 預處理節點資訊 c. 產生
Kotlin 檔案 Get Data from Element Pre-process Data Generate Kotlin files Annotation Processor 29
• 接著就可以開始用 Kotlin Poet 產生檔案了! Annotation Processor 30
• 很多種方式可以發佈 ◦ bintray、gradle plugin 上 Maven Central 等等 ◦
JitPack • JitPack ◦ 不麻煩 ◦ 快 • Release 後,請一定要先試過一次 ! ◦ 不然就會遇到問題 程式碼發佈方式 31
• 使用 KSP (Kotlin Symbol Processing) 取代 KAPT ◦ 據說速度可達兩倍之快
▪ 因為 KAPT 中間會先生成 Java Stub • Kotlin Fetcher & Cache • 支援 Kotlin 跨平台 KMM 未來方向 32
• Android Weekly • Android Arsenal • 安卓開發技術週報 • 社群網站(Facebook
社團) • 技術分享 Meetup 宣傳管道 33
謝謝大家! 34 KtRssReader KtRssReader