Bladeren bron

Refactor: remove interfaces

cooperku_kdanmobile 5 jaren geleden
bovenliggende
commit
26b1231001

+ 1 - 2
src/main/java/com/kdanmobile/reader/ReaderViewModel.kt

@@ -34,7 +34,6 @@ import com.kdanmobile.reader.screen.data.StampAttribute
 import com.kdanmobile.reader.screen.data.TextBoxAttribute
 import com.kdanmobile.reader.screen.handler.*
 import com.kdanmobile.reader.additionalpage.AdditionalPageManager
-import com.kdanmobile.reader.additionalpage.AdditionalPageManagerImpl
 import java.io.File
 import java.util.*
 import kotlin.collections.ArrayList
@@ -208,7 +207,7 @@ class ReaderViewModel(
 
     private var onClickLinkListener: OnClickLinkListener? = null
 
-    var additionalPageManager: AdditionalPageManager = AdditionalPageManagerImpl().also {
+    var additionalPageManager: AdditionalPageManager = AdditionalPageManager().also {
         readerModel.initAdditionalPageManager(it)
     }
         set(value) {

+ 64 - 9
src/main/java/com/kdanmobile/reader/additionalpage/AdditionalPageConverter.kt

@@ -1,5 +1,7 @@
 package com.kdanmobile.reader.additionalpage
 
+import androidx.annotation.IntRange
+import com.kdanmobile.kmpdfkit.globaldata.Config
 import com.kdanmobile.kmpdfkit.manager.controller.KMPDFDocumentController
 
 /**
@@ -11,42 +13,95 @@ import com.kdanmobile.kmpdfkit.manager.controller.KMPDFDocumentController
  *
  * 預設在原始文件的每頁之間都插入額外頁面,因此每隔一頁都可以插入一個廣告
  */
-interface AdditionalPageConverter {
+class AdditionalPageConverter(
+        //  原始文件每隔幾頁是「額外頁面」
+        @IntRange(from = 1) private val additionalPageInterval: Int = DEFAULT_ADDITIONAL_PAGE_INTERVAL,
+        //  第一個額外頁面至少是從原始文件第幾頁開始
+        @IntRange(from = 1) private val firstAdditionalPageIndex: Int = DEFAULT_FIRST_ADDITIONAL_PAGE_INDEX
+) {
 
-    var kmpdfDocumentController: KMPDFDocumentController?
+    companion object {
+        //  原始文件每隔幾頁是「額外頁面」
+        const val DEFAULT_ADDITIONAL_PAGE_INTERVAL = 1
+        //  第一個額外頁面至少是從原始文件第幾頁開始
+        const val DEFAULT_FIRST_ADDITIONAL_PAGE_INDEX = 1
+    }
+
+    var kmpdfDocumentController: KMPDFDocumentController? = null
 
     /**
      * 是否啟用額外頁面(例:已訂閱則不顯示)
      */
-    var isAdditionalPageEnabled: () -> Boolean
+    var isAdditionalPageEnabled: () -> Boolean = { true }
 
     /**
      * 判斷文件第pageIndex頁是否是額外頁面
      */
-    fun isAdditionalPage(pageIndex: Int): Boolean
+    fun isAdditionalPage(pageIndex: Int): Boolean {
+        if (!shouldApplyAdditionalPage()) return false
+        if (pageIndex < firstAdditionalPageIndex) return false
+        return (pageIndex - firstAdditionalPageIndex) % (additionalPageInterval + 1) == 0
+    }
 
     /**
      * 頁碼轉換,計算原始文件的第rawPageIndex頁在插入額外頁面後是第幾頁
      */
-    fun convertToPageIndex(rawPageIndex: Int): Int
+    fun convertToPageIndex(rawPageIndex: Int): Int {
+        if (!shouldApplyAdditionalPage()) return rawPageIndex
+        if (rawPageIndex < firstAdditionalPageIndex) return rawPageIndex
+        return rawPageIndex + 1 + (rawPageIndex - firstAdditionalPageIndex) / additionalPageInterval
+    }
 
     /**
      * 頁碼轉換,計算第pageIndex頁刪除額外頁面後是原始文件的第幾頁
      */
-    fun convertToRawPageIndex(pageIndex: Int): Int
+    fun convertToRawPageIndex(pageIndex: Int): Int {
+        if (!shouldApplyAdditionalPage()) return pageIndex
+        if (pageIndex < firstAdditionalPageIndex) return pageIndex
+        return (pageIndex * additionalPageInterval + firstAdditionalPageIndex) / (additionalPageInterval + 1)
+    }
 
     /**
      * 取得包含額外頁面的總頁數
      */
-    fun getPageCount(isNativeRefresh: Boolean = false): Int
+    fun getPageCount(isNativeRefresh: Boolean = false): Int {
+        val rawPageCount = getRawPageCount(isNativeRefresh)
+        if (!shouldApplyAdditionalPage()) return rawPageCount
+        val pageCount = convertToPageIndex(rawPageCount)
+        val lastPage = pageCount - 1
+        //  最後一頁不能是額外頁面
+        return when (isAdditionalPage(lastPage)) {
+            true -> pageCount - 1
+            false -> pageCount
+        }
+    }
 
     /**
      * 取得原始文件的總頁數
      */
-    fun getRawPageCount(isNativeRefresh: Boolean = false): Int
+    fun getRawPageCount(isNativeRefresh: Boolean = false): Int {
+        return kmpdfDocumentController?.getDocumentPageCount(isNativeRefresh) ?: 0
+    }
 
     /**
      * 取得當前顯示頁面的頁碼
      */
-    fun getCurrentPage(): Int
+    fun getCurrentPage(): Int {
+        return kmpdfDocumentController?.currentPageNum ?: 0
+    }
+
+    /**
+     * 是否套用額外頁面(非垂直閱覽模式則不套用)
+     */
+
+    private fun shouldApplyAdditionalPage(): Boolean {
+        return isAdditionalPageEnabled.invoke() && isVerticalContinuesViewMode()
+    }
+
+    /**
+     * 是否是垂直閱覽模式
+     */
+    private fun isVerticalContinuesViewMode(): Boolean {
+        return kmpdfDocumentController?.pdfViewMode == Config.PDFViewMode.VERTICAL_SINGLE_PAGE_CONTINUES
+    }
 }

+ 0 - 107
src/main/java/com/kdanmobile/reader/additionalpage/AdditionalPageConverterImpl.kt

@@ -1,107 +0,0 @@
-package com.kdanmobile.reader.additionalpage
-
-import androidx.annotation.IntRange
-import com.kdanmobile.kmpdfkit.globaldata.Config
-import com.kdanmobile.kmpdfkit.manager.controller.KMPDFDocumentController
-
-/**
- * 額外頁面頁碼轉換器
- * 以及判斷哪些頁面是額外頁面
- *
- * <名詞解釋>
- *     額外頁面:在原始文件之間插入的空頁面,之後可在其上插入其他內容(例如廣告)
- *
- * 預設在原始文件的每頁之間都插入額外頁面,因此每隔一頁都可以插入一個廣告
- */
-class AdditionalPageConverterImpl(
-        //  原始文件每隔幾頁是「額外頁面」
-        @IntRange(from = 1) private val additionalPageInterval: Int = DEFAULT_ADDITIONAL_PAGE_INTERVAL,
-        //  第一個額外頁面至少是從原始文件第幾頁開始
-        @IntRange(from = 1) private val firstAdditionalPageIndex: Int = DEFAULT_FIRST_ADDITIONAL_PAGE_INDEX
-) : AdditionalPageConverter {
-
-    companion object {
-        //  原始文件每隔幾頁是「額外頁面」
-        const val DEFAULT_ADDITIONAL_PAGE_INTERVAL = 1
-        //  第一個額外頁面至少是從原始文件第幾頁開始
-        const val DEFAULT_FIRST_ADDITIONAL_PAGE_INDEX = 1
-    }
-
-    override var kmpdfDocumentController: KMPDFDocumentController? = null
-
-    /**
-     * 是否啟用額外頁面(例:已訂閱則不顯示)
-     */
-    override var isAdditionalPageEnabled: () -> Boolean = { true }
-
-    /**
-     * 判斷文件第pageIndex頁是否是額外頁面
-     */
-    override fun isAdditionalPage(pageIndex: Int): Boolean {
-        if (!shouldApplyAdditionalPage()) return false
-        if (pageIndex < firstAdditionalPageIndex) return false
-        return (pageIndex - firstAdditionalPageIndex) % (additionalPageInterval + 1) == 0
-    }
-
-    /**
-     * 頁碼轉換,計算原始文件的第rawPageIndex頁在插入額外頁面後是第幾頁
-     */
-    override fun convertToPageIndex(rawPageIndex: Int): Int {
-        if (!shouldApplyAdditionalPage()) return rawPageIndex
-        if (rawPageIndex < firstAdditionalPageIndex) return rawPageIndex
-        return rawPageIndex + 1 + (rawPageIndex - firstAdditionalPageIndex) / additionalPageInterval
-    }
-
-    /**
-     * 頁碼轉換,計算第pageIndex頁刪除額外頁面後是原始文件的第幾頁
-     */
-    override fun convertToRawPageIndex(pageIndex: Int): Int {
-        if (!shouldApplyAdditionalPage()) return pageIndex
-        if (pageIndex < firstAdditionalPageIndex) return pageIndex
-        return (pageIndex * additionalPageInterval + firstAdditionalPageIndex) / (additionalPageInterval + 1)
-    }
-
-    /**
-     * 取得包含額外頁面的總頁數
-     */
-    override fun getPageCount(isNativeRefresh: Boolean): Int {
-        val rawPageCount = getRawPageCount(isNativeRefresh)
-        if (!shouldApplyAdditionalPage()) return rawPageCount
-        val pageCount = convertToPageIndex(rawPageCount)
-        val lastPage = pageCount - 1
-        //  最後一頁不能是額外頁面
-        return when (isAdditionalPage(lastPage)) {
-            true -> pageCount - 1
-            false -> pageCount
-        }
-    }
-
-    /**
-     * 取得原始文件的總頁數
-     */
-    override fun getRawPageCount(isNativeRefresh: Boolean): Int {
-        return kmpdfDocumentController?.getDocumentPageCount(isNativeRefresh) ?: 0
-    }
-
-    /**
-     * 取得當前顯示頁面的頁碼
-     */
-    override fun getCurrentPage(): Int {
-        return kmpdfDocumentController?.currentPageNum ?: 0
-    }
-
-    /**
-     * 是否套用額外頁面(非垂直閱覽模式則不套用)
-     */
-
-    private fun shouldApplyAdditionalPage(): Boolean {
-        return isAdditionalPageEnabled.invoke() && isVerticalContinuesViewMode()
-    }
-
-    /**
-     * 是否是垂直閱覽模式
-     */
-    private fun isVerticalContinuesViewMode(): Boolean {
-        return kmpdfDocumentController?.pdfViewMode == Config.PDFViewMode.VERTICAL_SINGLE_PAGE_CONTINUES
-    }
-}

+ 51 - 5
src/main/java/com/kdanmobile/reader/additionalpage/AdditionalPageDisplayStrategy.kt

@@ -1,23 +1,69 @@
 package com.kdanmobile.reader.additionalpage
 
 import android.util.SparseBooleanArray
+import androidx.annotation.IntRange
+import kotlin.math.abs
 
 /**
  * 額外頁面顯示策略
  * 額外頁面創建成功後,需符合當前顯示策略類型時才會顯示該額外頁面
  */
-interface AdditionalPageDisplayStrategy {
+class AdditionalPageDisplayStrategy(
+        var displayStrategyType: AdditionalPageDisplayStrategyType = AdditionalPageDisplayStrategyType.PAGE_INTERVAL,
+        //  至少每隔幾頁(包含額外頁面)才可以顯示廣告
+        @IntRange(from = 4) private val pageInterval: Int = DEFAULT_PAGE_INTERVAL,
+        //  至少每隔幾秒才可以顯示廣告
+        @IntRange(from = 5) private val timeInterval: Int = DEFAULT_TIME_INTERVAL
+) {
 
-    //  額外頁面顯示策略類型
-    var displayStrategyType: AdditionalPageDisplayStrategyType
+    companion object {
+        //  至少每隔幾頁(包含額外頁面)才可以顯示廣告,預設值4即表示每隔至少原始文件2頁才可以顯示廣告
+        const val DEFAULT_PAGE_INTERVAL = 4
+        //  至少每隔幾秒才可以顯示廣告
+        const val DEFAULT_TIME_INTERVAL = 5
+    }
+
+    /**
+     * 額外頁面最後顯示時間,與「TIME_INTERVAL」相關的顯示策略會使用到此變數
+     */
+    private var lastDisplayTime = System.currentTimeMillis()
 
     /**
      * 判斷第position頁是否能顯示額外頁面
      */
-    fun canDisplayAdditionalPageAt(additionalPageVisibleSet: SparseBooleanArray, position: Int): Boolean
+    fun canDisplayAdditionalPageAt(additionalPageVisibleSet: SparseBooleanArray, position: Int): Boolean {
+        return when (displayStrategyType) {
+            AdditionalPageDisplayStrategyType.HIDE -> false
+            AdditionalPageDisplayStrategyType.PAGE_INTERVAL -> isPageStrategyValid(additionalPageVisibleSet, position)
+            AdditionalPageDisplayStrategyType.TIME_INTERVAL -> isTimeStrategyValid()
+            AdditionalPageDisplayStrategyType.PAGE_OR_TIME_INTERVAL -> isPageStrategyValid(additionalPageVisibleSet, position) || isTimeStrategyValid()
+            AdditionalPageDisplayStrategyType.PAGE_AND_TIME_INTERVAL -> isPageStrategyValid(additionalPageVisibleSet, position) && isTimeStrategyValid()
+        }
+    }
+
+    /**
+     * 判斷是否符合「PAGE_INTERVAL」顯示策略
+     */
+    private fun isPageStrategyValid(additionalPageVisibleSet: SparseBooleanArray, pageIndex: Int): Boolean {
+        for (index in 0 until additionalPageVisibleSet.size()) {
+            if (abs(pageIndex - additionalPageVisibleSet.keyAt(index)) < pageInterval) {
+                return false
+            }
+        }
+        return true
+    }
+
+    /**
+     * 判斷是否符合「TIME_INTERVAL」顯示策略
+     */
+    private fun isTimeStrategyValid(): Boolean {
+        return System.currentTimeMillis() - lastDisplayTime >= timeInterval * 1000L
+    }
 
     /**
      * 更新最後顯示時間
      */
-    fun updateDisplayTime()
+    fun updateDisplayTime() {
+        lastDisplayTime = System.currentTimeMillis()
+    }
 }

+ 0 - 69
src/main/java/com/kdanmobile/reader/additionalpage/AdditionalPageDisplayStrategyImpl.kt

@@ -1,69 +0,0 @@
-package com.kdanmobile.reader.additionalpage
-
-import android.util.SparseBooleanArray
-import androidx.annotation.IntRange
-import kotlin.math.abs
-
-/**
- * 額外頁面顯示策略
- * 額外頁面創建成功後,需符合當前顯示策略類型時才會顯示該額外頁面
- */
-class AdditionalPageDisplayStrategyImpl(
-        override var displayStrategyType: AdditionalPageDisplayStrategyType = AdditionalPageDisplayStrategyType.PAGE_INTERVAL,
-        //  至少每隔幾頁(包含額外頁面)才可以顯示廣告
-        @IntRange(from = 4) private val pageInterval: Int = DEFAULT_PAGE_INTERVAL,
-        //  至少每隔幾秒才可以顯示廣告
-        @IntRange(from = 5) private val timeInterval: Int = DEFAULT_TIME_INTERVAL
-) : AdditionalPageDisplayStrategy {
-
-    companion object {
-        //  至少每隔幾頁(包含額外頁面)才可以顯示廣告,預設值4即表示每隔至少原始文件2頁才可以顯示廣告
-        const val DEFAULT_PAGE_INTERVAL = 4
-        //  至少每隔幾秒才可以顯示廣告
-        const val DEFAULT_TIME_INTERVAL = 5
-    }
-
-    /**
-     * 額外頁面最後顯示時間,與「TIME_INTERVAL」相關的顯示策略會使用到此變數
-     */
-    private var lastDisplayTime = System.currentTimeMillis()
-
-    /**
-     * 判斷第position頁是否能顯示額外頁面
-     */
-    override fun canDisplayAdditionalPageAt(additionalPageVisibleSet: SparseBooleanArray, position: Int): Boolean {
-        return when (displayStrategyType) {
-            AdditionalPageDisplayStrategyType.HIDE -> false
-            AdditionalPageDisplayStrategyType.PAGE_INTERVAL -> isPageStrategyValid(additionalPageVisibleSet, position)
-            AdditionalPageDisplayStrategyType.TIME_INTERVAL -> isTimeStrategyValid()
-            AdditionalPageDisplayStrategyType.PAGE_OR_TIME_INTERVAL -> isPageStrategyValid(additionalPageVisibleSet, position) || isTimeStrategyValid()
-            AdditionalPageDisplayStrategyType.PAGE_AND_TIME_INTERVAL -> isPageStrategyValid(additionalPageVisibleSet, position) && isTimeStrategyValid()
-        }
-    }
-
-    /**
-     * 判斷是否符合「PAGE_INTERVAL」顯示策略
-     */
-    private fun isPageStrategyValid(additionalPageVisibleSet: SparseBooleanArray, pageIndex: Int): Boolean {
-        for (index in 0 until additionalPageVisibleSet.size()) {
-            if (abs(pageIndex - additionalPageVisibleSet.keyAt(index)) < pageInterval) {
-                return false
-            }
-        }
-        return true
-    }
-
-    /**
-     * 判斷是否符合「TIME_INTERVAL」顯示策略
-     */
-    private fun isTimeStrategyValid(): Boolean {
-        return System.currentTimeMillis() - lastDisplayTime >= timeInterval * 1000L
-    }
-
-    /**
-     * 更新最後顯示時間
-     */
-    override fun updateDisplayTime() {
-        lastDisplayTime = System.currentTimeMillis()
-    }
-}

+ 86 - 11
src/main/java/com/kdanmobile/reader/additionalpage/AdditionalPageManager.kt

@@ -1,5 +1,9 @@
 package com.kdanmobile.reader.additionalpage
 
+import android.util.SparseBooleanArray
+import androidx.annotation.IntRange
+import kotlin.math.abs
+
 /**
  * 額外頁面管理員
  * 判斷哪些頁面是額外頁面、是否該顯示額外頁面
@@ -7,13 +11,16 @@ package com.kdanmobile.reader.additionalpage
  * <名詞解釋>
  *     額外頁面:在原始文件之間插入的空頁面,之後可在其上插入其他內容(例如廣告)
  */
-interface AdditionalPageManager {
-
-    //  額外頁面頁碼轉換器
-    val pageConverter: AdditionalPageConverter
+class AdditionalPageManager(
+        val pageConverter: AdditionalPageConverter = AdditionalPageConverter(),
+        val displayStrategy: AdditionalPageDisplayStrategy = AdditionalPageDisplayStrategy(),
+        @IntRange(from = 3) private val nextInterval: Int = DEFAULT_NEXT_INTERVAL
+) {
 
-    //  額外頁面顯示策略
-    val displayStrategy: AdditionalPageDisplayStrategy
+    companion object {
+        //  當前頁面改變後,前後第N頁該顯示額外頁面
+        const val DEFAULT_NEXT_INTERVAL = 3
+    }
 
     //  額外頁面顯示策略類型
     var displayStrategyType: AdditionalPageDisplayStrategyType
@@ -24,29 +31,97 @@ interface AdditionalPageManager {
             displayStrategy.displayStrategyType = value
         }
 
+    /**
+     * 記錄額外頁面頁碼與其是否可見
+     */
+    private val additionalPageVisibleSet = SparseBooleanArray()
+
+    /**
+     * 記錄哪些額外頁面是隱藏不可見
+     */
+    private val hiddenAdditionalPageSet = HashSet<Int>()
+
     /**
      * 請求額外頁面
      */
-    var requestAdditionalPage: (position: Int) -> Unit
+    var requestAdditionalPage: (position: Int) -> Unit = {}
 
     /**
      * 判斷額外頁面是否讀取完畢
      */
-    var isAdditionalPageLoaded: (position: Int) -> Boolean
+    var isAdditionalPageLoaded: (position: Int) -> Boolean = {
+        false
+    }
+
+    init {
+        pageConverter.isAdditionalPageEnabled = {
+            displayStrategyType != AdditionalPageDisplayStrategyType.HIDE
+        }
+    }
 
     /**
      * 判斷第position頁是否是額外頁面,並且該額外頁面是否可見
      */
-    fun isAdditionalPageVisible(position: Int): Boolean
+    fun isAdditionalPageVisible(position: Int): Boolean {
+        return pageConverter.isAdditionalPage(position) && additionalPageVisibleSet[position]
+    }
+
+    /**
+     * 判斷第position頁是否可顯示額外頁面
+     * 若是滿足以下任意條件則不可顯示額外頁面:
+     * .該頁不是額外頁面
+     * .該頁在可視範圍內(與當前頁差距小於nextInterval頁)
+     * .頁碼超過文件範圍
+     */
+    private fun canDisplayAdditionalPageAt(position: Int): Boolean {
+        return when {
+            !pageConverter.isAdditionalPage(position) -> false
+            abs(position - pageConverter.getCurrentPage()) < nextInterval -> false
+            position < 0 || position >= pageConverter.getPageCount() -> false
+            else -> true
+        }
+    }
 
     /**
      * 當前頁面更新時呼叫此方法
      * 判斷哪幾頁應請求/顯示額外頁面
      */
-    fun onPageChanged(position: Int)
+    fun onPageChanged(position: Int) {
+        //  若不該顯示額外頁面則停止執行
+        if (!pageConverter.isAdditionalPageEnabled.invoke()) return
+
+        for (dir in -1 .. 1 step 2) {
+            //  判斷position的前後第nextInterval頁
+            val targetPosition = position + nextInterval * dir
+            //  是否可顯示額外頁面
+            val isValid = displayStrategy.canDisplayAdditionalPageAt(additionalPageVisibleSet, targetPosition)
+            val isHidden = hiddenAdditionalPageSet.contains(targetPosition)
+            if (isValid && !isHidden) {
+                //  該額外頁面是否請求成功
+                if (isAdditionalPageLoaded.invoke(targetPosition)) {
+                    //  若該位置可顯示額外頁面
+                    if (canDisplayAdditionalPageAt(targetPosition)) {
+                        //  顯示額外頁面
+                        additionalPageVisibleSet.put(targetPosition, true)
+                        //  更新最後顯示時間
+                        displayStrategy.updateDisplayTime()
+                    }
+                } else {
+                    requestAdditionalPage.invoke(targetPosition)
+                }
+            }
+        }
+    }
 
     /**
      * 隱藏額外頁面
      */
-    fun tryToHideAdditionalPageAt(position: Int): Boolean
+    fun tryToHideAdditionalPageAt(position: Int): Boolean {
+        if (!pageConverter.isAdditionalPage(position)) return false
+        //  移除該額外頁面
+        additionalPageVisibleSet.put(position, false)
+        //  紀錄為隱藏狀態
+        hiddenAdditionalPageSet.add(position)
+        return true
+    }
 }

+ 0 - 118
src/main/java/com/kdanmobile/reader/additionalpage/AdditionalPageManagerImpl.kt

@@ -1,118 +0,0 @@
-package com.kdanmobile.reader.additionalpage
-
-import android.util.SparseBooleanArray
-import androidx.annotation.IntRange
-import kotlin.math.abs
-
-/**
- * 額外頁面管理員
- * 判斷哪些頁面是額外頁面、是否該顯示額外頁面
- *
- * <名詞解釋>
- *     額外頁面:在原始文件之間插入的空頁面,之後可在其上插入其他內容(例如廣告)
- */
-class AdditionalPageManagerImpl(
-        override val pageConverter: AdditionalPageConverter = AdditionalPageConverterImpl(),
-        override val displayStrategy: AdditionalPageDisplayStrategy = AdditionalPageDisplayStrategyImpl(),
-        @IntRange(from = 3) private val nextInterval: Int = DEFAULT_NEXT_INTERVAL
-) : AdditionalPageManager {
-
-    companion object {
-        //  當前頁面改變後,前後第N頁該顯示額外頁面
-        const val DEFAULT_NEXT_INTERVAL = 3
-    }
-
-    /**
-     * 記錄額外頁面頁碼與其是否可見
-     */
-    private val additionalPageVisibleSet = SparseBooleanArray()
-
-    /**
-     * 記錄哪些額外頁面是隱藏不可見
-     */
-    private val hiddenAdditionalPageSet = HashSet<Int>()
-
-    /**
-     * 請求額外頁面
-     */
-    override var requestAdditionalPage: (position: Int) -> Unit = {}
-
-    /**
-     * 判斷額外頁面是否讀取完畢
-     */
-    override var isAdditionalPageLoaded: (position: Int) -> Boolean = {
-        false
-    }
-
-    init {
-        pageConverter.isAdditionalPageEnabled = {
-            displayStrategyType != AdditionalPageDisplayStrategyType.HIDE
-        }
-    }
-
-    /**
-     * 判斷第position頁是否是額外頁面,並且該額外頁面是否可見
-     */
-    override fun isAdditionalPageVisible(position: Int): Boolean {
-        return pageConverter.isAdditionalPage(position) && additionalPageVisibleSet[position]
-    }
-
-    /**
-     * 判斷第position頁是否可顯示額外頁面
-     * 若是滿足以下任意條件則不可顯示額外頁面:
-     * .該頁不是額外頁面
-     * .該頁在可視範圍內(與當前頁差距小於nextInterval頁)
-     * .頁碼超過文件範圍
-     */
-    private fun canDisplayAdditionalPageAt(position: Int): Boolean {
-        return when {
-            !pageConverter.isAdditionalPage(position) -> false
-            abs(position - pageConverter.getCurrentPage()) < nextInterval -> false
-            position < 0 || position >= pageConverter.getPageCount() -> false
-            else -> true
-        }
-    }
-
-    /**
-     * 當前頁面更新時呼叫此方法
-     * 判斷哪幾頁應請求/顯示額外頁面
-     */
-    override fun onPageChanged(position: Int) {
-        //  若不該顯示額外頁面則停止執行
-        if (!pageConverter.isAdditionalPageEnabled.invoke()) return
-
-        for (dir in -1 .. 1 step 2) {
-            //  判斷position的前後第nextInterval頁
-            val targetPosition = position + nextInterval * dir
-            //  是否可顯示額外頁面
-            val isValid = displayStrategy.canDisplayAdditionalPageAt(additionalPageVisibleSet, targetPosition)
-            val isHidden = hiddenAdditionalPageSet.contains(targetPosition)
-            if (isValid && !isHidden) {
-                //  該額外頁面是否請求成功
-                if (isAdditionalPageLoaded.invoke(targetPosition)) {
-                    //  若該位置可顯示額外頁面
-                    if (canDisplayAdditionalPageAt(targetPosition)) {
-                        //  顯示額外頁面
-                        additionalPageVisibleSet.put(targetPosition, true)
-                        //  更新最後顯示時間
-                        displayStrategy.updateDisplayTime()
-                    }
-                } else {
-                    requestAdditionalPage.invoke(targetPosition)
-                }
-            }
-        }
-    }
-
-    /**
-     * 隱藏額外頁面
-     */
-    override fun tryToHideAdditionalPageAt(position: Int): Boolean {
-        if (!pageConverter.isAdditionalPage(position)) return false
-        //  移除該額外頁面
-        additionalPageVisibleSet.put(position, false)
-        //  紀錄為隱藏狀態
-        hiddenAdditionalPageSet.add(position)
-        return true
-    }
-}