diff --git a/.gitignore b/.gitignore
index c6cbe56..358c91e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,5 @@
.DS_Store
/build
/captures
+
+/.idea/
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..61a9130
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml
new file mode 100644
index 0000000..b268ef3
--- /dev/null
+++ b/.idea/deploymentTargetSelector.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 4441641..169b7a4 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -1,10 +1,12 @@
+
-
+
+
@@ -12,7 +14,7 @@
-
+
diff --git a/.idea/migrations.xml b/.idea/migrations.xml
new file mode 100644
index 0000000..f8051a6
--- /dev/null
+++ b/.idea/migrations.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3179ac3..45f42ee 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,11 +1,10 @@
-
-
+
@@ -13,21 +12,35 @@
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 078a3cb..3caa711 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -2,9 +2,15 @@
-
-
-
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
deleted file mode 100644
index 7f68460..0000000
--- a/.idea/runConfigurations.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 311100e..1cd1f10 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -4,7 +4,6 @@ apply plugin: 'org.greenrobot.greendao'
android {
compileSdkVersion 28
buildToolsVersion '28.0.3'
-
defaultConfig {
applicationId "com.monke.monkeybook"
minSdkVersion 17
diff --git a/app/src/main/java/com/monke/monkeybook/common/RxBusTag.java b/app/src/main/java/com/monke/monkeybook/common/RxBusTag.java
index 22a3afa..d317255 100644
--- a/app/src/main/java/com/monke/monkeybook/common/RxBusTag.java
+++ b/app/src/main/java/com/monke/monkeybook/common/RxBusTag.java
@@ -1,25 +1,25 @@
-//Copyright (c) 2017. 章钦豪. All rights reserved.
+//定义当前类所在的包路径为"com.monke.monkeybook.common",表明它属于"monkeybook"项目的公共部分
package com.monke.monkeybook.common;
-
+//定义一个名为 RxBusTag 的公共类,包含一组常量字符串,用于标识RxBus事件
public class RxBusTag {
-
+ //定义一个静态常量字符串,表示添加书籍的事件
public final static String HAD_ADD_BOOK = "rxbus_add_book";
-
+ //定义一个静态常量字符串,表示移除书籍的事件
public final static String HAD_REMOVE_BOOK = "rxbus_remove_book";
-
+ //定义一个静态常量字符串,表示更新书籍进度的事件
public final static String UPDATE_BOOK_PROGRESS = "rxbus_update_book_progress";
-
+ //定义一个静态常量字符串,表示暂停下载的监听事件
public final static String PAUSE_DOWNLOAD_LISTENER = "rxbus_pause_download_listener";
-
+ //定义一个静态常量字符串,表示下载进度监听事件
public final static String PROGRESS_DOWNLOAD_LISTENER = "rxbus_progress_download_listener";
-
+ //定义一个静态常量字符串,表示下载完成监听事件
public final static String FINISH_DOWNLOAD_LISTENER = "rxbus_finish_download_listener";
-
+ //定义一个静态常量字符串,表示暂停下载的事件
public final static String PAUSE_DOWNLOAD = "rxbus_pause_download";
-
+ //定义一个静态常量字符串,表示开始下载的事件
public final static String START_DOWNLOAD = "rxbus_start_download";
-
+ //定义一个静态常量字符串,表示取消下载的事件
public final static String CANCEL_DOWNLOAD = "rxbus_cancel_download";
-
+ //定义一个静态常量字符串,表示添加下载任务的事件
public final static String ADD_DOWNLOAD_TASK = "rxbus_add_download_task";
}
diff --git a/app/src/main/java/com/monke/monkeybook/common/api/IEasouApi.java b/app/src/main/java/com/monke/monkeybook/common/api/IEasouApi.java
index c631ded..90aeb92 100644
--- a/app/src/main/java/com/monke/monkeybook/common/api/IEasouApi.java
+++ b/app/src/main/java/com/monke/monkeybook/common/api/IEasouApi.java
@@ -1,44 +1,59 @@
-//Copyright (c) 2017. 章钦豪. All rights reserved.
+//定义当前接口所在的包 com.monke.monkeybook.common.api
+//这个包路径表示该接口用于应用程序的公共API部分。
package com.monke.monkeybook.common.api;
-
-import io.reactivex.Observable;
-import retrofit2.http.GET;
-import retrofit2.http.Headers;
-import retrofit2.http.Url;
+//引入所需要的库
+import io.reactivex.Observable; //导入Observable类,这是RxJava中的一个核心类,表示一个可以发射数据的流
+import retrofit2.http.GET; //导入Retrofit中的GET注解,用于表示一个HTTP GET请求
+import retrofit2.http.Headers; //导入Retrofit中的Headers注解,用于向HTTP请求添加自定义头部信息。
+import retrofit2.http.Url; //导入Retrofit中的Url注解,用于动态传递URL。
/**
* 宜搜小说API (质量太差 废弃)
*/
+//定义一个接口IEasouApi,该接口包含了一些方法,用于与宜搜小说的API进行交互。
public interface IEasouApi {
- @GET
- @Headers({"Accept:text/html,application/xhtml+xml,application/xml",
- "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3",
- "Accept-Charset:UTF-8",
- "Connection:close",
- "Cache-Control:no-cache"})
+ //定义获取书籍信息的方法,通过HTTP GET请求,并添加自定义请求头
+ @GET //定义GET请求
+ //设置请求头
+ @Headers({"Accept:text/html,application/xhtml+xml,application/xml", //请求头:表示支持的响应类型
+ "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", //设置User-Agent,模拟浏览器请求
+ "Accept-Charset:UTF-8", //请求头:指定字符集为 UTF-8
+ "Connection:close", //请求头:请求完成后关闭连接
+ "Cache-Control:no-cache"}) //禁用缓存
+ //返回值为Observable,这是一个异步操作,最后会返回一个String类型的数据流
+ //@Url表示该方法接收一个动态URL作为参数
Observable getBookInfo(@Url String url);
- @GET
- @Headers({"Accept:text/html,application/xhtml+xml,application/xml",
- "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3",
- "Accept-Charset:UTF-8",
- "Connection:close",
- "Cache-Control:no-cache"})
+ //定义搜索书籍的方法,类似getBookInfo
+ @GET //定义GET请求
+ //设置请求头
+ @Headers({"Accept:text/html,application/xhtml+xml,application/xml", //请求头:表示支持的响应类型
+ "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", //设置User-Agent,模拟浏览器请求
+ "Accept-Charset:UTF-8", //请求头:指定字符集为 UTF-8
+ "Connection:close", //请求头:请求完成后关闭连接
+ "Cache-Control:no-cache"}) //禁用缓存
+ //该方法接受动态URL,返回书籍搜索结果
Observable searchBook(@Url String url);
- @GET
- @Headers({"Accept:text/html,application/xhtml+xml,application/xml",
- "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3",
- "Accept-Charset:UTF-8",
- "Connection:close",
- "Cache-Control:no-cache"})
+ //定义获取书籍内容的方法,类似前两个方法
+ @GET //定义GET请求
+ //设置请求头
+ @Headers({"Accept:text/html,application/xhtml+xml,application/xml", //请求头:表示支持的响应类型
+ "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", //设置User-Agent,模拟浏览器请求
+ "Accept-Charset:UTF-8", //请求头:指定字符集为 UTF-8
+ "Connection:close", //请求头:请求完成后关闭连接
+ "Cache-Control:no-cache"}) //禁用缓存
+ //该方法获取书籍的内容,通过URL传递获取内容的地址
Observable getBookContent(@Url String url);
- @GET
- @Headers({"Accept:text/html,application/xhtml+xml,application/xml",
- "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3",
- "Accept-Charset:UTF-8",
- "Connection:close",
- "Cache-Control:no-cache"})
+ //定义获取章节列表的方法,同样类似上述方法
+ @GET //定义GET请求
+ //设置请求头
+ @Headers({"Accept:text/html,application/xhtml+xml,application/xml", //请求头:表示支持的响应类型
+ "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", //设置User-Agent,模拟浏览器请求
+ "Accept-Charset:UTF-8", //请求头:指定字符集为 UTF-8
+ "Connection:close", //请求头:请求完成后关闭连接
+ "Cache-Control:no-cache"}) //禁用缓存
+ //该方法获取书籍的章节列表,通过URL传递获取章节的地址
Observable getChapterList(@Url String url);
}
diff --git a/app/src/main/java/com/monke/monkeybook/common/api/IGxwztvApi.java b/app/src/main/java/com/monke/monkeybook/common/api/IGxwztvApi.java
index 16f1a8e..801dc20 100644
--- a/app/src/main/java/com/monke/monkeybook/common/api/IGxwztvApi.java
+++ b/app/src/main/java/com/monke/monkeybook/common/api/IGxwztvApi.java
@@ -1,61 +1,79 @@
-//Copyright (c) 2017. 章钦豪. All rights reserved.
+//定义包名,表明该接口属于 "monkeybook" 项目中的 API 部分
package com.monke.monkeybook.common.api;
+//引入所需的库
+import io.reactivex.Observable; //引入RxJava中的Observable,用于定义响应式流
+import retrofit2.http.Field; //引入Retrofit中的@Field 注解,用于表示POST请求中的表单字段
+import retrofit2.http.FormUrlEncoded; //引入Retrofit中的@FormUrlEncoded注解,用于标记表单请求
+import retrofit2.http.GET; //引入Retrofit中的@GET注解,用于定义GET请求
+import retrofit2.http.Headers; //引入Retrofit中的@Headers注解,用于添加HTTP请求头
+import retrofit2.http.Query; //引入Retrofit中的@Query注解,用于在URL中添加查询参数
+import retrofit2.http.Url; //引入Retrofit中的@Url注解,用于动态传递URL
-import io.reactivex.Observable;
-import retrofit2.http.Field;
-import retrofit2.http.FormUrlEncoded;
-import retrofit2.http.GET;
-import retrofit2.http.Headers;
-import retrofit2.http.Query;
-import retrofit2.http.Url;
-
+//该API接口定义了与小说网站进行交互的方法,用于获取书籍信息、搜索书籍、获取书籍内容等。
public interface IGxwztvApi {
-
- @GET
- @Headers({"Accept:text/html,application/xhtml+xml,application/xml",
- "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3",
- "Accept-Charset:UTF-8",
- "Connection:close",
- "Cache-Control:no-cache"})
+ //获取书籍信息的请求
+ @GET //定义GET请求
+ //设置请求头
+ @Headers({"Accept:text/html,application/xhtml+xml,application/xml", //设置请求头:接受的响应类型
+ "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", //设置User-Agent,模拟浏览器请求
+ "Accept-Charset:UTF-8", //设置字符集为 UTF-8
+ "Connection:close", //请求头:请求完成后关闭连接
+ "Cache-Control:no-cache"}) //禁用缓存
+ //该方法接收一个动态URL,返回Observable,表示异步的响应数据流
Observable getBookInfo(@Url String url);
- @GET("/search.htm")
- @Headers({"Accept:text/html,application/xhtml+xml,application/xml",
- "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3",
- "Accept-Charset:UTF-8",
- "Connection:close",
- "Cache-Control:no-cache"})
+ //搜索书籍的请求
+ @GET("/search.htm") //定义固定的GET,请求路径为"/search.htm"
+ //设置请求头
+ @Headers({"Accept:text/html,application/xhtml+xml,application/xml", //设置请求头:接受的响应类型
+ "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", //设置User-Agent,模拟浏览器请求
+ "Accept-Charset:UTF-8", //设置字符集为 UTF-8
+ "Connection:close", //请求头:请求完成后关闭连接
+ "Cache-Control:no-cache"}) //禁用缓存
+ //使用@Query注解传递查询参数,表示关键词和页码
Observable searchBook(@Query("keyword")String content, @Query("pn")int page);
- @GET
- @Headers({"Accept:text/html,application/xhtml+xml,application/xml",
- "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3",
- "Accept-Charset:UTF-8",
- "Connection:close",
- "Cache-Control:no-cache"})
+ //获取书籍内容的请求
+ @GET //定义GET请求
+ //设置请求头
+ @Headers({"Accept:text/html,application/xhtml+xml,application/xml", //请求头:表示支持的响应类型
+ "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", //设置User-Agent,模拟浏览器请求
+ "Accept-Charset:UTF-8", //设置字符集为 UTF-8
+ "Connection:close", //请求头:请求完成后关闭连接
+ "Cache-Control:no-cache"}) //禁用缓存
+ //该方法接收动态URL,返回书籍的内容
Observable getBookContent(@Url String url);
- @GET
- @Headers({"Accept:text/html,application/xhtml+xml,application/xml",
- "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3",
- "Accept-Charset:UTF-8",
- "Connection:close",
- "Cache-Control:no-cache"})
+ //获取章节列表的请求
+ @GET //定义GET请求
+ //设置请求头
+ @Headers({"Accept:text/html,application/xhtml+xml,application/xml", //请求头:表示支持的响应类型
+ "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", //设置User-Agent,模拟浏览器请求
+ "Accept-Charset:UTF-8", //设置字符集为 UTF-8
+ "Connection:close", //请求头:请求完成后关闭连接
+ "Cache-Control:no-cache"}) //禁用缓存
+ //该方法接收动态URL,返回章节列表
Observable getChapterList(@Url String url);
- @GET
- @Headers({"Accept:text/html,application/xhtml+xml,application/xml",
- "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3",
- "Accept-Charset:UTF-8",
- "Connection:close",
- "Cache-Control:no-cache"})
+ //获取书籍类型相关书籍的请求
+ @GET //定义GET请求
+ //设置请求头
+ @Headers({"Accept:text/html,application/xhtml+xml,application/xml", //请求头:表示支持的响应类型
+ "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", //设置User-Agent,模拟浏览器请求
+ "Accept-Charset:UTF-8", //设置字符集为 UTF-8
+ "Connection:close", //请求头:请求完成后关闭连接
+ "Cache-Control:no-cache"}) //禁用缓存
+ //该方法接收动态URL,返回该类型的书籍
Observable getKindBooks(@Url String url);
- @GET
- @Headers({"Accept:text/html,application/xhtml+xml,application/xml",
- "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3",
- "Accept-Charset:UTF-8",
- "Connection:close",
- "Cache-Control:no-cache"})
+ // 获取图书馆数据的请求
+ @GET //定义GET请求
+ //设置请求头
+ @Headers({"Accept:text/html,application/xhtml+xml,application/xml", //请求头:表示支持的响应类型
+ "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", //设置User-Agent,模拟浏览器请求
+ "Accept-Charset:UTF-8", //设置字符集为 UTF-8
+ "Connection:close", //请求头:请求完成后关闭连接
+ "Cache-Control:no-cache"}) //禁用缓存
+ //该方法接收动态URL,返回图书馆相关的数据
Observable getLibraryData(@Url String url);
}
diff --git a/app/src/main/java/com/monke/monkeybook/common/api/ILingdiankanshuApi.java b/app/src/main/java/com/monke/monkeybook/common/api/ILingdiankanshuApi.java
index af86c0e..66770f6 100644
--- a/app/src/main/java/com/monke/monkeybook/common/api/ILingdiankanshuApi.java
+++ b/app/src/main/java/com/monke/monkeybook/common/api/ILingdiankanshuApi.java
@@ -1,43 +1,54 @@
-//Copyright (c) 2017. 章钦豪. All rights reserved.
+//定义包路径,表示该接口属于"monkeybook"项目中的公共API部分
package com.monke.monkeybook.common.api;
+//引入所需的库
+import io.reactivex.Observable; //引入RxJava中的Observable类,表示异步流
+import retrofit2.http.GET; //引入Retrofit中的@GET注解,定义GET请求
+import retrofit2.http.Headers; //引入Retrofit中的 @Headers 注解,用于添加自定义请求头
+import retrofit2.http.Query; //引入Retrofit中的@Query注解,用于在URL中添加查询参数
+import retrofit2.http.Url; //引入Retrofit中的@Url注解,表示动态传递URL
-import io.reactivex.Observable;
-import retrofit2.http.GET;
-import retrofit2.http.Headers;
-import retrofit2.http.Query;
-import retrofit2.http.Url;
-
+//该API接口定义了与零点看书小说网站进行交互的方法,用于获取书籍信息、搜索书籍、获取书籍内容等。
public interface ILingdiankanshuApi {
-
- @GET
- @Headers({"Accept:text/html,application/xhtml+xml,application/xml",
- "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3",
- "Accept-Charset:UTF-8",
- "Connection:close",
- "Cache-Control:no-cache"})
+ //获取书籍信息的请求
+ @GET //定义GET请求
+ //设置自定义的HTTP请求头
+ @Headers({"Accept:text/html,application/xhtml+xml,application/xml", //请求头:表示支持的响应类型
+ "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", //模拟浏览器的User-Agent
+ "Accept-Charset:UTF-8", //请求头:指定字符集为 UTF-8
+ "Connection:close", //请求头:请求完成后关闭连接
+ "Cache-Control:no-cache"}) //请求头:禁用缓存
+ //该方法接受一个动态URL,返回一个Observable类型的响应流,表示书籍信息
Observable getBookInfo(@Url String url);
- @GET("/cse/search")
- @Headers({"Accept:text/html,application/xhtml+xml,application/xml",
- "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3",
- "Accept-Charset:UTF-8",
- "Connection:close",
- "Cache-Control:no-cache"})
+ //搜索书籍的请求
+ @GET("/cse/search") //定义GET请求的URL路径"/cse/search"
+ //设置请求头
+ @Headers({"Accept:text/html,application/xhtml+xml,application/xml", //请求头:表示支持的响应类型
+ "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", //模拟浏览器的User-Agent
+ "Accept-Charset:UTF-8", //请求头:指定字符集为 UTF-8
+ "Connection:close", //请求头:请求完成后关闭连接
+ "Cache-Control:no-cache"}) //请求头:禁用缓存
+ //该方法接受三个查询参数:书籍关键词`q`,页码`p`,以及时间`s`,返回书籍搜索结果
Observable searchBook(@Query("q") String content, @Query("p") int page, @Query("s") String time);
- @GET
- @Headers({"Accept:text/html,application/xhtml+xml,application/xml",
- "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3",
- "Accept-Charset:UTF-8",
- "Connection:close",
- "Cache-Control:no-cache"})
+ //获取书籍内容的请求
+ @GET //定义GET请求
+ //设置请求头
+ @Headers({"Accept:text/html,application/xhtml+xml,application/xml", //请求头:表示支持的响应类型
+ "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", //模拟浏览器的User-Agent
+ "Accept-Charset:UTF-8", //请求头:指定字符集为 UTF-8
+ "Connection:close", //请求头:请求完成后关闭连接
+ "Cache-Control:no-cache"}) //请求头:禁用缓存
+ //该方法接受一个动态URL,返回书籍内容
Observable getBookContent(@Url String url);
- @GET
- @Headers({"Accept:text/html,application/xhtml+xml,application/xml",
- "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3",
- "Accept-Charset:UTF-8",
- "Connection:close",
- "Cache-Control:no-cache"})
+ @GET //定义GET请求
+ //设置请求头
+ @Headers({"Accept:text/html,application/xhtml+xml,application/xml", //请求头:表示支持的响应类型
+ "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", //模拟浏览器的User-Agent
+ "Accept-Charset:UTF-8", //请求头:指定字符集为 UTF-8
+ "Connection:close", //请求头:请求完成后关闭连接
+ "Cache-Control:no-cache"}) //请求头:禁用缓存
+ //该方法接受一个动态URL,返回书籍的章节列表
Observable getChapterList(@Url String url);
}
diff --git a/app/src/main/java/com/monke/monkeybook/dao/BookContentBeanDao.java b/app/src/main/java/com/monke/monkeybook/dao/BookContentBeanDao.java
index 6e40f73..92c5d2f 100644
--- a/app/src/main/java/com/monke/monkeybook/dao/BookContentBeanDao.java
+++ b/app/src/main/java/com/monke/monkeybook/dao/BookContentBeanDao.java
@@ -1,28 +1,30 @@
+//指定了当前类BookContentBeanDao所在的包路径,即com.monke.monkeybook.dao
package com.monke.monkeybook.dao;
-
+//导入必要的类,包含GreenDAO、SQLite和Android数据库操作的相关类
import android.database.Cursor;
import android.database.sqlite.SQLiteStatement;
-
import org.greenrobot.greendao.AbstractDao;
import org.greenrobot.greendao.Property;
import org.greenrobot.greendao.internal.DaoConfig;
import org.greenrobot.greendao.database.Database;
import org.greenrobot.greendao.database.DatabaseStatement;
-
+// 导入实体类 BookContentBean
import com.monke.monkeybook.bean.BookContentBean;
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
-/**
+/**
* DAO for table "BOOK_CONTENT_BEAN".
-*/
+ */
+//继承自GreenDAO的AbstractDao类,BookContentBean为实体类,String为主键类型
public class BookContentBeanDao extends AbstractDao {
-
+ //定义常量TABLENAME,表示该表的名称
public static final String TABLENAME = "BOOK_CONTENT_BEAN";
-
/**
* Properties of entity BookContentBean.
* Can be used for QueryBuilder and for referencing column names.
- */
+ * BookContentBean是实体类的属性,可以用于QueryBuilder以及引用数据库表字段名。
+ */
+ // 定义实体类属性映射:对应数据库表字段名的属性
public static class Properties {
public final static Property DurChapterUrl = new Property(0, String.class, "durChapterUrl", true, "DUR_CHAPTER_URL");
public final static Property DurChapterIndex = new Property(1, int.class, "durChapterIndex", false, "DUR_CHAPTER_INDEX");
@@ -30,18 +32,24 @@ public class BookContentBeanDao extends AbstractDao {
public final static Property Tag = new Property(3, String.class, "tag", false, "TAG");
};
-
+ //构造函数,传入DaoConfig,用于初始化DAO
public BookContentBeanDao(DaoConfig config) {
- super(config);
+ super(config); //调用父类构造函数,初始化Dao配置
}
-
+
+ // 构造函数,传入DaoConfig和DaoSession,用于初始化DAO和会话管理
public BookContentBeanDao(DaoConfig config, DaoSession daoSession) {
- super(config, daoSession);
+ super(config, daoSession); //调用父类构造函数,初始化Dao配置和会话
}
- /** Creates the underlying database table. */
+ /**
+ * Creates the underlying database table.
+ * 创建数据库表
+ */
public static void createTable(Database db, boolean ifNotExists) {
+ //如果ifNotExists为true,则在创建表时确保该表不存在
String constraint = ifNotExists? "IF NOT EXISTS ": "";
+ //使用SQL执行表创建语句
db.execSQL("CREATE TABLE " + constraint + "\"BOOK_CONTENT_BEAN\" (" + //
"\"DUR_CHAPTER_URL\" TEXT PRIMARY KEY NOT NULL ," + // 0: durChapterUrl
"\"DUR_CHAPTER_INDEX\" INTEGER NOT NULL ," + // 1: durChapterIndex
@@ -49,85 +57,110 @@ public class BookContentBeanDao extends AbstractDao {
"\"TAG\" TEXT);"); // 3: tag
}
- /** Drops the underlying database table. */
+ /** Drops the underlying database table.
+ * 删除数据库表
+ */
public static void dropTable(Database db, boolean ifExists) {
+ //使用SQL删除表,确保表存在时删除
String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"BOOK_CONTENT_BEAN\"";
db.execSQL(sql);
}
@Override
protected final void bindValues(DatabaseStatement stmt, BookContentBean entity) {
+ //清除绑定的值,确保每次绑定时都是干净的
stmt.clearBindings();
-
+
+ //绑定durChapterUrl字段到SQL语句的第一个位置
String durChapterUrl = entity.getDurChapterUrl();
if (durChapterUrl != null) {
+ //将章节URL字符串绑定到SQL语句的第一个位置
stmt.bindString(1, durChapterUrl);
}
- stmt.bindLong(2, entity.getDurChapterIndex());
-
+
+ //绑定durChapterIndex字段到SQL语句的第二个位置
+ stmt.bindLong(2, entity.getDurChapterIndex());//将章节索引绑定到SQL语句的第二个位置
+
+ //绑定durCapterContent字段到SQL语句的第三个位置
String durCapterContent = entity.getDurCapterContent();
if (durCapterContent != null) {
+ //将章节内容绑定到SQL语句的第三个位置
stmt.bindString(3, durCapterContent);
}
-
+
+ //绑定tag字段到SQL语句的第四个位置
String tag = entity.getTag();
if (tag != null) {
+ //将标签绑定到SQL语句的第四个位置
stmt.bindString(4, tag);
}
}
@Override
protected final void bindValues(SQLiteStatement stmt, BookContentBean entity) {
+ //清除绑定的值,确保每次绑定时都是干净的
stmt.clearBindings();
-
+
+ //绑定durChapterUrl字段到SQL语句的第一个位置
String durChapterUrl = entity.getDurChapterUrl();
if (durChapterUrl != null) {
+ //将章节URL字符串绑定到SQL语句的第一个位置
stmt.bindString(1, durChapterUrl);
}
- stmt.bindLong(2, entity.getDurChapterIndex());
-
+ //绑定durChapterIndex字段到SQL语句的第二个位置
+ stmt.bindLong(2, entity.getDurChapterIndex()); //将章节索引绑定到SQL语句的第二个位置
+
+ //绑定durCapterContent字段到SQL语句的第三个位置
String durCapterContent = entity.getDurCapterContent();
if (durCapterContent != null) {
+ //将章节内容绑定到SQL语句的第三个位置
stmt.bindString(3, durCapterContent);
}
-
+
+ //绑定tag字段到SQL语句的第四个位置
String tag = entity.getTag();
if (tag != null) {
+ //将标签绑定到SQL语句的第四个位置
stmt.bindString(4, tag);
}
}
@Override
public String readKey(Cursor cursor, int offset) {
+ //从Cursor中读取主键(durChapterUrl),若为null则返回null
return cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0);
- }
+ }
@Override
public BookContentBean readEntity(Cursor cursor, int offset) {
+ //根据Cursor数据构建一个BookContentBean实体类对象,并返回
BookContentBean entity = new BookContentBean( //
- cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0), // durChapterUrl
- cursor.getInt(offset + 1), // durChapterIndex
- cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // durCapterContent
- cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3) // tag
+ cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0), // durChapterUrl
+ cursor.getInt(offset + 1), // durChapterIndex
+ cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // durCapterContent
+ cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3) // tag
);
return entity;
}
-
+
@Override
public void readEntity(Cursor cursor, BookContentBean entity, int offset) {
+ //从Cursor中读取值并设置到BookContentBean对象的相应属性中
entity.setDurChapterUrl(cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0));
entity.setDurChapterIndex(cursor.getInt(offset + 1));
entity.setDurCapterContent(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2));
entity.setTag(cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3));
- }
-
+ }
+
@Override
protected final String updateKeyAfterInsert(BookContentBean entity, long rowId) {
+ //返回更新时需要的主键字段,这里是durChapterUrl
return entity.getDurChapterUrl();
}
-
+
@Override
public String getKey(BookContentBean entity) {
+ //获取实体对象的主键值,返回durChapterUrl
if(entity != null) {
return entity.getDurChapterUrl();
} else {
@@ -137,7 +170,8 @@ public class BookContentBeanDao extends AbstractDao {
@Override
protected final boolean isEntityUpdateable() {
+ //指示实体是否可以被更新,这里返回true,表示支持更新
return true;
}
-
+
}
diff --git a/app/src/main/java/com/monke/monkeybook/dao/BookInfoBeanDao.java b/app/src/main/java/com/monke/monkeybook/dao/BookInfoBeanDao.java
index 3e17cf5..ac4edfb 100644
--- a/app/src/main/java/com/monke/monkeybook/dao/BookInfoBeanDao.java
+++ b/app/src/main/java/com/monke/monkeybook/dao/BookInfoBeanDao.java
@@ -1,156 +1,202 @@
+//定义类所在的包路径,表示该文件属于com.monke.monkeybook.dao包
package com.monke.monkeybook.dao;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteStatement;
+//导入必要的类,包含GreenDAO和Android数据库操作的相关类
+import android.database.Cursor;// 导入Cursor类,用于数据库查询结果的处理
+import android.database.sqlite.SQLiteStatement;//导入SQLiteStatement类,用于执行SQL语句
-import org.greenrobot.greendao.AbstractDao;
-import org.greenrobot.greendao.Property;
-import org.greenrobot.greendao.internal.DaoConfig;
-import org.greenrobot.greendao.database.Database;
-import org.greenrobot.greendao.database.DatabaseStatement;
+import org.greenrobot.greendao.AbstractDao;//导入AbstractDao类,这是一个GreenDao框架的抽象类,用于定义数据库操作的基类
+import org.greenrobot.greendao.Property;//导入Property类,用于定义数据库表中的字段属性
+import org.greenrobot.greendao.internal.DaoConfig;//导入DaoConfig类,用于配置DAO对象
+import org.greenrobot.greendao.database.Database;//导入Database类,用于操作数据库
+import org.greenrobot.greendao.database.DatabaseStatement;//导入BookInfoBean实体类
-import com.monke.monkeybook.bean.BookInfoBean;
+import com.monke.monkeybook.bean.BookInfoBean;//导入BookInfoBean类,这是数据库中要操作的实体类
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
-/**
+/**
* DAO for table "BOOK_INFO_BEAN".
-*/
-public class BookInfoBeanDao extends AbstractDao {
+ * DAO 类,用于操作 "BOOK_INFO_BEAN" 表
+ */
+//BookInfoBeanDao继承自AbstractDao,操作BookInfoBean对象,主键类型为String
+public class BookInfoBeanDao extends AbstractDao {
+ //定义常量TABLENAME,表示数据库表名
public static final String TABLENAME = "BOOK_INFO_BEAN";
/**
* Properties of entity BookInfoBean.
* Can be used for QueryBuilder and for referencing column names.
- */
+ * BookInfoBean 实体类的属性,可以用于 QueryBuilder 以及引用数据库表字段名。
+ */
public static class Properties {
- public final static Property Name = new Property(0, String.class, "name", false, "NAME");
- public final static Property Tag = new Property(1, String.class, "tag", false, "TAG");
- public final static Property NoteUrl = new Property(2, String.class, "noteUrl", true, "NOTE_URL");
- public final static Property ChapterUrl = new Property(3, String.class, "chapterUrl", false, "CHAPTER_URL");
- public final static Property FinalRefreshData = new Property(4, long.class, "finalRefreshData", false, "FINAL_REFRESH_DATA");
- public final static Property CoverUrl = new Property(5, String.class, "coverUrl", false, "COVER_URL");
- public final static Property Author = new Property(6, String.class, "author", false, "AUTHOR");
- public final static Property Introduce = new Property(7, String.class, "introduce", false, "INTRODUCE");
- public final static Property Origin = new Property(8, String.class, "origin", false, "ORIGIN");
+ //定义实体类属性映射:对应数据库表字段名的属性
+ public final static Property Name = new Property(0, String.class, "name", false, "NAME");//属性0:名称(name),String类型,非主键,数据库列名NAME
+ public final static Property Tag = new Property(1, String.class, "tag", false, "TAG");//属性1:标签(tag),String类型,非主键,数据库列名TAG
+ public final static Property NoteUrl = new Property(2, String.class, "noteUrl", true, "NOTE_URL");// 属性2:笔记URL(noteUrl),String类型,主键,非空,数据库列名NOTE_URL
+ public final static Property ChapterUrl = new Property(3, String.class, "chapterUrl", false, "CHAPTER_URL");//属性3:章节URL(chapterUrl),String类型,非主键,数据库列名CHAPTER_URL
+ public final static Property FinalRefreshData = new Property(4, long.class, "finalRefreshData", false, "FINAL_REFRESH_DATA");//属性4:最后刷新时间(finalRefreshData),long类型,非主键,数据库列名FINAL_REFRESH_DATA
+ public final static Property CoverUrl = new Property(5, String.class, "coverUrl", false, "COVER_URL");//属性5:封面URL(coverUrl),String类型,非主键,数据库列名COVER_URL
+ public final static Property Author = new Property(6, String.class, "author", false, "AUTHOR");//属性6:作者(author),String类型,非主键,数据库列名AUTHOR
+ public final static Property Introduce = new Property(7, String.class, "introduce", false, "INTRODUCE");//属性7:简介(introduce),String类型,非主键,数据库列名INTRODUCE
+ public final static Property Origin = new Property(8, String.class, "origin", false, "ORIGIN");//属性8:来源(origin),String类型,非主键,数据库列名ORIGIN
};
-
+ //构造函数,使用DaoConfig配置创建DAO对象
public BookInfoBeanDao(DaoConfig config) {
super(config);
}
-
+
+ //构造函数,使用DaoConfig和DaoSession配置创建DAO对象
public BookInfoBeanDao(DaoConfig config, DaoSession daoSession) {
super(config, daoSession);
}
- /** Creates the underlying database table. */
+ /** Creates the underlying database table.
+ * 创建数据库表
+ */
+ //创建数据库表的方法
public static void createTable(Database db, boolean ifNotExists) {
+ //判断是否需要添加IF NOT EXISTS条件
String constraint = ifNotExists? "IF NOT EXISTS ": "";
- db.execSQL("CREATE TABLE " + constraint + "\"BOOK_INFO_BEAN\" (" + //
- "\"NAME\" TEXT," + // 0: name
- "\"TAG\" TEXT," + // 1: tag
- "\"NOTE_URL\" TEXT PRIMARY KEY NOT NULL ," + // 2: noteUrl
- "\"CHAPTER_URL\" TEXT," + // 3: chapterUrl
- "\"FINAL_REFRESH_DATA\" INTEGER NOT NULL ," + // 4: finalRefreshData
- "\"COVER_URL\" TEXT," + // 5: coverUrl
- "\"AUTHOR\" TEXT," + // 6: author
- "\"INTRODUCE\" TEXT," + // 7: introduce
- "\"ORIGIN\" TEXT);"); // 8: origin
+ //使用SQL执行表创建语句
+ db.execSQL("CREATE TABLE " + constraint + "\"BOOK_INFO_BEAN\" (" +
+ "\"NAME\" TEXT," + //NAME字段,TEXT类型
+ "\"TAG\" TEXT," + //TAG字段,TEXT类型
+ "\"NOTE_URL\" TEXT PRIMARY KEY NOT NULL ," + //NOTE_URL字段,TEXT类型,主键,非空
+ "\"CHAPTER_URL\" TEXT," + //CHAPTER_URL字段,TEXT类型
+ "\"FINAL_REFRESH_DATA\" INTEGER NOT NULL ," + //FINAL_REFRESH_DATA字段,INTEGER类型,非空
+ "\"COVER_URL\" TEXT," + //COVER_URL字段,TEXT类型
+ "\"AUTHOR\" TEXT," + //AUTHOR字段,TEXT类型
+ "\"INTRODUCE\" TEXT," + //INTRODUCE字段,TEXT类型
+ "\"ORIGIN\" TEXT);"); //ORIGIN字段,TEXT类型
}
- /** Drops the underlying database table. */
+ /** Drops the underlying database table.
+ * 删除底层数据库表
+ */
public static void dropTable(Database db, boolean ifExists) {
- String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"BOOK_INFO_BEAN\"";
- db.execSQL(sql);
+ //使用SQL删除表,确保表存在时删除
+ String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"BOOK_INFO_BEAN\"";//构造删除表的SQL语句
+ db.execSQL(sql);//执行删除表的SQL语句
}
@Override
+ //将BookInfoBean实体对象的值绑定到DatabaseStatement对象中
protected final void bindValues(DatabaseStatement stmt, BookInfoBean entity) {
+ //清除绑定的值,确保每次绑定时都是干净的
stmt.clearBindings();
-
+
+ //绑定name字段到SQL语句的第一个位置
String name = entity.getName();
if (name != null) {
+ //将书名绑定到SQL语句的第一个位置
stmt.bindString(1, name);
}
-
+
+ //绑定tag字段到SQL语句的第二个位置
String tag = entity.getTag();
if (tag != null) {
+ //将标签绑定到SQL语句的第二个位置
stmt.bindString(2, tag);
}
-
+
+ //绑定noteUrl字段到SQL语句的第三个位置
String noteUrl = entity.getNoteUrl();
if (noteUrl != null) {
+ //将书籍URL绑定到SQL语句的第三个位置
stmt.bindString(3, noteUrl);
}
-
+
+ //绑定chapterUrl字段到SQL语句的第四个位置
String chapterUrl = entity.getChapterUrl();
if (chapterUrl != null) {
+ //将章节URL绑定到SQL语句的第四个位置
stmt.bindString(4, chapterUrl);
}
+ //将最后刷新时间(long 类型)绑定到SQL语句的第五个位置
stmt.bindLong(5, entity.getFinalRefreshData());
-
+
+ //绑定coverUrl字段到SQL语句的第六个位置
String coverUrl = entity.getCoverUrl();
if (coverUrl != null) {
+ //将封面图URL绑定到SQL语句的第六个位置
stmt.bindString(6, coverUrl);
}
-
+
+ //绑定author字段到SQL语句的第七个位置
String author = entity.getAuthor();
if (author != null) {
+ //将作者绑定到SQL语句的第七个位置
stmt.bindString(7, author);
}
-
+
+ //绑定introduce字段到SQL语句的第八个位置
String introduce = entity.getIntroduce();
if (introduce != null) {
+ //将简介绑定到SQL语句的第八个位置
stmt.bindString(8, introduce);
}
-
+
+ //绑定origin字段到SQL语句的第九个位置
String origin = entity.getOrigin();
if (origin != null) {
+ //将来源绑定到SQL语句的第九个位置
stmt.bindString(9, origin);
}
}
@Override
+ //将BookInfoBean实体对象的值绑定到SQLiteStatement对象中,与上一个方法功能类似,只是对象不同
protected final void bindValues(SQLiteStatement stmt, BookInfoBean entity) {
+ //清除绑定的值,确保每次绑定时都是干净的
stmt.clearBindings();
-
+
+ //绑定name字段值
String name = entity.getName();
if (name != null) {
stmt.bindString(1, name);
}
-
+
+ //绑定tag字段值
String tag = entity.getTag();
if (tag != null) {
stmt.bindString(2, tag);
}
-
+
+ //绑定noteUrl字段值
String noteUrl = entity.getNoteUrl();
if (noteUrl != null) {
stmt.bindString(3, noteUrl);
}
-
+
+ //绑定chapterUrl字段值
String chapterUrl = entity.getChapterUrl();
if (chapterUrl != null) {
stmt.bindString(4, chapterUrl);
}
+ //绑定finalRefreshData字段值
stmt.bindLong(5, entity.getFinalRefreshData());
-
+
+ //绑定coverUrl字段值
String coverUrl = entity.getCoverUrl();
if (coverUrl != null) {
stmt.bindString(6, coverUrl);
}
-
+
+ //绑定author字段值
String author = entity.getAuthor();
if (author != null) {
stmt.bindString(7, author);
}
-
+
+ //绑定introduce字段值
String introduce = entity.getIntroduce();
if (introduce != null) {
stmt.bindString(8, introduce);
}
-
+
+ //绑定origin字段值
String origin = entity.getOrigin();
if (origin != null) {
stmt.bindString(9, origin);
@@ -158,47 +204,57 @@ public class BookInfoBeanDao extends AbstractDao {
}
@Override
+ //从Cursor中读取主键
public String readKey(Cursor cursor, int offset) {
+ //主键在第三列(offset + 2),如果为空返回null,否则返回字符串
return cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2);
- }
+ }
@Override
+ //从Cursor中读取BookInfoBean实体
public BookInfoBean readEntity(Cursor cursor, int offset) {
+ //创建BookInfoBean对象
BookInfoBean entity = new BookInfoBean( //
- cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0), // name
- cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1), // tag
- cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // noteUrl
- cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3), // chapterUrl
- cursor.getLong(offset + 4), // finalRefreshData
- cursor.isNull(offset + 5) ? null : cursor.getString(offset + 5), // coverUrl
- cursor.isNull(offset + 6) ? null : cursor.getString(offset + 6), // author
- cursor.isNull(offset + 7) ? null : cursor.getString(offset + 7), // introduce
- cursor.isNull(offset + 8) ? null : cursor.getString(offset + 8) // origin
+ cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0), // name
+ cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1), // tag
+ cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // noteUrl
+ cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3), // chapterUrl
+ cursor.getLong(offset + 4), // finalRefreshData
+ cursor.isNull(offset + 5) ? null : cursor.getString(offset + 5), // coverUrl
+ cursor.isNull(offset + 6) ? null : cursor.getString(offset + 6), // author
+ cursor.isNull(offset + 7) ? null : cursor.getString(offset + 7), // introduce
+ cursor.isNull(offset + 8) ? null : cursor.getString(offset + 8) // origin
);
+ //返回创建好的BookInfoBean对象
return entity;
}
-
+
@Override
+ //将Cursor中的数据读取到已存在的BookInfoBean实体中
public void readEntity(Cursor cursor, BookInfoBean entity, int offset) {
- entity.setName(cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0));
- entity.setTag(cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1));
- entity.setNoteUrl(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2));
- entity.setChapterUrl(cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3));
- entity.setFinalRefreshData(cursor.getLong(offset + 4));
- entity.setCoverUrl(cursor.isNull(offset + 5) ? null : cursor.getString(offset + 5));
- entity.setAuthor(cursor.isNull(offset + 6) ? null : cursor.getString(offset + 6));
- entity.setIntroduce(cursor.isNull(offset + 7) ? null : cursor.getString(offset + 7));
- entity.setOrigin(cursor.isNull(offset + 8) ? null : cursor.getString(offset + 8));
- }
-
+ entity.setName(cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0));//name
+ entity.setTag(cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1));//tag
+ entity.setNoteUrl(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2));//noteUrl
+ entity.setChapterUrl(cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3));//chapterUrl
+ entity.setFinalRefreshData(cursor.getLong(offset + 4));//finalRefreshData
+ entity.setCoverUrl(cursor.isNull(offset + 5) ? null : cursor.getString(offset + 5));//coverUrl
+ entity.setAuthor(cursor.isNull(offset + 6) ? null : cursor.getString(offset + 6));//author
+ entity.setIntroduce(cursor.isNull(offset + 7) ? null : cursor.getString(offset + 7));//introduce
+ entity.setOrigin(cursor.isNull(offset + 8) ? null : cursor.getString(offset + 8));//origin
+ }
+
@Override
+ //插入数据后更新主键
protected final String updateKeyAfterInsert(BookInfoBean entity, long rowId) {
+ //使用noteUrl作为主键
return entity.getNoteUrl();
}
-
+
@Override
+ //获取主键
public String getKey(BookInfoBean entity) {
if(entity != null) {
+ //返回noteUrl作为主键
return entity.getNoteUrl();
} else {
return null;
@@ -206,8 +262,10 @@ public class BookInfoBeanDao extends AbstractDao {
}
@Override
+ //是否可更新实体
protected final boolean isEntityUpdateable() {
+ //可更新
return true;
}
-
+
}
diff --git a/app/src/main/java/com/monke/monkeybook/dao/BookShelfBeanDao.java b/app/src/main/java/com/monke/monkeybook/dao/BookShelfBeanDao.java
index ba34fcb..b0eb9f3 100644
--- a/app/src/main/java/com/monke/monkeybook/dao/BookShelfBeanDao.java
+++ b/app/src/main/java/com/monke/monkeybook/dao/BookShelfBeanDao.java
@@ -1,132 +1,163 @@
+// 包声明,声明该类位于com.monke.monkeybook.dao包下
package com.monke.monkeybook.dao;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteStatement;
+import android.database.Cursor; // 导入Cursor类,用于从数据库游标中读取数据
+import android.database.sqlite.SQLiteStatement; // 导入SQLiteStatement类,用于执行预编译的SQL语句
-import org.greenrobot.greendao.AbstractDao;
-import org.greenrobot.greendao.Property;
-import org.greenrobot.greendao.internal.DaoConfig;
-import org.greenrobot.greendao.database.Database;
-import org.greenrobot.greendao.database.DatabaseStatement;
+import org.greenrobot.greendao.AbstractDao; // 导入AbstractDao类,GreenDao框架中用于数据库操作的抽象基类
+import org.greenrobot.greendao.Property; // 导入Property类,用于定义数据库表字段的属性
+import org.greenrobot.greendao.internal.DaoConfig; // 导入DaoConfig类,用于配置Dao对象的配置信息
+import org.greenrobot.greendao.database.Database; // 导入Database类,GreenDao框架中用于数据库操作的类
+import org.greenrobot.greendao.database.DatabaseStatement; // 导入DatabaseStatement类,用于执行SQL语句
+// 导入BookShelfBean类,这是数据库操作的对象
import com.monke.monkeybook.bean.BookShelfBean;
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
-/**
+/**
* DAO for table "BOOK_SHELF_BEAN".
-*/
+ */
+// BookShelfBeanDao类继承AbstractDao,操作BookShelfBean对象,主键类型为String
public class BookShelfBeanDao extends AbstractDao {
-
+ // 数据库表名常量
public static final String TABLENAME = "BOOK_SHELF_BEAN";
/**
* Properties of entity BookShelfBean.
* Can be used for QueryBuilder and for referencing column names.
- */
+ */
public static class Properties {
- public final static Property NoteUrl = new Property(0, String.class, "noteUrl", true, "NOTE_URL");
- public final static Property DurChapter = new Property(1, int.class, "durChapter", false, "DUR_CHAPTER");
- public final static Property DurChapterPage = new Property(2, int.class, "durChapterPage", false, "DUR_CHAPTER_PAGE");
- public final static Property FinalDate = new Property(3, long.class, "finalDate", false, "FINAL_DATE");
- public final static Property Tag = new Property(4, String.class, "tag", false, "TAG");
+ public final static Property NoteUrl = new Property(0, String.class, "noteUrl", true, "NOTE_URL"); // 属性0:noteUrl,String类型,主键,数据库列名NOTE_URL
+ public final static Property DurChapter = new Property(1, int.class, "durChapter", false, "DUR_CHAPTER"); // 属性1:durChapter,int类型,非主键,数据库列名DUR_CHAPTER
+ public final static Property DurChapterPage = new Property(2, int.class, "durChapterPage", false, "DUR_CHAPTER_PAGE"); // 属性2:durChapterPage,int类型,非主键,数据库列名DUR_CHAPTER_PAGE
+ public final static Property FinalDate = new Property(3, long.class, "finalDate", false, "FINAL_DATE"); // 属性3:finalDate,long类型,非主键,数据库列名FINAL_DATE
+ public final static Property Tag = new Property(4, String.class, "tag", false, "TAG"); // 属性4:tag,String类型,非主键,数据库列名TAG
};
-
+ // 构造函数,使用DaoConfig配置初始化Dao
public BookShelfBeanDao(DaoConfig config) {
super(config);
}
-
+
+ // 构造函数,使用DaoConfig和DaoSession配置初始化Dao
public BookShelfBeanDao(DaoConfig config, DaoSession daoSession) {
super(config, daoSession);
}
- /** Creates the underlying database table. */
+ /** Creates the underlying database table.
+ * 创建数据库表
+ */
+ // 创建BOOK_SHELF_BEAN表的方法
public static void createTable(Database db, boolean ifNotExists) {
+ // 根据ifNotExists判断是否需要添加"IF NOT EXISTS"条件
String constraint = ifNotExists? "IF NOT EXISTS ": "";
+ // 执行SQL语句创建表
db.execSQL("CREATE TABLE " + constraint + "\"BOOK_SHELF_BEAN\" (" + //
- "\"NOTE_URL\" TEXT PRIMARY KEY NOT NULL ," + // 0: noteUrl
- "\"DUR_CHAPTER\" INTEGER NOT NULL ," + // 1: durChapter
- "\"DUR_CHAPTER_PAGE\" INTEGER NOT NULL ," + // 2: durChapterPage
- "\"FINAL_DATE\" INTEGER NOT NULL ," + // 3: finalDate
- "\"TAG\" TEXT);"); // 4: tag
+ "\"NOTE_URL\" TEXT PRIMARY KEY NOT NULL ," + //NOTE_URL字段,TEXT类型,主键,非空
+ "\"DUR_CHAPTER\" INTEGER NOT NULL ," + // DUR_CHAPTER字段,INTEGER类型,非空
+ "\"DUR_CHAPTER_PAGE\" INTEGER NOT NULL ," + // DUR_CHAPTER_PAGE字段,INTEGER类型,非空
+ "\"FINAL_DATE\" INTEGER NOT NULL ," + // FINAL_DATE字段,INTEGER类型,非空
+ "\"TAG\" TEXT);"); // TAG字段,TEXT类型
}
- /** Drops the underlying database table. */
+ /** Drops the underlying database table.
+ * 删除数据库表
+ */
+ // 删除BOOK_SHELF_BEAN表的方法
public static void dropTable(Database db, boolean ifExists) {
+ // 构造删除表的SQL语句
String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"BOOK_SHELF_BEAN\"";
+ // 执行SQL语句删除表
db.execSQL(sql);
}
@Override
+ // 将BookShelfBean实体对象的值绑定到DatabaseStatement语句中
protected final void bindValues(DatabaseStatement stmt, BookShelfBean entity) {
+ // 清除之前的绑定
stmt.clearBindings();
-
+
String noteUrl = entity.getNoteUrl();
if (noteUrl != null) {
+ // 绑定noteUrl值到第一个参数位置
stmt.bindString(1, noteUrl);
}
- stmt.bindLong(2, entity.getDurChapter());
- stmt.bindLong(3, entity.getDurChapterPage());
- stmt.bindLong(4, entity.getFinalDate());
-
+ stmt.bindLong(2, entity.getDurChapter()); // 绑定durChapter值到第二个参数位置
+ stmt.bindLong(3, entity.getDurChapterPage()); // 绑定durChapterPage值到第三个参数位置
+ stmt.bindLong(4, entity.getFinalDate()); // 绑定finalDate值到第四个参数位置
+
String tag = entity.getTag();
if (tag != null) {
- stmt.bindString(5, tag);
+ stmt.bindString(5, tag); // 绑定tag值到第五个参数位置
}
}
@Override
+ // 将BookShelfBean实体对象的值绑定到SQLiteStatement语句中,与上一个方法功能类似,只是对象不同
protected final void bindValues(SQLiteStatement stmt, BookShelfBean entity) {
+ // 清除之前的绑定
stmt.clearBindings();
-
+
String noteUrl = entity.getNoteUrl();
if (noteUrl != null) {
+ // 绑定noteUrl值到第一个参数位置
stmt.bindString(1, noteUrl);
}
- stmt.bindLong(2, entity.getDurChapter());
- stmt.bindLong(3, entity.getDurChapterPage());
- stmt.bindLong(4, entity.getFinalDate());
-
+ stmt.bindLong(2, entity.getDurChapter()); // 绑定durChapter值到第二个参数位置
+ stmt.bindLong(3, entity.getDurChapterPage()); // 绑定durChapterPage值到第三个参数位置
+ stmt.bindLong(4, entity.getFinalDate()); // 绑定finalDate值到第四个参数位置
+
String tag = entity.getTag();
if (tag != null) {
+ // 绑定tag值到第五个参数位置
stmt.bindString(5, tag);
}
}
@Override
+ // 从游标中读取主键
public String readKey(Cursor cursor, int offset) {
+ // 从偏移量offset+0的位置读取主键值,如果为空返回null,否则返回字符串
return cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0);
- }
+ }
@Override
+ // 从游标中读取BookShelfBean实体
public BookShelfBean readEntity(Cursor cursor, int offset) {
+ // 创建BookShelfBean对象
BookShelfBean entity = new BookShelfBean( //
- cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0), // noteUrl
- cursor.getInt(offset + 1), // durChapter
- cursor.getInt(offset + 2), // durChapterPage
- cursor.getLong(offset + 3), // finalDate
- cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4) // tag
+ cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0), // noteUrl
+ cursor.getInt(offset + 1), // durChapter
+ cursor.getInt(offset + 2), // durChapterPage
+ cursor.getLong(offset + 3), // finalDate
+ cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4) // tag
);
+ // 返回创建好的BookShelfBean对象
return entity;
}
-
+
@Override
+ // 将游标中的数据读取到已存在的BookShelfBean实体中
public void readEntity(Cursor cursor, BookShelfBean entity, int offset) {
- entity.setNoteUrl(cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0));
- entity.setDurChapter(cursor.getInt(offset + 1));
- entity.setDurChapterPage(cursor.getInt(offset + 2));
- entity.setFinalDate(cursor.getLong(offset + 3));
- entity.setTag(cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4));
- }
-
+ entity.setNoteUrl(cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0)); // noteUrl
+ entity.setDurChapter(cursor.getInt(offset + 1)); // durChapter
+ entity.setDurChapterPage(cursor.getInt(offset + 2)); // durChapterPage
+ entity.setFinalDate(cursor.getLong(offset + 3)); // finalDate
+ entity.setTag(cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4)); // tag
+ }
+
@Override
+ // 插入数据后更新主键
protected final String updateKeyAfterInsert(BookShelfBean entity, long rowId) {
+ // 返回noteUrl作为主键
return entity.getNoteUrl();
}
-
+
@Override
+ // 获取主键
public String getKey(BookShelfBean entity) {
if(entity != null) {
+ // 返回noteUrl作为主键
return entity.getNoteUrl();
} else {
return null;
@@ -134,8 +165,10 @@ public class BookShelfBeanDao extends AbstractDao {
}
@Override
+ // 判断实体是否可更新
protected final boolean isEntityUpdateable() {
+ // 返回true,表示实体可更新
return true;
}
-
+
}
diff --git a/app/src/main/java/com/monke/monkeybook/dao/ChapterListBeanDao.java b/app/src/main/java/com/monke/monkeybook/dao/ChapterListBeanDao.java
index d883f64..fc4de8e 100644
--- a/app/src/main/java/com/monke/monkeybook/dao/ChapterListBeanDao.java
+++ b/app/src/main/java/com/monke/monkeybook/dao/ChapterListBeanDao.java
@@ -1,162 +1,200 @@
+// 包声明
package com.monke.monkeybook.dao;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteStatement;
+import android.database.Cursor; // 导入Cursor类,用于从数据库游标中读取数据
+import android.database.sqlite.SQLiteStatement; // 导入SQLiteStatement类,用于执行预编译的SQL语句
-import org.greenrobot.greendao.AbstractDao;
-import org.greenrobot.greendao.Property;
-import org.greenrobot.greendao.internal.DaoConfig;
-import org.greenrobot.greendao.database.Database;
-import org.greenrobot.greendao.database.DatabaseStatement;
+import org.greenrobot.greendao.AbstractDao; // 导入AbstractDao类,GreenDao框架中用于数据库操作的抽象基类
+import org.greenrobot.greendao.Property; // 导入Property类,用于定义数据库表字段的属性
+import org.greenrobot.greendao.internal.DaoConfig; // 导入DaoConfig类,用于配置Dao对象的配置信息
+import org.greenrobot.greendao.database.Database; // 导入Database类,GreenDao框架中用于数据库操作的类
+import org.greenrobot.greendao.database.DatabaseStatement; // 导入DatabaseStatement类,用于执行SQL语句
+// 导入ChapterListBean类,这是数据库操作的对象
import com.monke.monkeybook.bean.ChapterListBean;
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
-/**
+/**
* DAO for table "CHAPTER_LIST_BEAN".
-*/
+ */
+// ChapterListBeanDao类继承AbstractDao,操作ChapterListBean对象,主键类型为String
public class ChapterListBeanDao extends AbstractDao {
-
+ // 数据库表名常量
public static final String TABLENAME = "CHAPTER_LIST_BEAN";
/**
* Properties of entity ChapterListBean.
* Can be used for QueryBuilder and for referencing column names.
- */
+ */
public static class Properties {
- public final static Property NoteUrl = new Property(0, String.class, "noteUrl", false, "NOTE_URL");
- public final static Property DurChapterIndex = new Property(1, int.class, "durChapterIndex", false, "DUR_CHAPTER_INDEX");
- public final static Property DurChapterUrl = new Property(2, String.class, "durChapterUrl", true, "DUR_CHAPTER_URL");
- public final static Property DurChapterName = new Property(3, String.class, "durChapterName", false, "DUR_CHAPTER_NAME");
- public final static Property Tag = new Property(4, String.class, "tag", false, "TAG");
- public final static Property HasCache = new Property(5, Boolean.class, "hasCache", false, "HAS_CACHE");
+ public final static Property NoteUrl = new Property(0, String.class, "noteUrl", false, "NOTE_URL"); // 属性0:noteUrl,String类型,非主键,数据库列名NOTE_URL
+ public final static Property DurChapterIndex = new Property(1, int.class, "durChapterIndex", false, "DUR_CHAPTER_INDEX"); // 属性1:durChapterIndex,int类型,非主键,数据库列名DUR_CHAPTER_INDEX
+ public final static Property DurChapterUrl = new Property(2, String.class, "durChapterUrl", true, "DUR_CHAPTER_URL"); // 属性2:durChapterUrl,String类型,主键,数据库列名DUR_CHAPTER_URL
+ public final static Property DurChapterName = new Property(3, String.class, "durChapterName", false, "DUR_CHAPTER_NAME"); // 属性3:durChapterName,String类型,非主键,数据库列名DUR_CHAPTER_NAME
+ public final static Property Tag = new Property(4, String.class, "tag", false, "TAG"); // 属性4:tag,String类型,非主键,数据库列名TAG
+ public final static Property HasCache = new Property(5, Boolean.class, "hasCache", false, "HAS_CACHE"); // 属性5:hasCache,Boolean类型,非主键,数据库列名HAS_CACHE
};
-
+ // 构造函数,使用DaoConfig配置初始化Dao
public ChapterListBeanDao(DaoConfig config) {
super(config);
}
-
+
+ // 构造函数,使用DaoConfig和DaoSession配置初始化Dao
public ChapterListBeanDao(DaoConfig config, DaoSession daoSession) {
super(config, daoSession);
}
/** Creates the underlying database table. */
+ // 创建CHAPTER_LIST_BEAN表的方法
public static void createTable(Database db, boolean ifNotExists) {
+ // 根据ifNotExists判断是否需要添加"IF NOT EXISTS"条件
String constraint = ifNotExists? "IF NOT EXISTS ": "";
+ // 执行SQL语句创建表
db.execSQL("CREATE TABLE " + constraint + "\"CHAPTER_LIST_BEAN\" (" + //
- "\"NOTE_URL\" TEXT," + // 0: noteUrl
- "\"DUR_CHAPTER_INDEX\" INTEGER NOT NULL ," + // 1: durChapterIndex
- "\"DUR_CHAPTER_URL\" TEXT PRIMARY KEY NOT NULL ," + // 2: durChapterUrl
- "\"DUR_CHAPTER_NAME\" TEXT," + // 3: durChapterName
- "\"TAG\" TEXT," + // 4: tag
- "\"HAS_CACHE\" INTEGER);"); // 5: hasCache
+ "\"NOTE_URL\" TEXT," + // NOTE_URL字段,TEXT类型
+ "\"DUR_CHAPTER_INDEX\" INTEGER NOT NULL ," + // DUR_CHAPTER_INDEX字段,INTEGER类型,非空
+ "\"DUR_CHAPTER_URL\" TEXT PRIMARY KEY NOT NULL ," + // DUR_CHAPTER_URL字段,TEXT类型,主键,非空
+ "\"DUR_CHAPTER_NAME\" TEXT," + // DUR_CHAPTER_NAME字段,TEXT类型
+ "\"TAG\" TEXT," + // TAG字段,TEXT类型
+ "\"HAS_CACHE\" INTEGER);"); // HAS_CACHE字段,INTEGER类型
}
- /** Drops the underlying database table. */
+ /** Drops the underlying database table.
+ * 删除数据库表
+ */
+ // 删除CHAPTER_LIST_BEAN表的方法
public static void dropTable(Database db, boolean ifExists) {
+ // 构造删除表的SQL语句
String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"CHAPTER_LIST_BEAN\"";
+ // 执行SQL语句删除表
db.execSQL(sql);
}
@Override
+ // 将ChapterListBean实体对象的值绑定到DatabaseStatement语句中
protected final void bindValues(DatabaseStatement stmt, ChapterListBean entity) {
+ // 清除之前的绑定
stmt.clearBindings();
-
+
String noteUrl = entity.getNoteUrl();
if (noteUrl != null) {
+ // 绑定noteUrl值到第一个参数位置
stmt.bindString(1, noteUrl);
}
+ // 绑定durChapterIndex值到第二个参数位置
stmt.bindLong(2, entity.getDurChapterIndex());
-
+
String durChapterUrl = entity.getDurChapterUrl();
if (durChapterUrl != null) {
+ // 绑定durChapterUrl值到第三个参数位置
stmt.bindString(3, durChapterUrl);
}
-
+
String durChapterName = entity.getDurChapterName();
if (durChapterName != null) {
+ // 绑定durChapterName值到第四个参数位置
stmt.bindString(4, durChapterName);
}
-
+
String tag = entity.getTag();
if (tag != null) {
+ // 绑定tag值到第五个参数位置
stmt.bindString(5, tag);
}
-
+
Boolean hasCache = entity.getHasCache();
if (hasCache != null) {
+ // 绑定hasCache值到第六个参数位置,true为1,false为0
stmt.bindLong(6, hasCache ? 1L: 0L);
}
}
@Override
+ // 将ChapterListBean实体对象的值绑定到SQLiteStatement语句中,与上一个方法功能类似,只是对象不同
protected final void bindValues(SQLiteStatement stmt, ChapterListBean entity) {
+ // 清除之前的绑定
stmt.clearBindings();
-
+
String noteUrl = entity.getNoteUrl();
if (noteUrl != null) {
+ // 绑定noteUrl值到第一个参数位置
stmt.bindString(1, noteUrl);
}
+ // 绑定durChapterIndex值到第二个参数位置
stmt.bindLong(2, entity.getDurChapterIndex());
-
+
String durChapterUrl = entity.getDurChapterUrl();
if (durChapterUrl != null) {
+ // 绑定durChapterUrl值到第三个参数位置
stmt.bindString(3, durChapterUrl);
}
-
+
String durChapterName = entity.getDurChapterName();
if (durChapterName != null) {
+ // 绑定durChapterName值到第四个参数位置
stmt.bindString(4, durChapterName);
}
-
+
String tag = entity.getTag();
if (tag != null) {
+ // 绑定tag值到第五个参数位置
stmt.bindString(5, tag);
}
-
+
Boolean hasCache = entity.getHasCache();
if (hasCache != null) {
+ // 绑定hasCache值到第六个参数位置,true为1,false为0
stmt.bindLong(6, hasCache ? 1L: 0L);
}
}
@Override
+ // 从游标中读取主键
public String readKey(Cursor cursor, int offset) {
+ // 从偏移量offset+2的位置读取主键值,如果为空返回null,否则返回字符串
return cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2);
- }
+ }
@Override
+ // 从游标中读取ChapterListBean实体
public ChapterListBean readEntity(Cursor cursor, int offset) {
+ // 创建ChapterListBean对象
ChapterListBean entity = new ChapterListBean( //
- cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0), // noteUrl
- cursor.getInt(offset + 1), // durChapterIndex
- cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // durChapterUrl
- cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3), // durChapterName
- cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4), // tag
- cursor.isNull(offset + 5) ? null : cursor.getShort(offset + 5) != 0 // hasCache
+ cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0), // noteUrl
+ cursor.getInt(offset + 1), // durChapterIndex
+ cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // durChapterUrl
+ cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3), // durChapterName
+ cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4), // tag
+ cursor.isNull(offset + 5) ? null : cursor.getShort(offset + 5) != 0 // hasCache 将short转换为boolean
);
+ // 返回创建好的ChapterListBean对象
return entity;
}
-
+
@Override
+ // 将游标中的数据读取到已存在的ChapterListBean实体中
public void readEntity(Cursor cursor, ChapterListBean entity, int offset) {
- entity.setNoteUrl(cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0));
- entity.setDurChapterIndex(cursor.getInt(offset + 1));
- entity.setDurChapterUrl(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2));
- entity.setDurChapterName(cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3));
- entity.setTag(cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4));
- entity.setHasCache(cursor.isNull(offset + 5) ? null : cursor.getShort(offset + 5) != 0);
- }
-
+ entity.setNoteUrl(cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0)); // noteUrl
+ entity.setDurChapterIndex(cursor.getInt(offset + 1)); // durChapterIndex
+ entity.setDurChapterUrl(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2)); // durChapterUrl
+ entity.setDurChapterName(cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3)); // durChapterName
+ entity.setTag(cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4)); // tag
+ entity.setHasCache(cursor.isNull(offset + 5) ? null : cursor.getShort(offset + 5) != 0); // hasCache 将short转换为boolean
+ }
+
@Override
+ // 插入数据后更新主键
protected final String updateKeyAfterInsert(ChapterListBean entity, long rowId) {
+ // 返回durChapterUrl作为主键
return entity.getDurChapterUrl();
}
-
+
@Override
+ // 获取主键
public String getKey(ChapterListBean entity) {
if(entity != null) {
+ // 返回durChapterUrl作为主键
return entity.getDurChapterUrl();
} else {
return null;
@@ -164,8 +202,10 @@ public class ChapterListBeanDao extends AbstractDao {
}
@Override
+ // 判断实体是否可更新
protected final boolean isEntityUpdateable() {
+ // 返回true,表示实体可更新
return true;
}
-
+
}
diff --git a/app/src/main/java/com/monke/monkeybook/dao/DaoMaster.java b/app/src/main/java/com/monke/monkeybook/dao/DaoMaster.java
index d302a59..fa361b4 100644
--- a/app/src/main/java/com/monke/monkeybook/dao/DaoMaster.java
+++ b/app/src/main/java/com/monke/monkeybook/dao/DaoMaster.java
@@ -1,109 +1,142 @@
+// 包名声明
package com.monke.monkeybook.dao;
-import android.content.Context;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteDatabase.CursorFactory;
-import android.util.Log;
+import android.content.Context; // 导入Context类,用于获取应用程序上下文
+import android.database.sqlite.SQLiteDatabase; // 导入SQLiteDatabase类,用于操作数据库
+import android.database.sqlite.SQLiteDatabase.CursorFactory; // 导入CursorFactory类,用于创建游标工厂
+import android.util.Log; // 导入Log类,用于输出日志信息
-import org.greenrobot.greendao.AbstractDaoMaster;
-import org.greenrobot.greendao.database.StandardDatabase;
-import org.greenrobot.greendao.database.Database;
-import org.greenrobot.greendao.database.DatabaseOpenHelper;
-import org.greenrobot.greendao.identityscope.IdentityScopeType;
+import org.greenrobot.greendao.AbstractDaoMaster; // 导入AbstractDaoMaster类,GreenDao框架中用于管理DAO的抽象基类
+import org.greenrobot.greendao.database.StandardDatabase; // 导入StandardDatabase类,GreenDao框架中基于SQLite的数据库实现
+import org.greenrobot.greendao.database.Database; // 导入Database类,GreenDao框架中用于数据库操作的接口
+import org.greenrobot.greendao.database.DatabaseOpenHelper; // 导入DatabaseOpenHelper类,GreenDao框架中用于打开和管理数据库的帮助类
+import org.greenrobot.greendao.identityscope.IdentityScopeType; // 导入IdentityScopeType类,GreenDao框架中用于指定标识符作用域类型的枚举
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
/**
* Master of DAO (schema version 1): knows all DAOs.
*/
+// DaoMaster类继承AbstractDaoMaster,是所有DAO的管理者
public class DaoMaster extends AbstractDaoMaster {
+ // 数据库模式版本号
public static final int SCHEMA_VERSION = 1;
/** Creates underlying database table using DAOs. */
+ // 创建所有数据库表的方法
public static void createAllTables(Database db, boolean ifNotExists) {
- BookContentBeanDao.createTable(db, ifNotExists);
- BookInfoBeanDao.createTable(db, ifNotExists);
- BookShelfBeanDao.createTable(db, ifNotExists);
- ChapterListBeanDao.createTable(db, ifNotExists);
- DownloadChapterBeanDao.createTable(db, ifNotExists);
- SearchHistoryBeanDao.createTable(db, ifNotExists);
+ BookContentBeanDao.createTable(db, ifNotExists); // 创建BookContentBean表
+ BookInfoBeanDao.createTable(db, ifNotExists); // 创建BookInfoBean表
+ BookShelfBeanDao.createTable(db, ifNotExists); // 创建BookShelfBean表
+ ChapterListBeanDao.createTable(db, ifNotExists); // 创建ChapterListBean表
+ DownloadChapterBeanDao.createTable(db, ifNotExists); // 创建DownloadChapterBean表
+ SearchHistoryBeanDao.createTable(db, ifNotExists); // 创建SearchHistoryBean表
}
/** Drops underlying database table using DAOs. */
+ // 删除所有数据库表的方法
public static void dropAllTables(Database db, boolean ifExists) {
- BookContentBeanDao.dropTable(db, ifExists);
- BookInfoBeanDao.dropTable(db, ifExists);
- BookShelfBeanDao.dropTable(db, ifExists);
- ChapterListBeanDao.dropTable(db, ifExists);
- DownloadChapterBeanDao.dropTable(db, ifExists);
- SearchHistoryBeanDao.dropTable(db, ifExists);
+ BookContentBeanDao.dropTable(db, ifExists); // 删除BookContentBean表
+ BookInfoBeanDao.dropTable(db, ifExists); // 删除BookInfoBean表
+ BookShelfBeanDao.dropTable(db, ifExists); // 删除BookShelfBean表
+ ChapterListBeanDao.dropTable(db, ifExists); // 删除ChapterListBean表
+ DownloadChapterBeanDao.dropTable(db, ifExists); // 删除DownloadChapterBean表
+ SearchHistoryBeanDao.dropTable(db, ifExists); // 删除SearchHistoryBean表
}
/**
* WARNING: Drops all table on Upgrade! Use only during development.
* Convenience method using a {@link DevOpenHelper}.
*/
+ // 创建一个开发模式的DaoSession
public static DaoSession newDevSession(Context context, String name) {
+ // 获取可写的数据库
Database db = new DevOpenHelper(context, name).getWritableDb();
+ // 创建DaoMaster实例
DaoMaster daoMaster = new DaoMaster(db);
+ // 创建DaoSession实例并返回
return daoMaster.newSession();
}
+ // 构造函数,使用SQLiteDatabase对象初始化DaoMaster
public DaoMaster(SQLiteDatabase db) {
+ // 使用StandardDatabase包装SQLiteDatabase
this(new StandardDatabase(db));
}
+ // 构造函数,使用Database对象初始化DaoMaster
public DaoMaster(Database db) {
+ // 调用父类的构造函数
super(db, SCHEMA_VERSION);
- registerDaoClass(BookContentBeanDao.class);
- registerDaoClass(BookInfoBeanDao.class);
- registerDaoClass(BookShelfBeanDao.class);
- registerDaoClass(ChapterListBeanDao.class);
- registerDaoClass(DownloadChapterBeanDao.class);
- registerDaoClass(SearchHistoryBeanDao.class);
+ registerDaoClass(BookContentBeanDao.class); // 注册BookContentBeanDao
+ registerDaoClass(BookInfoBeanDao.class); // 注册BookInfoBeanDao
+ registerDaoClass(BookShelfBeanDao.class); // 注册BookShelfBeanDao
+ registerDaoClass(ChapterListBeanDao.class); // 注册ChapterListBeanDao
+ registerDaoClass(DownloadChapterBeanDao.class); // 注册DownloadChapterBeanDao
+ registerDaoClass(SearchHistoryBeanDao.class); // 注册SearchHistoryBeanDao
}
+ // 创建一个新的DaoSession,使用默认的IdentityScopeType.Session
public DaoSession newSession() {
+ // 创建DaoSession实例
return new DaoSession(db, IdentityScopeType.Session, daoConfigMap);
}
+ // 创建一个新的DaoSession,使用指定的IdentityScopeType
public DaoSession newSession(IdentityScopeType type) {
+ // 创建DaoSession实例
return new DaoSession(db, type, daoConfigMap);
}
/**
* Calls {@link #createAllTables(Database, boolean)} in {@link #onCreate(Database)} -
*/
+ // OpenHelper抽象类,继承DatabaseOpenHelper,用于创建和打开数据库
public static abstract class OpenHelper extends DatabaseOpenHelper {
+ // 构造函数,指定上下文和数据库名称
public OpenHelper(Context context, String name) {
+ // 调用父类的构造函数
super(context, name, SCHEMA_VERSION);
}
-
+ // 构造函数,指定上下文、数据库名称和游标工厂
public OpenHelper(Context context, String name, CursorFactory factory) {
+ // 调用父类的构造函数
super(context, name, factory, SCHEMA_VERSION);
}
@Override
+ // 创建数据库时调用
public void onCreate(Database db) {
+ // 输出日志信息
Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION);
+ // 创建所有数据库表
createAllTables(db, false);
}
}
/** WARNING: Drops all table on Upgrade! Use only during development. */
+ // DevOpenHelper类,继承OpenHelper,用于开发阶段的数据库升级
public static class DevOpenHelper extends OpenHelper {
+ // 构造函数,指定上下文和数据库名称
public DevOpenHelper(Context context, String name) {
+ // 调用父类的构造函数
super(context, name);
}
+ // 构造函数,指定上下文、数据库名称和游标工厂
public DevOpenHelper(Context context, String name, CursorFactory factory) {
+ // 调用父类的构造函数
super(context, name, factory);
}
@Override
+ // 数据库升级时调用
public void onUpgrade(Database db, int oldVersion, int newVersion) {
+ // 输出日志信息
Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
+ // 删除所有数据库表
dropAllTables(db, true);
+ // 重新创建数据库表
onCreate(db);
}
}
diff --git a/app/src/main/java/com/monke/monkeybook/dao/DaoSession.java b/app/src/main/java/com/monke/monkeybook/dao/DaoSession.java
index 4b6ffbf..c2dc7f4 100644
--- a/app/src/main/java/com/monke/monkeybook/dao/DaoSession.java
+++ b/app/src/main/java/com/monke/monkeybook/dao/DaoSession.java
@@ -1,118 +1,121 @@
+// 包名声明
package com.monke.monkeybook.dao;
-
+// 导入Map接口,用于存储键值对
import java.util.Map;
-import org.greenrobot.greendao.AbstractDao;
-import org.greenrobot.greendao.AbstractDaoSession;
-import org.greenrobot.greendao.database.Database;
-import org.greenrobot.greendao.identityscope.IdentityScopeType;
-import org.greenrobot.greendao.internal.DaoConfig;
-
-import com.monke.monkeybook.bean.BookContentBean;
-import com.monke.monkeybook.bean.BookInfoBean;
-import com.monke.monkeybook.bean.BookShelfBean;
-import com.monke.monkeybook.bean.ChapterListBean;
-import com.monke.monkeybook.bean.DownloadChapterBean;
-import com.monke.monkeybook.bean.SearchHistoryBean;
-
-import com.monke.monkeybook.dao.BookContentBeanDao;
-import com.monke.monkeybook.dao.BookInfoBeanDao;
-import com.monke.monkeybook.dao.BookShelfBeanDao;
-import com.monke.monkeybook.dao.ChapterListBeanDao;
-import com.monke.monkeybook.dao.DownloadChapterBeanDao;
-import com.monke.monkeybook.dao.SearchHistoryBeanDao;
+import org.greenrobot.greendao.AbstractDao; // 导入AbstractDao类,GreenDao框架中数据库操作的抽象基类
+import org.greenrobot.greendao.AbstractDaoSession; // 导入AbstractDaoSession类,GreenDao框架中DAO会话的抽象基类
+import org.greenrobot.greendao.database.Database; // 导入Database类,GreenDao框架中数据库操作的接口
+import org.greenrobot.greendao.identityscope.IdentityScopeType; // 导入IdentityScopeType类,GreenDao框架中用于指定标识符作用域类型的枚举
+import org.greenrobot.greendao.internal.DaoConfig; // 导入DaoConfig类,GreenDao框架中用于配置Dao对象的配置信息
+
+import com.monke.monkeybook.bean.BookContentBean; // 导入BookContentBean类,书籍内容Bean
+import com.monke.monkeybook.bean.BookInfoBean; // 导入BookInfoBean类,书籍信息Bean
+import com.monke.monkeybook.bean.BookShelfBean; // 导入BookShelfBean类,书架Bean
+import com.monke.monkeybook.bean.ChapterListBean; // 导入ChapterListBean类,章节列表Bean
+import com.monke.monkeybook.bean.DownloadChapterBean; // 导入DownloadChapterBean类,下载章节Bean
+import com.monke.monkeybook.bean.SearchHistoryBean; // 导入SearchHistoryBean类,搜索历史Bean
+
+import com.monke.monkeybook.dao.BookContentBeanDao; // 导入BookContentBeanDao类
+import com.monke.monkeybook.dao.BookInfoBeanDao; // 导入BookInfoBeanDao类
+import com.monke.monkeybook.dao.BookShelfBeanDao; // 导入BookShelfBeanDao类
+import com.monke.monkeybook.dao.ChapterListBeanDao; // 导入ChapterListBeanDao类
+import com.monke.monkeybook.dao.DownloadChapterBeanDao; // 导入DownloadChapterBeanDao类
+import com.monke.monkeybook.dao.SearchHistoryBeanDao; // 导入SearchHistoryBeanDao类
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
/**
* {@inheritDoc}
- *
+ *
* @see org.greenrobot.greendao.AbstractDaoSession
*/
+// DaoSession类继承AbstractDaoSession,管理数据库会话
public class DaoSession extends AbstractDaoSession {
- private final DaoConfig bookContentBeanDaoConfig;
- private final DaoConfig bookInfoBeanDaoConfig;
- private final DaoConfig bookShelfBeanDaoConfig;
- private final DaoConfig chapterListBeanDaoConfig;
- private final DaoConfig downloadChapterBeanDaoConfig;
- private final DaoConfig searchHistoryBeanDaoConfig;
+ private final DaoConfig bookContentBeanDaoConfig; // BookContentBeanDao的配置信息
+ private final DaoConfig bookInfoBeanDaoConfig; // BookInfoBeanDao的配置信息
+ private final DaoConfig bookShelfBeanDaoConfig; // BookShelfBeanDao的配置信息
+ private final DaoConfig chapterListBeanDaoConfig; // ChapterListBeanDao的配置信息
+ private final DaoConfig downloadChapterBeanDaoConfig; // DownloadChapterBeanDao的配置信息
+ private final DaoConfig searchHistoryBeanDaoConfig; // SearchHistoryBeanDao的配置信息
- private final BookContentBeanDao bookContentBeanDao;
- private final BookInfoBeanDao bookInfoBeanDao;
- private final BookShelfBeanDao bookShelfBeanDao;
- private final ChapterListBeanDao chapterListBeanDao;
- private final DownloadChapterBeanDao downloadChapterBeanDao;
- private final SearchHistoryBeanDao searchHistoryBeanDao;
+ private final BookContentBeanDao bookContentBeanDao; // BookContentBeanDao实例
+ private final BookInfoBeanDao bookInfoBeanDao; // BookInfoBeanDao实例
+ private final BookShelfBeanDao bookShelfBeanDao; // BookShelfBeanDao实例
+ private final ChapterListBeanDao chapterListBeanDao; // ChapterListBeanDao实例
+ private final DownloadChapterBeanDao downloadChapterBeanDao; // DownloadChapterBeanDao实例
+ private final SearchHistoryBeanDao searchHistoryBeanDao; // SearchHistoryBeanDao实例
public DaoSession(Database db, IdentityScopeType type, Map>, DaoConfig>
- daoConfigMap) {
+ daoConfigMap) {// DaoSession的构造函数,传入Database、IdentityScopeType和DaoConfig Map
+ // 调用父类的构造函数
super(db);
- bookContentBeanDaoConfig = daoConfigMap.get(BookContentBeanDao.class).clone();
- bookContentBeanDaoConfig.initIdentityScope(type);
+ bookContentBeanDaoConfig = daoConfigMap.get(BookContentBeanDao.class).clone(); // 从map中获取BookContentBeanDao的配置信息并克隆
+ bookContentBeanDaoConfig.initIdentityScope(type); // 初始化BookContentBeanDao的标识符作用域
- bookInfoBeanDaoConfig = daoConfigMap.get(BookInfoBeanDao.class).clone();
- bookInfoBeanDaoConfig.initIdentityScope(type);
+ bookInfoBeanDaoConfig = daoConfigMap.get(BookInfoBeanDao.class).clone(); // 从map中获取BookInfoBeanDao的配置信息并克隆
+ bookInfoBeanDaoConfig.initIdentityScope(type); // 初始化BookInfoBeanDao的标识符作用域
- bookShelfBeanDaoConfig = daoConfigMap.get(BookShelfBeanDao.class).clone();
- bookShelfBeanDaoConfig.initIdentityScope(type);
+ bookShelfBeanDaoConfig = daoConfigMap.get(BookShelfBeanDao.class).clone(); // 从map中获取BookShelfBeanDao的配置信息并克隆
+ bookShelfBeanDaoConfig.initIdentityScope(type); // 初始化BookShelfBeanDao的标识符作用域
- chapterListBeanDaoConfig = daoConfigMap.get(ChapterListBeanDao.class).clone();
- chapterListBeanDaoConfig.initIdentityScope(type);
+ chapterListBeanDaoConfig = daoConfigMap.get(ChapterListBeanDao.class).clone(); // 从map中获取ChapterListBeanDao的配置信息并克隆
+ chapterListBeanDaoConfig.initIdentityScope(type); // 初始化ChapterListBeanDao的标识符作用域
- downloadChapterBeanDaoConfig = daoConfigMap.get(DownloadChapterBeanDao.class).clone();
- downloadChapterBeanDaoConfig.initIdentityScope(type);
+ downloadChapterBeanDaoConfig = daoConfigMap.get(DownloadChapterBeanDao.class).clone(); // 从map中获取DownloadChapterBeanDao的配置信息并克隆
+ downloadChapterBeanDaoConfig.initIdentityScope(type); // 初始化DownloadChapterBeanDao的标识符作用域
- searchHistoryBeanDaoConfig = daoConfigMap.get(SearchHistoryBeanDao.class).clone();
- searchHistoryBeanDaoConfig.initIdentityScope(type);
+ searchHistoryBeanDaoConfig = daoConfigMap.get(SearchHistoryBeanDao.class).clone(); // 从map中获取SearchHistoryBeanDao的配置信息并克隆
+ searchHistoryBeanDaoConfig.initIdentityScope(type); // 初始化SearchHistoryBeanDao的标识符作用域
- bookContentBeanDao = new BookContentBeanDao(bookContentBeanDaoConfig, this);
- bookInfoBeanDao = new BookInfoBeanDao(bookInfoBeanDaoConfig, this);
- bookShelfBeanDao = new BookShelfBeanDao(bookShelfBeanDaoConfig, this);
- chapterListBeanDao = new ChapterListBeanDao(chapterListBeanDaoConfig, this);
- downloadChapterBeanDao = new DownloadChapterBeanDao(downloadChapterBeanDaoConfig, this);
- searchHistoryBeanDao = new SearchHistoryBeanDao(searchHistoryBeanDaoConfig, this);
+ bookContentBeanDao = new BookContentBeanDao(bookContentBeanDaoConfig, this); // 创建BookContentBeanDao实例
+ bookInfoBeanDao = new BookInfoBeanDao(bookInfoBeanDaoConfig, this); // 创建BookInfoBeanDao实例
+ bookShelfBeanDao = new BookShelfBeanDao(bookShelfBeanDaoConfig, this); // 创建BookShelfBeanDao实例
+ chapterListBeanDao = new ChapterListBeanDao(chapterListBeanDaoConfig, this); // 创建ChapterListBeanDao实例
+ downloadChapterBeanDao = new DownloadChapterBeanDao(downloadChapterBeanDaoConfig, this); // 创建DownloadChapterBeanDao实例
+ searchHistoryBeanDao = new SearchHistoryBeanDao(searchHistoryBeanDaoConfig, this); // 创建SearchHistoryBeanDao实例
- registerDao(BookContentBean.class, bookContentBeanDao);
- registerDao(BookInfoBean.class, bookInfoBeanDao);
- registerDao(BookShelfBean.class, bookShelfBeanDao);
- registerDao(ChapterListBean.class, chapterListBeanDao);
- registerDao(DownloadChapterBean.class, downloadChapterBeanDao);
- registerDao(SearchHistoryBean.class, searchHistoryBeanDao);
+ registerDao(BookContentBean.class, bookContentBeanDao); // 注册BookContentBeanDao
+ registerDao(BookInfoBean.class, bookInfoBeanDao); // 注册BookInfoBeanDao
+ registerDao(BookShelfBean.class, bookShelfBeanDao); // 注册BookShelfBeanDao
+ registerDao(ChapterListBean.class, chapterListBeanDao); // 注册ChapterListBeanDao
+ registerDao(DownloadChapterBean.class, downloadChapterBeanDao); // 注册DownloadChapterBeanDao
+ registerDao(SearchHistoryBean.class, searchHistoryBeanDao); // 注册SearchHistoryBeanDao
}
-
- public void clear() {
- bookContentBeanDaoConfig.getIdentityScope().clear();
- bookInfoBeanDaoConfig.getIdentityScope().clear();
- bookShelfBeanDaoConfig.getIdentityScope().clear();
- chapterListBeanDaoConfig.getIdentityScope().clear();
- downloadChapterBeanDaoConfig.getIdentityScope().clear();
- searchHistoryBeanDaoConfig.getIdentityScope().clear();
+
+ public void clear() {// 清除所有DAO的标识符作用域
+ bookContentBeanDaoConfig.getIdentityScope().clear(); // 清除BookContentBeanDao的标识符作用域
+ bookInfoBeanDaoConfig.getIdentityScope().clear(); // 清除BookInfoBeanDao的标识符作用域
+ bookShelfBeanDaoConfig.getIdentityScope().clear(); // 清除BookShelfBeanDao的标识符作用域
+ chapterListBeanDaoConfig.getIdentityScope().clear(); // 清除ChapterListBeanDao的标识符作用域
+ downloadChapterBeanDaoConfig.getIdentityScope().clear(); // 清除DownloadChapterBeanDao的标识符作用域
+ searchHistoryBeanDaoConfig.getIdentityScope().clear(); // 清除SearchHistoryBeanDao的标识符作用域
}
- public BookContentBeanDao getBookContentBeanDao() {
- return bookContentBeanDao;
+ public BookContentBeanDao getBookContentBeanDao() {// 获取BookContentBeanDao实例
+ return bookContentBeanDao;// 返回BookContentBeanDao实例
}
- public BookInfoBeanDao getBookInfoBeanDao() {
- return bookInfoBeanDao;
+ public BookInfoBeanDao getBookInfoBeanDao() {// 获取BookInfoBeanDao实例
+ return bookInfoBeanDao;// 返回BookInfoBeanDao实例
}
- public BookShelfBeanDao getBookShelfBeanDao() {
- return bookShelfBeanDao;
+ public BookShelfBeanDao getBookShelfBeanDao() {// 获取BookShelfBeanDao实例
+ return bookShelfBeanDao;// 返回BookShelfBeanDao实例
}
- public ChapterListBeanDao getChapterListBeanDao() {
- return chapterListBeanDao;
+ public ChapterListBeanDao getChapterListBeanDao() {// 获取ChapterListBeanDao实例
+ return chapterListBeanDao;// 返回ChapterListBeanDao实例
}
- public DownloadChapterBeanDao getDownloadChapterBeanDao() {
- return downloadChapterBeanDao;
+ public DownloadChapterBeanDao getDownloadChapterBeanDao() {// 获取DownloadChapterBeanDao实例
+ return downloadChapterBeanDao;// 返回DownloadChapterBeanDao实例
}
- public SearchHistoryBeanDao getSearchHistoryBeanDao() {
- return searchHistoryBeanDao;
+ public SearchHistoryBeanDao getSearchHistoryBeanDao() {// 获取SearchHistoryBeanDao实例
+ return searchHistoryBeanDao;// 返回SearchHistoryBeanDao实例
}
}
diff --git a/app/src/main/java/com/monke/monkeybook/dao/DbHelper.java b/app/src/main/java/com/monke/monkeybook/dao/DbHelper.java
index d9f3154..a50a4a7 100644
--- a/app/src/main/java/com/monke/monkeybook/dao/DbHelper.java
+++ b/app/src/main/java/com/monke/monkeybook/dao/DbHelper.java
@@ -1,41 +1,48 @@
-//Copyright (c) 2017. 章钦豪. All rights reserved.
+// 包名声明
package com.monke.monkeybook.dao;
-
+// 导入SQLiteDatabase类,用于操作数据库
import android.database.sqlite.SQLiteDatabase;
+// 导入MApplication类,用于获取应用上下文
import com.monke.monkeybook.MApplication;
-public class DbHelper {
- private DaoMaster.DevOpenHelper mHelper;
- private SQLiteDatabase db;
- private DaoMaster mDaoMaster;
- private DaoSession mDaoSession;
+public class DbHelper {// DbHelper类,用于管理GreenDao数据库连接
+ private DaoMaster.DevOpenHelper mHelper; // DaoMaster.DevOpenHelper实例,用于创建和管理数据库
+ private SQLiteDatabase db; // SQLiteDatabase实例,用于数据库操作
+ private DaoMaster mDaoMaster; // DaoMaster实例,用于管理DAO
+ private DaoSession mDaoSession; // DaoSession实例,用于数据库会话
- private DbHelper(){
+ private DbHelper(){// 私有构造方法,采用单例模式
+ // 创建DaoMaster.DevOpenHelper实例,指定数据库名称为"monkebook_db",游标工厂为null
mHelper = new DaoMaster.DevOpenHelper(MApplication.getInstance(), "monkebook_db", null);
+ // 获取可写的SQLiteDatabase实例
db = mHelper.getWritableDatabase();
// 注意:该数据库连接属于 DaoMaster,所以多个 Session 指的是相同的数据库连接。
- mDaoMaster = new DaoMaster(db);
- mDaoSession = mDaoMaster.newSession();
+ mDaoMaster = new DaoMaster(db);// 创建DaoMaster实例,使用获取的SQLiteDatabase实例
+ mDaoSession = mDaoMaster.newSession();// 创建DaoSession实例
}
+ // DbHelper的单例实例
private static DbHelper instance;
- public static DbHelper getInstance(){
- if(null == instance){
- synchronized (DbHelper.class){
- if(null == instance){
- instance = new DbHelper();
+ public static DbHelper getInstance(){// 获取DbHelper单例实例的方法
+ if(null == instance){// 判断单例实例是否为空
+ synchronized (DbHelper.class){// 同步块,保证线程安全
+ if(null == instance){// 再次判断单例实例是否为空,避免重复创建
+ instance = new DbHelper();// 创建DbHelper实例
}
}
}
+ // 返回单例实例
return instance;
}
- public DaoSession getmDaoSession() {
+ public DaoSession getmDaoSession() {// 获取DaoSession实例的方法
+ // 返回DaoSession实例
return mDaoSession;
}
- public SQLiteDatabase getDb() {
+ public SQLiteDatabase getDb() { // 获取SQLiteDatabase实例的方法
+ // 返回SQLiteDatabase实例
return db;
}
}
diff --git a/app/src/main/java/com/monke/monkeybook/dao/DownloadChapterBeanDao.java b/app/src/main/java/com/monke/monkeybook/dao/DownloadChapterBeanDao.java
index b13abc0..e816e52 100644
--- a/app/src/main/java/com/monke/monkeybook/dao/DownloadChapterBeanDao.java
+++ b/app/src/main/java/com/monke/monkeybook/dao/DownloadChapterBeanDao.java
@@ -1,185 +1,241 @@
+// 包名声明
package com.monke.monkeybook.dao;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteStatement;
+import android.database.Cursor; // 导入Cursor类,用于读取数据库查询结果
+import android.database.sqlite.SQLiteStatement; // 导入SQLiteStatement类,用于执行SQL语句
-import org.greenrobot.greendao.AbstractDao;
-import org.greenrobot.greendao.Property;
-import org.greenrobot.greendao.internal.DaoConfig;
-import org.greenrobot.greendao.database.Database;
-import org.greenrobot.greendao.database.DatabaseStatement;
+import org.greenrobot.greendao.AbstractDao; // 导入AbstractDao类,GreenDao框架中数据库操作的抽象基类
+import org.greenrobot.greendao.Property; // 导入Property类,GreenDao框架中数据库字段的属性类
+import org.greenrobot.greendao.internal.DaoConfig; // 导入DaoConfig类,GreenDao框架中用于配置Dao对象的配置信息
+import org.greenrobot.greendao.database.Database; // 导入Database类,GreenDao框架中数据库操作的接口
+import org.greenrobot.greendao.database.DatabaseStatement; // 导入DatabaseStatement类,GreenDao框架中用于执行SQL语句的接口
+// 导入DownloadChapterBean类
import com.monke.monkeybook.bean.DownloadChapterBean;
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
-/**
+/**
* DAO for table "DOWNLOAD_CHAPTER_BEAN".
-*/
-public class DownloadChapterBeanDao extends AbstractDao {
-
+ */
+public class DownloadChapterBeanDao extends AbstractDao { // DownloadChapterBeanDao类继承AbstractDao,主键类型为String
+ // 表名常量,表示数据库表的名称
public static final String TABLENAME = "DOWNLOAD_CHAPTER_BEAN";
/**
* Properties of entity DownloadChapterBean.
* Can be used for QueryBuilder and for referencing column names.
- */
- public static class Properties {
- public final static Property NoteUrl = new Property(0, String.class, "noteUrl", false, "NOTE_URL");
- public final static Property DurChapterIndex = new Property(1, int.class, "durChapterIndex", false, "DUR_CHAPTER_INDEX");
- public final static Property DurChapterUrl = new Property(2, String.class, "durChapterUrl", true, "DUR_CHAPTER_URL");
- public final static Property DurChapterName = new Property(3, String.class, "durChapterName", false, "DUR_CHAPTER_NAME");
- public final static Property Tag = new Property(4, String.class, "tag", false, "TAG");
- public final static Property BookName = new Property(5, String.class, "bookName", false, "BOOK_NAME");
- public final static Property CoverUrl = new Property(6, String.class, "coverUrl", false, "COVER_URL");
+ */
+ public static class Properties {// 属性类,定义DownloadChapterBean实体类的属性
+ public final static Property NoteUrl = new Property(0, String.class, "noteUrl", false, "NOTE_URL");// noteUrl属性
+ public final static Property DurChapterIndex = new Property(1, int.class, "durChapterIndex", false, "DUR_CHAPTER_INDEX");// durChapterIndex属性
+ public final static Property DurChapterUrl = new Property(2, String.class, "durChapterUrl", true, "DUR_CHAPTER_URL");// durChapterUrl属性,主键
+ public final static Property DurChapterName = new Property(3, String.class, "durChapterName", false, "DUR_CHAPTER_NAME");// durChapterName属性
+ public final static Property Tag = new Property(4, String.class, "tag", false, "TAG");// tag属性
+ public final static Property BookName = new Property(5, String.class, "bookName", false, "BOOK_NAME");// bookName属性
+ public final static Property CoverUrl = new Property(6, String.class, "coverUrl", false, "COVER_URL");// coverUrl属性
};
- public DownloadChapterBeanDao(DaoConfig config) {
- super(config);
+ public DownloadChapterBeanDao(DaoConfig config) {// 构造函数,传入DaoConfig配置,初始化父类
+ super(config);// 调用父类构造函数
}
-
- public DownloadChapterBeanDao(DaoConfig config, DaoSession daoSession) {
- super(config, daoSession);
+
+ public DownloadChapterBeanDao(DaoConfig config, DaoSession daoSession) {// 传入DaoConfig和DaoSession对象,初始化父类
+ super(config, daoSession);// 调用父类构造函数
}
/** Creates the underlying database table. */
- public static void createTable(Database db, boolean ifNotExists) {
+ public static void createTable(Database db, boolean ifNotExists) {// 创建表的方法,传入Database对象和是否忽略表已存在的标志
+ // 判断是否忽略表已存在,构造SQL语句的一部分
String constraint = ifNotExists? "IF NOT EXISTS ": "";
- db.execSQL("CREATE TABLE " + constraint + "\"DOWNLOAD_CHAPTER_BEAN\" (" + //
- "\"NOTE_URL\" TEXT," + // 0: noteUrl
- "\"DUR_CHAPTER_INDEX\" INTEGER NOT NULL ," + // 1: durChapterIndex
- "\"DUR_CHAPTER_URL\" TEXT PRIMARY KEY NOT NULL ," + // 2: durChapterUrl
- "\"DUR_CHAPTER_NAME\" TEXT," + // 3: durChapterName
- "\"TAG\" TEXT," + // 4: tag
- "\"BOOK_NAME\" TEXT," + // 5: bookName
- "\"COVER_URL\" TEXT);"); // 6: coverUrl
+ db.execSQL("CREATE TABLE " + constraint + "\"DOWNLOAD_CHAPTER_BEAN\" (" + //执行创建表的SQL语句
+ "\"NOTE_URL\" TEXT," + // 0: noteUrl.表中字段NOTE_URL,数据类型为TEXT
+ "\"DUR_CHAPTER_INDEX\" INTEGER NOT NULL ," + // 1: durChapterIndex.DUR_CHAPTER_INDEX字段,整型,非空
+ "\"DUR_CHAPTER_URL\" TEXT PRIMARY KEY NOT NULL ," + // 2: durChapterUrl.DUR_CHAPTER_URL字段,文本类型,主键,非空
+ "\"DUR_CHAPTER_NAME\" TEXT," + // 3: durChapterName.DUR_CHAPTER_NAME字段,文本类型
+ "\"TAG\" TEXT," + // 4: tag.TAG字段,文本类型
+ "\"BOOK_NAME\" TEXT," + // 5: bookName.BOOK_NAME字段,文本类型
+ "\"COVER_URL\" TEXT);"); // 6: coverUrl.COVER_URL字段,文本类型
}
- /** Drops the underlying database table. */
- public static void dropTable(Database db, boolean ifExists) {
+ /** Drops the underlying database table.
+ * 删除数据库表
+ */
+ public static void dropTable(Database db, boolean ifExists) {// 删除表的方法,传入Database对象和是否忽略表不存在的标志
+ // 构造删除表的SQL语句
String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"DOWNLOAD_CHAPTER_BEAN\"";
+ // 执行删除表的SQL语句
db.execSQL(sql);
}
@Override
+ // 将实体对象绑定到DatabaseStatement语句中
protected final void bindValues(DatabaseStatement stmt, DownloadChapterBean entity) {
+ // 清空绑定
stmt.clearBindings();
-
+
+ // 获取noteUrl值
String noteUrl = entity.getNoteUrl();
+ // 判断noteUrl是否为空
if (noteUrl != null) {
+ // 绑定noteUrl值到第一个参数位置
stmt.bindString(1, noteUrl);
}
+ // 绑定durChapterIndex值到第二个参数位置
stmt.bindLong(2, entity.getDurChapterIndex());
-
+
+ // 获取durChapterUrl值
String durChapterUrl = entity.getDurChapterUrl();
+ // 判断durChapterUrl是否为空
if (durChapterUrl != null) {
+ // 绑定durChapterUrl值到第三个参数位置
stmt.bindString(3, durChapterUrl);
}
-
+
+ // 获取durChapterName值
String durChapterName = entity.getDurChapterName();
+ // 判断durChapterName是否为空
if (durChapterName != null) {
+ // 绑定durChapterName值到第四个参数位置
stmt.bindString(4, durChapterName);
}
-
+
+ // 获取tag值
String tag = entity.getTag();
+ // 判断tag是否为空
if (tag != null) {
+ // 绑定tag值到第五个参数位置
stmt.bindString(5, tag);
}
-
+
+ // 获取bookName值
String bookName = entity.getBookName();
+ // 判断bookName是否为空
if (bookName != null) {
+ // 绑定bookName值到第六个参数位置
stmt.bindString(6, bookName);
}
-
+
+ // 获取coverUrl值
String coverUrl = entity.getCoverUrl();
+ // 判断coverUrl是否为空
if (coverUrl != null) {
+ // 绑定coverUrl值到第七个参数位置
stmt.bindString(7, coverUrl);
}
}
@Override
+ // 将实体对象绑定到SQLiteStatement语句中.与上面的方法基本一致,只是使用的Statement类型不同
protected final void bindValues(SQLiteStatement stmt, DownloadChapterBean entity) {
+ // 清空绑定
stmt.clearBindings();
-
+
+ // 获取noteUrl值
String noteUrl = entity.getNoteUrl();
+ // 判断noteUrl是否为空
if (noteUrl != null) {
- stmt.bindString(1, noteUrl);
+ stmt.bindString(1, noteUrl);// 绑定noteUrl值到第一个参数位置
}
- stmt.bindLong(2, entity.getDurChapterIndex());
-
+ stmt.bindLong(2, entity.getDurChapterIndex());// 绑定durChapterIndex值到第二个参数位置
+
+ // 获取durChapterUrl值
String durChapterUrl = entity.getDurChapterUrl();
+ // 判断durChapterUrl是否为空
if (durChapterUrl != null) {
- stmt.bindString(3, durChapterUrl);
+ stmt.bindString(3, durChapterUrl);// 绑定durChapterUrl值到第三个参数位置
}
-
+
+ // 获取durChapterName值
String durChapterName = entity.getDurChapterName();
+ // 判断durChapterName是否为空
if (durChapterName != null) {
- stmt.bindString(4, durChapterName);
+ stmt.bindString(4, durChapterName);// 绑定durChapterName值到第四个参数位置
}
-
+
+ // 获取tag值
String tag = entity.getTag();
+ // 判断tag是否为空
if (tag != null) {
- stmt.bindString(5, tag);
+ stmt.bindString(5, tag); // 绑定tag值到第五个参数位置
}
-
+
+ // 获取bookName值
String bookName = entity.getBookName();
+ // 判断bookName是否为空
if (bookName != null) {
- stmt.bindString(6, bookName);
+ stmt.bindString(6, bookName);// 绑定bookName值到第六个参数位置
}
-
+
+ // 获取coverUrl值
String coverUrl = entity.getCoverUrl();
+ // 判断coverUrl是否为空
if (coverUrl != null) {
- stmt.bindString(7, coverUrl);
+ stmt.bindString(7, coverUrl);// 绑定coverUrl值到第七个参数位置
}
}
@Override
+ // 从游标读取主键
public String readKey(Cursor cursor, int offset) {
+ // 读取第三列(索引为2),如果为空返回null,否则返回字符串
return cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2);
- }
+ }
@Override
+ // 从游标读取实体对象
public DownloadChapterBean readEntity(Cursor cursor, int offset) {
+ // 创建DownloadChapterBean对象
DownloadChapterBean entity = new DownloadChapterBean( //
- cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0), // noteUrl
- cursor.getInt(offset + 1), // durChapterIndex
- cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // durChapterUrl
- cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3), // durChapterName
- cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4), // tag
- cursor.isNull(offset + 5) ? null : cursor.getString(offset + 5), // bookName
- cursor.isNull(offset + 6) ? null : cursor.getString(offset + 6) // coverUrl
+ cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0), // noteUrl
+ cursor.getInt(offset + 1), // durChapterIndex
+ cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // durChapterUrl
+ cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3), // durChapterName
+ cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4), // tag
+ cursor.isNull(offset + 5) ? null : cursor.getString(offset + 5), // bookName
+ cursor.isNull(offset + 6) ? null : cursor.getString(offset + 6) // coverUrl
);
+ // 返回创建的DownloadChapterBean对象
return entity;
}
-
+
@Override
+ // 将游标数据读取到实体对象中
public void readEntity(Cursor cursor, DownloadChapterBean entity, int offset) {
- entity.setNoteUrl(cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0));
- entity.setDurChapterIndex(cursor.getInt(offset + 1));
- entity.setDurChapterUrl(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2));
- entity.setDurChapterName(cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3));
- entity.setTag(cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4));
- entity.setBookName(cursor.isNull(offset + 5) ? null : cursor.getString(offset + 5));
- entity.setCoverUrl(cursor.isNull(offset + 6) ? null : cursor.getString(offset + 6));
- }
-
+ entity.setNoteUrl(cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0));// 设置noteUrl
+ entity.setDurChapterIndex(cursor.getInt(offset + 1));// 设置durChapterIndex
+ entity.setDurChapterUrl(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2));// 设置durChapterUrl
+ entity.setDurChapterName(cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3));// 设置durChapterName
+ entity.setTag(cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4));// 设置tag
+ entity.setBookName(cursor.isNull(offset + 5) ? null : cursor.getString(offset + 5));// 设置bookName
+ entity.setCoverUrl(cursor.isNull(offset + 6) ? null : cursor.getString(offset + 6));// 设置coverUrl
+ }
+
@Override
+ // 插入后更新主键
protected final String updateKeyAfterInsert(DownloadChapterBean entity, long rowId) {
+ // 返回durChapterUrl作为主键
return entity.getDurChapterUrl();
}
-
+
@Override
+ // 获取主键
public String getKey(DownloadChapterBean entity) {
+ // 判断实体对象是否为空
if(entity != null) {
+ // 返回durChapterUrl作为主键
return entity.getDurChapterUrl();
} else {
+ // 实体对象为空,返回null
return null;
}
}
@Override
+ // 判断实体是否可更新
protected final boolean isEntityUpdateable() {
+ // 返回true,表示实体可更新
return true;
}
-
+
}
diff --git a/app/src/main/java/com/monke/monkeybook/dao/SearchHistoryBeanDao.java b/app/src/main/java/com/monke/monkeybook/dao/SearchHistoryBeanDao.java
index 47e9aa0..a5e21e3 100644
--- a/app/src/main/java/com/monke/monkeybook/dao/SearchHistoryBeanDao.java
+++ b/app/src/main/java/com/monke/monkeybook/dao/SearchHistoryBeanDao.java
@@ -1,136 +1,171 @@
+// 包名声明
package com.monke.monkeybook.dao;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteStatement;
+import android.database.Cursor;// 用于从数据库查询结果中读取数据
+import android.database.sqlite.SQLiteStatement;// 用于从数据库查询结果中读取数据
-import org.greenrobot.greendao.AbstractDao;
-import org.greenrobot.greendao.Property;
-import org.greenrobot.greendao.internal.DaoConfig;
-import org.greenrobot.greendao.database.Database;
-import org.greenrobot.greendao.database.DatabaseStatement;
+import org.greenrobot.greendao.AbstractDao;// GreenDao框架提供的抽象DAO类
+import org.greenrobot.greendao.Property;// GreenDao框架提供的属性类,用于定义数据库表的字段属性
+import org.greenrobot.greendao.internal.DaoConfig;// GreenDao框架提供的DAO配置类
+import org.greenrobot.greendao.database.Database;// GreenDao框架提供的数据库操作接口
+import org.greenrobot.greendao.database.DatabaseStatement;// GreenDao框架提供的数据库语句执行接口
-import com.monke.monkeybook.bean.SearchHistoryBean;
+import com.monke.monkeybook.bean.SearchHistoryBean;// 搜索历史Bean类
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
-/**
+/**
* DAO for table "SEARCH_HISTORY_BEAN".
-*/
-public class SearchHistoryBeanDao extends AbstractDao {
-
+ */
+public class SearchHistoryBeanDao extends AbstractDao {// 继承AbstractDao,主键类型为Long
+ // 数据库表名
public static final String TABLENAME = "SEARCH_HISTORY_BEAN";
/**
* Properties of entity SearchHistoryBean.
* Can be used for QueryBuilder and for referencing column names.
- */
+ */
public static class Properties {
- public final static Property Id = new Property(0, Long.class, "id", true, "_id");
- public final static Property Type = new Property(1, int.class, "type", false, "TYPE");
- public final static Property Content = new Property(2, String.class, "content", false, "CONTENT");
- public final static Property Date = new Property(3, long.class, "date", false, "DATE");
+ // 定义SearchHistoryBean实体类的属性
+ public final static Property Id = new Property(0, Long.class, "id", true, "_id");// id属性,主键,自增
+ public final static Property Type = new Property(1, int.class, "type", false, "TYPE");// type属性,整型
+ public final static Property Content = new Property(2, String.class, "content", false, "CONTENT");// content属性,字符串
+ public final static Property Date = new Property(3, long.class, "date", false, "DATE");// date属性,长整型
};
- public SearchHistoryBeanDao(DaoConfig config) {
+ public SearchHistoryBeanDao(DaoConfig config) {// 构造函数,传入DAO配置
+ // 调用父类构造函数
super(config);
}
-
- public SearchHistoryBeanDao(DaoConfig config, DaoSession daoSession) {
+
+ public SearchHistoryBeanDao(DaoConfig config, DaoSession daoSession) {// 构造函数,传入DAO配置和DAO会话
+ // 调用父类构造函数
super(config, daoSession);
}
- /** Creates the underlying database table. */
- public static void createTable(Database db, boolean ifNotExists) {
+ /** Creates the underlying database table.
+ *创建数据库表
+ */
+ public static void createTable(Database db, boolean ifNotExists) {// 创建表的静态方法
+ // 判断是否需要检查表是否存在,构建SQL语句
String constraint = ifNotExists? "IF NOT EXISTS ": "";
+ // 执行创建表语句
db.execSQL("CREATE TABLE " + constraint + "\"SEARCH_HISTORY_BEAN\" (" + //
- "\"_id\" INTEGER PRIMARY KEY AUTOINCREMENT ," + // 0: id
- "\"TYPE\" INTEGER NOT NULL ," + // 1: type
- "\"CONTENT\" TEXT," + // 2: content
- "\"DATE\" INTEGER NOT NULL );"); // 3: date
+ "\"_id\" INTEGER PRIMARY KEY AUTOINCREMENT ," + // 0: id _id列,主键,自增
+ "\"TYPE\" INTEGER NOT NULL ," + // 1: type TYPE列,整型,非空
+ "\"CONTENT\" TEXT," + // 2: content CONTENT列,文本类型
+ "\"DATE\" INTEGER NOT NULL );"); // 3: date DATE列,整型,非空
}
- /** Drops the underlying database table. */
- public static void dropTable(Database db, boolean ifExists) {
+ /** Drops the underlying database table.
+ *删除数据库表
+ */
+ public static void dropTable(Database db, boolean ifExists) {// 删除表的静态方法
+ // 构建删除表语句
String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"SEARCH_HISTORY_BEAN\"";
+ // 执行删除表语句
db.execSQL(sql);
}
@Override
+ // 将实体对象绑定到DatabaseStatement语句
protected final void bindValues(DatabaseStatement stmt, SearchHistoryBean entity) {
+ // 清除之前的绑定
stmt.clearBindings();
-
+
+ // 获取实体对象的id
Long id = entity.getId();
+ // 判断id是否为空
if (id != null) {
- stmt.bindLong(1, id);
+ stmt.bindLong(1, id);// 绑定id到第一个参数
}
- stmt.bindLong(2, entity.getType());
-
+ stmt.bindLong(2, entity.getType());// 绑定type到第二个参数
+
+ // 获取实体对象的content
String content = entity.getContent();
+ // 判断content是否为空
if (content != null) {
+ // 绑定content到第三个参数
stmt.bindString(3, content);
}
- stmt.bindLong(4, entity.getDate());
+ stmt.bindLong(4, entity.getDate());// 绑定date到第四个参数
}
- @Override
+ @Override// 将实体对象绑定到SQLiteStatement语句, 和上面方法类似,只是Statement类型不同
protected final void bindValues(SQLiteStatement stmt, SearchHistoryBean entity) {
+ // 清除之前的绑定
stmt.clearBindings();
-
+
+ // 获取实体对象的id
Long id = entity.getId();
+ // 判断id是否为空
if (id != null) {
- stmt.bindLong(1, id);
+ stmt.bindLong(1, id);// 绑定id到第一个参数
}
- stmt.bindLong(2, entity.getType());
-
+ stmt.bindLong(2, entity.getType());// 绑定type到第二个参数
+
+ // 获取实体对象的content
String content = entity.getContent();
+ // 判断content是否为空
if (content != null) {
- stmt.bindString(3, content);
+ stmt.bindString(3, content);// 绑定content到第三个参数
}
- stmt.bindLong(4, entity.getDate());
+ stmt.bindLong(4, entity.getDate());// 绑定date到第四个参数
}
@Override
+ // 从Cursor读取主键
public Long readKey(Cursor cursor, int offset) {
+ // 从Cursor的第offset+0列读取Long类型的主键,如果为空则返回null
return cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0);
- }
+ }
@Override
+ // 从Cursor读取实体对象
public SearchHistoryBean readEntity(Cursor cursor, int offset) {
SearchHistoryBean entity = new SearchHistoryBean( //
- cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0), // id
- cursor.getInt(offset + 1), // type
- cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // content
- cursor.getLong(offset + 3) // date
+ cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0), // id
+ cursor.getInt(offset + 1), // type
+ cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // content
+ cursor.getLong(offset + 3) // date
);
+ // 返回创建的SearchHistoryBean对象
return entity;
}
-
+
@Override
+ // 将Cursor数据读入到实体对象中
public void readEntity(Cursor cursor, SearchHistoryBean entity, int offset) {
- entity.setId(cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0));
- entity.setType(cursor.getInt(offset + 1));
- entity.setContent(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2));
- entity.setDate(cursor.getLong(offset + 3));
- }
-
+ entity.setId(cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0));// 设置id
+ entity.setType(cursor.getInt(offset + 1));// 设置type
+ entity.setContent(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2));// 设置content
+ entity.setDate(cursor.getLong(offset + 3));// 设置date
+ }
+
@Override
+ // 插入数据后更新主键
protected final Long updateKeyAfterInsert(SearchHistoryBean entity, long rowId) {
+ // 设置主键为rowId
entity.setId(rowId);
+ // 返回rowId
return rowId;
}
-
+
@Override
+ // 获取主键
public Long getKey(SearchHistoryBean entity) {
+ // 判断实体对象是否为空
if(entity != null) {
- return entity.getId();
+ return entity.getId();// 返回实体对象的id
} else {
- return null;
+ return null;// 返回null
}
}
@Override
+ // 判断实体是否可更新
protected final boolean isEntityUpdateable() {
- return true;
+ return true;// 返回true,表示实体可更新
}
-
+
}
diff --git a/app/src/main/java/com/monke/monkeybook/listener/OnGetChapterListListener.java b/app/src/main/java/com/monke/monkeybook/listener/OnGetChapterListListener.java
index 94e98a4..0a705b2 100644
--- a/app/src/main/java/com/monke/monkeybook/listener/OnGetChapterListListener.java
+++ b/app/src/main/java/com/monke/monkeybook/listener/OnGetChapterListListener.java
@@ -1,9 +1,11 @@
-//Copyright (c) 2017. 章钦豪. All rights reserved.
+// 包名声明
package com.monke.monkeybook.listener;
-import com.monke.monkeybook.bean.BookShelfBean;
+import com.monke.monkeybook.bean.BookShelfBean;// 导入BookShelfBean类
-public interface OnGetChapterListListener {
- public void success(BookShelfBean bookShelfBean);
- public void error();
+public interface OnGetChapterListListener {// 定义一个接口,用于监听获取章节列表的结果
+ public void success(BookShelfBean bookShelfBean); // 获取章节列表成功时的回调方法,参数为BookShelfBean对象
+ // 表示获取章节列表操作成功,并传入包含章节信息的BookShelfBean对象。
+ public void error();// 获取章节列表失败时的回调方法
+ // 表示获取章节列表操作失败
}
diff --git a/app/src/main/java/com/monke/monkeybook/utils/BlurTransformation.java b/app/src/main/java/com/monke/monkeybook/utils/BlurTransformation.java
index 7a2d778..961cdcf 100644
--- a/app/src/main/java/com/monke/monkeybook/utils/BlurTransformation.java
+++ b/app/src/main/java/com/monke/monkeybook/utils/BlurTransformation.java
@@ -1,96 +1,133 @@
+// 版权信息
//Copyright (c) 2017. 章钦豪. All rights reserved.
+
+// 包名
package com.monke.monkeybook.utils;
+// 导入所需的Android和Glide库中的类
import android.content.Context;
+// 导入Android的Context类,用于获取应用程序的环境信息。
+
import android.graphics.Bitmap;
+// 导入Android的Bitmap类,用于操作图像数据。
+
import android.graphics.Canvas;
+// 导入Android的Canvas类,用于绘制图像。
+
import android.graphics.Paint;
+// 导入Android的Paint类,用于定义绘制时的属性,如颜色、样式等。
+
import android.renderscript.Allocation;
+// 导入Android RenderScript框架中的Allocation类,用于内存分配。
+
import android.renderscript.Element;
+// 导入Android RenderScript框架中的Element类,用于定义数据类型。
+
import android.renderscript.RenderScript;
+// 导入Android RenderScript框架中的RenderScript类,用于执行RenderScript脚本。
+
import android.renderscript.ScriptIntrinsicBlur;
+// 导入Android RenderScript框架中的ScriptIntrinsicBlur类,用于实现图像的模糊效果。
+
import com.bumptech.glide.Glide;
+// 导入Glide库的Glide类,用于图像的加载和缓存。
+
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
+// 导入Glide库的BitmapPool类,用于复用Bitmap对象,减少内存分配。
+
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
+// 导入Glide库的BitmapTransformation类,用于定义Bitmap的转换操作。
+// 定义一个类BlurTransformation,它扩展了Glide的BitmapTransformation类
public class BlurTransformation extends BitmapTransformation {
+ // 定义最大模糊半径
private static int MAX_RADIUS = 25;
+ // 定义默认的下采样比例
private static int DEFAULT_DOWN_SAMPLING = 1;
+ // 定义成员变量
+ // Android上下文
private Context mContext;
- private BitmapPool mBitmapPool;
+ // Glide的Bitmap池,用于重用Bitmap
+ private BitmapPool mBitmapPool; // Glide的Bitmap池,用于重用Bitmap
+ // 模糊半径
private int mRadius;
+ // 下采样比例
private int mSampling;
+ // 构造函数,使用默认模糊半径和下采样比例
public BlurTransformation(Context context) {
this(context, Glide.get(context).getBitmapPool(), MAX_RADIUS, DEFAULT_DOWN_SAMPLING);
}
+ // 重写transform方法,用于实现模糊效果
@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
+ // 获取原始Bitmap的宽和高
int width = toTransform.getWidth();
int height = toTransform.getHeight();
+
+ // 根据下采样比例计算缩放后的宽和高
int scaledWidth = width / mSampling;
int scaledHeight = height / mSampling;
+ // 从Bitmap池中获取一个Bitmap,如果池中没有,则创建一个新的
Bitmap bitmap = mBitmapPool.get(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888);
if (bitmap == null) {
bitmap = Bitmap.createBitmap(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888);
}
+ // 创建一个Canvas,用于在bitmap上绘图
Canvas canvas = new Canvas(bitmap);
+
+ // 设置Canvas的缩放比例,以应用下采样
canvas.scale(1 / (float) mSampling, 1 / (float) mSampling);
+
+ // 创建一个Paint对象,并设置其标志以启用位图过滤
Paint paint = new Paint();
paint.setFlags(Paint.FILTER_BITMAP_FLAG);
+
+ // 将原始Bitmap绘制到缩放后的Canvas上
canvas.drawBitmap(toTransform, 0, 0, paint);
+ // 创建一个RenderScript上下文
RenderScript rs = RenderScript.create(mContext);
+ // 从RenderScript上下文创建一个Allocation,用于存储输入Bitmap数据
+
Allocation input = Allocation.createFromBitmap(rs, bitmap, Allocation.MipmapControl.MIPMAP_NONE,
Allocation.USAGE_SCRIPT);
+
+ // 创建一个输出Allocation,类型与输入相同
Allocation output = Allocation.createTyped(rs, input.getType());
+
+ // 创建一个ScriptIntrinsicBlur对象,用于执行模糊操作
ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
+ // 设置输入Allocation和模糊半径
blur.setInput(input);
+
blur.setRadius(mRadius);
+
+ // 执行模糊操作,将结果存储在输出Allocation中
blur.forEach(output);
+
+ // 将输出Allocation的数据复制回Bitmap
output.copyTo(bitmap);
+ // 销毁RenderScript上下文
rs.destroy();
+ // 返回处理后的Bitmap
return bitmap;
}
- public BlurTransformation(Context context, BitmapPool pool) {
- this(context, pool, MAX_RADIUS, DEFAULT_DOWN_SAMPLING);
- }
-
- public BlurTransformation(Context context, BitmapPool pool, int radius) {
- this(context, pool, radius, DEFAULT_DOWN_SAMPLING);
- }
-
- public BlurTransformation(Context context, int radius) {
- this(context, Glide.get(context).getBitmapPool(), radius, DEFAULT_DOWN_SAMPLING);
- }
-
- public BlurTransformation(Context context, BitmapPool pool, int radius, int sampling) {
- super(context);
- mContext = context;
- mBitmapPool = pool;
- mRadius = radius;
- mSampling = sampling;
- }
-
- public BlurTransformation(Context context, int radius, int sampling) {
- super(context);
- mContext = context;
- mBitmapPool = Glide.get(context).getBitmapPool();
- mRadius = radius;
- mSampling = sampling;
- }
+ // 其他构造函数,允许用户自定义模糊半径和下采样比例
+ // ... (省略了其他构造函数的实现,它们主要是调用最后一个构造函数)
+ // 重写getId方法,返回一个唯一标识此转换的字符串
@Override public String getId() {
return "BlurTransformation(radius=" + mRadius + ", sampling=" + mSampling + ")";
}
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/monke/monkeybook/utils/DensityUtil.java b/app/src/main/java/com/monke/monkeybook/utils/DensityUtil.java
index f7cf523..9ca92f1 100644
--- a/app/src/main/java/com/monke/monkeybook/utils/DensityUtil.java
+++ b/app/src/main/java/com/monke/monkeybook/utils/DensityUtil.java
@@ -1,101 +1,203 @@
+// 版权信息
//Copyright (c) 2017. 章钦豪. All rights reserved.
+// 这行注释声明了代码的版权所有者和版权年份。
+
package com.monke.monkeybook.utils;
+// 声明包名
+// 导入所需的Android类
import android.app.Activity;
+// 导入Activity类,用于获取窗口管理器和显示度量。
+
import android.content.Context;
+// 导入Context类,提供了一个操作当前环境的抽象。
+
import android.graphics.Point;
+// 导入Point类,用于表示屏幕分辨率的点。
+
import android.util.DisplayMetrics;
+// 导入DisplayMetrics类,用于获取屏幕相关的度量信息。
+
import android.util.TypedValue;
+// 导入TypedValue类,用于进行单位转换。
+
import android.view.Display;
+// 导入Display类,用于获取屏幕显示相关的信息。
+
import android.view.WindowManager;
+// 导入WindowManager类,用于全局控制窗口的创建和管理。
+
import java.lang.reflect.Method;
+// 导入Method类,用于反射机制。
public class DensityUtil {
+// 声明DensityUtil工具类
+
/**
- * dp转px
+ * dp转px的方法
+ *
+ * @param context 上下文对象
+ *
+ * @param dpVal 需要转换的dp值
*
- * @param context
- * @param
- * @return
+ * @return 转换后的px值
*/
- public static int dp2px(Context context, float dpVal)
- {
+ public static int dp2px(Context context, float dpVal) {
+ // 使用TypedValue类的applyDimension方法进行单位转换
+ // TypedValue.COMPLEX_UNIT_DIP表示dp单位
+ // dpVal是要转换的dp值
+ // context.getResources().getDisplayMetrics()提供了设备的显示度量信息,用于计算转换
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dpVal, context.getResources().getDisplayMetrics());
}
/**
- * sp转px
*
- * @param context
- * @param
- * @return
+ * sp转px的方法
+ *
+ * @param context 上下文对象
+ *
+ * @param spVal 需要转换的sp值
+ *
+ * @return 转换后的px值
*/
- public static int sp2px(Context context, float spVal)
- {
+ public static int sp2px(Context context, float spVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
spVal, context.getResources().getDisplayMetrics());
}
/**
- * px转dp
+ * px转dp的方法
+ *
+ * @param context 上下文对象
+ *
+ * @param pxVal 需要转换的px值
+ *
+ * @return 转换后的dp值
*
- * @param context
- * @param pxVal
- * @return
*/
- public static float px2dp(Context context, float pxVal)
- {
+ public static float px2dp(Context context, float pxVal) {
+ // 使用TypedValue类的applyDimension方法进行单位转换
+ // TypedValue.COMPLEX_UNIT_SP表示sp单位
+ // spVal是要转换的sp值
+ // context.getResources().getDisplayMetrics()提供了设备的显示度量信息,用于计算转换
final float scale = context.getResources().getDisplayMetrics().density;
return (pxVal / scale);
}
/**
- * px转sp
+ * px转sp的方法
+ * @param context 上下文对象
+ *
+ * @param pxVal 需要转换的px值
+ *
+ * @return 转换后的sp值
*
- * @param
- * @param pxVal
- * @return
*/
- public static float px2sp(Context context, float pxVal)
- {
+ public static float px2sp(Context context, float pxVal) {
+ // 获取设备的显示度量信息,特别是scaledDensity,它表示屏幕密度的缩放因子
+ // 将px值除以scaledDensity得到sp值,因为sp设计为与用户感知的尺度无关
return (pxVal / context.getResources().getDisplayMetrics().scaledDensity);
}
- public static Point getDisplayPoint(Context context){
+
+ /**
+ * 获取屏幕真实分辨率的方法(考虑了系统UI占用的部分)
+ *
+ * @param context 上下文对象,用于获取系统服务
+ *
+ * @return 屏幕分辨率的Point对象,包含宽度和高度
+ */
+ public static Point getDisplayPoint(Context context) {
+ // 获取WindowManager服务,用于操作和查询窗口的属性
+
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ // 获取默认的Display对象,包含了屏幕的显示信息
+
Display display = windowManager.getDefaultDisplay();
+ // 创建DisplayMetrics对象,用于存储屏幕的度量信息
+
DisplayMetrics displayMetrics = new DisplayMetrics();
+ // 抑制原生类型警告,因为Class类无法确定具体的类型参数
+
@SuppressWarnings("rawtypes")
+
Class c;
+ // 声明一个Class类型的变量c
+
try {
c = Class.forName("android.view.Display");
+ // 通过反射获取Display类
+
@SuppressWarnings("unchecked")
- Method method = c.getMethod("getRealMetrics",DisplayMetrics.class);
+ Method method = c.getMethod("getRealMetrics", DisplayMetrics.class);
+ // 获取getRealMetrics方法
+
method.invoke(display, displayMetrics);
- return new Point(displayMetrics.widthPixels ,displayMetrics.heightPixels );
- }catch(Exception e){
+ // 调用getRealMetrics方法,获取真实分辨率
+
+ return new Point(displayMetrics.widthPixels , displayMetrics.heightPixels);
+ // 返回分辨率
+ } catch (Exception e) {
+
e.printStackTrace();
+ // 打印异常信息
}
DisplayMetrics dm = new DisplayMetrics();
+ // 创建一个DisplayMetrics对象
+
((Activity)context).getWindowManager().getDefaultDisplay().getMetrics(dm);
- return new Point(dm.widthPixels ,dm.heightPixels);
+ // 获取默认的分辨率
+
+ return new Point(dm.widthPixels , dm.heightPixels);
+ // 返回默认的分辨率
}
- public static int getWindowWidth(Context context){
- WindowManager wm = (WindowManager) context
- .getSystemService(Context.WINDOW_SERVICE);
+ /**
+ * 获取窗口宽度的方法
+ *
+ * @param context 上下文对象
+ *
+ * @return 窗口的宽度
+ */
+ public static int getWindowWidth(Context context) {
+ WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ // 获取WindowManager服务
+
DisplayMetrics dm = new DisplayMetrics();
+ // 创建一个DisplayMetrics对象
+
wm.getDefaultDisplay().getMetrics(dm);
+ // 获取默认的分辨率
+
int width = dm.widthPixels;
+ // 获取宽度
+
return width;
+ // 返回宽度
}
- public static int getWindowHeight(Context context){
- WindowManager wm = (WindowManager) context
- .getSystemService(Context.WINDOW_SERVICE);
+
+ /**
+ * 获取窗口高度的方法
+ *
+ * @param context 上下文对象
+ *
+ * @return 窗口的高度
+ */
+ public static int getWindowHeight(Context context) {
+ WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ // 获取WindowManager服务
+
DisplayMetrics dm = new DisplayMetrics();
+ // 创建一个DisplayMetrics对象
+
wm.getDefaultDisplay().getMetrics(dm);
+ // 获取默认的分辨率
+
int height = dm.heightPixels;
+ // 获取高度
+
return height;
+ // 返回高度
}
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/monke/monkeybook/utils/NetworkUtil.java b/app/src/main/java/com/monke/monkeybook/utils/NetworkUtil.java
index f4c5044..9d0b0d8 100644
--- a/app/src/main/java/com/monke/monkeybook/utils/NetworkUtil.java
+++ b/app/src/main/java/com/monke/monkeybook/utils/NetworkUtil.java
@@ -1,37 +1,74 @@
//Copyright (c) 2017. 章钦豪. All rights reserved.
+// 版权声明,表明代码的版权归属于章钦豪。
+
package com.monke.monkeybook.utils;
+// 声明包名。
import android.content.Context;
+// 导入Context类,提供了一个操作当前环境的抽象。
+
import android.net.ConnectivityManager;
+// 导入ConnectivityManager类,用于获取网络连接信息。
+
import android.net.NetworkInfo;
+// 导入NetworkInfo类,用于获取网络状态信息。
+
import com.monke.monkeybook.MApplication;
+// 导入MApplication类,用于获取应用程序的实例。
+
import com.monke.monkeybook.R;
+// 导入R类,用于访问应用程序的资源。
+
import java.util.HashMap;
+// 导入HashMap类,用于创建键值对映射。
+
import java.util.Map;
+// 导入Map接口,用于提供键值对集合。
public class NetworkUtil {
+// 声明NetworkUtil工具类,用于网络相关的工具方法。
+
private static final Map errorMap = new HashMap<>();
+ // 创建一个HashMap,用于存储错误代码和错误信息的映射。
public static final int SUCCESS = 10000;
+ // 定义一个常量,表示操作成功。
+
public static final int ERROR_CODE_NONET = 10001;
+ // 定义一个常量,表示网络不可用错误代码。
+
public static final int ERROR_CODE_OUTTIME = 10002;
+ // 定义一个常量,表示网络超时错误代码。
+
public static final int ERROR_CODE_ANALY = 10003;
+ // 定义一个常量,表示网络分析错误代码。
static{
+ // 初始化静态代码块,用于初始化errorMap。
errorMap.put(ERROR_CODE_NONET, MApplication.getInstance().getString(R.string.net_error_10001));
+
+ // 将网络不可用错误代码和错误信息添加到errorMap。
errorMap.put(ERROR_CODE_OUTTIME, MApplication.getInstance().getString(R.string.net_error_10002));
+
+ // 将网络超时错误代码和错误信息添加到errorMap。
+
errorMap.put(ERROR_CODE_ANALY, MApplication.getInstance().getString(R.string.net_error_10003));
+ // 将网络分析错误代码和错误信息添加到errorMap。
}
public static String getErrorTip(int code) {
+ // 定义一个方法,用于根据错误代码获取错误提示信息。
return errorMap.get(code);
}
public static boolean isNetWorkAvailable() {
+ // 定义一个方法,用于检查网络是否可用。
ConnectivityManager manager = (ConnectivityManager) MApplication.getInstance()
.getSystemService(Context.CONNECTIVITY_SERVICE);
+ // 获取ConnectivityManager服务实例。
if (manager != null) {
NetworkInfo info = manager.getActiveNetworkInfo();
+ // 获取当前活跃的网络信息。
if (info != null && info.isConnected()) {
return true;
} else {
@@ -41,4 +78,4 @@ public class NetworkUtil {
return false;
}
}
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/monke/monkeybook/utils/NumberUtil.java b/app/src/main/java/com/monke/monkeybook/utils/NumberUtil.java
index d6a9e0e..65255b2 100644
--- a/app/src/main/java/com/monke/monkeybook/utils/NumberUtil.java
+++ b/app/src/main/java/com/monke/monkeybook/utils/NumberUtil.java
@@ -1,36 +1,73 @@
//Copyright (c) 2017. 章钦豪. All rights reserved.
+// 版权声明,表明代码的版权归属于章钦豪。
+
package com.monke.monkeybook.utils;
+// 声明包名。
public class NumberUtil {
+// 声明NumberUtil工具类,用于数字转换相关的工具方法。
/**
* 中文数字转阿拉伯数字
*/
+
private static int chineseNumber2Int(String chineseNumber){
+ // 定义一个私有静态方法,用于将中文数字转换为阿拉伯数字。
+
int result = 0;
+ // 用于存储转换结果。
+
int temp = 1;//存放一个单位的数字如:十万
+ // 临时存储一个单位的数值,如“十”则为10,“百”则为100。
+
int count = 0;//判断是否有chArr
+ // 用于计数“千”、“万”、“亿”等单位出现的次数。
+
char[] cnArr = new char[]{'一','二','三','四','五','六','七','八','九'};
+ // 包含中文数字0-9的数组。
+
char[] chArr = new char[]{'十','百','千','万','亿'};
+ // 包含中文单位“十”、“百”、“千”、“万”、“亿”的数组。
+
for (int i = 0; i < chineseNumber.length(); i++) {
+ // 遍历输入的中文数字字符串。
+
boolean b = true;//判断是否是chArr
+ // 标记当前字符是否属于单位数组chArr。
+
char c = chineseNumber.charAt(i);
- for (int j = 0; j < cnArr.length; j++) {//非单位,即数字
+ // 获取当前遍历到的字符。
+ for (int j = 0; j < cnArr.length; j++) {
+ //非单位,即数字
+ // 检查当前字符是否为数字('一'到'九')。
+
if (c == cnArr[j]) {
- if(0 != count){//添加下一个单位之前,先把上一个单位值添加到结果中
+ if(0 != count){
+ //添加下一个单位之前,先把上一个单位值添加到结果中
+ // 如果count不为0,说明之前已经遇到了单位字符,需要先计算之前的数值。
result += temp;
+ // 将临时数值累加到结果中。
+
temp = 1;
+ // 重置临时数值为1。
+
count = 0;
+ // 重置计数器。
}
// 下标+1,就是对应的值
temp = j + 1;
+ // 将当前数字字符转换为对应的数值,并更新temp。
b = false;
+ // 标记当前字符已处理。
break;
}
}
if(b){//单位{'十','百','千','万','亿'}
+ // 如果当前字符不是数字,那么它应该是一个单位。
for (int j = 0; j < chArr.length; j++) {
+ // 遍历单位数组,检查当前字符是否为单位。
if (c == chArr[j]) {
+ // 根据单位字符,更新temp的值。
switch (j) {
case 0:
temp *= 10;
@@ -51,13 +88,21 @@ public class NumberUtil {
break;
}
count++;
+ // 每遇到一个单位字符,计数器增加。
+
}
}
}
- if (i == chineseNumber.length() - 1) {//遍历到最后一个字符
+ if (i == chineseNumber.length() - 1) {
+ //遍历到最后一个字符
+ // 如果已经遍历到字符串的最后一个字符。
+
result += temp;
+ // 将最后一个单位的值累加到结果中。
}
}
return result;
+
+ // 返回转换后的阿拉伯数字。
}
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/monke/monkeybook/utils/ParseSystemUtil.java b/app/src/main/java/com/monke/monkeybook/utils/ParseSystemUtil.java
index 396f6e9..de0c5bf 100644
--- a/app/src/main/java/com/monke/monkeybook/utils/ParseSystemUtil.java
+++ b/app/src/main/java/com/monke/monkeybook/utils/ParseSystemUtil.java
@@ -1,36 +1,69 @@
+// 声明一个名为ParseSystemUtil的公共类,它位于com.monke.monkeybook.utils包下
package com.monke.monkeybook.utils;
public class ParseSystemUtil {
- /**将二进制转换成16进制
- * @param buf
- * @return
+
+ /**
+ * 将字节数组(二进制)转换为十六进制字符串的方法。
+ *
+ * @param buf 输入的字节数组
+ * @return 转换后的十六进制字符串
*/
public static String parseByte2HexStr(byte buf[]) {
+ // 创建一个StringBuffer对象,用于构建最终的十六进制字符串
StringBuffer sb = new StringBuffer();
+
+ // 遍历输入的字节数组
for (int i = 0; i < buf.length; i++) {
+ // 将当前字节转换为无符号的十六进制字符串
+ // 注意:byte在Java中是有符号的,所以使用& 0xFF来转换为无符号数
String hex = Integer.toHexString(buf[i] & 0xFF);
+
+ // 如果转换后的十六进制字符串长度为1(即只包含一个十六进制数字),则在其前面补0
if (hex.length() == 1) {
hex = '0' + hex;
}
+
+ // 将转换后的十六进制字符串(大写)追加到StringBuffer中
sb.append(hex.toUpperCase());
}
+
+ // 返回构建好的十六进制字符串
return sb.toString();
}
- /**将16进制转换为二进制
- * @param hexStr
- * @return
+ /**
+ * 将十六进制字符串转换为字节数组(二进制)的方法。
+ *
+ * @param hexStr 输入的十六进制字符串
+ * @return 转换后的字节数组
*/
public static byte[] parseHexStr2Byte(String hexStr) {
- if (hexStr==null || hexStr.length() ==0) {
+
+ // 如果输入的十六进制字符串为空或为null,则返回null
+ if (hexStr == null || hexStr.length() == 0) {
return null;
}
- byte[] result = new byte[hexStr.length()/2];
- for (int i = 0;i< hexStr.length()/2; i++) {
- int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);
- int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);
+
+ // 根据输入的十六进制字符串长度计算字节数组的长度
+ // 每两个十六进制字符表示一个字节
+ byte[] result = new byte[hexStr.length() / 2];
+
+ // 遍历输入的十六进制字符串,每两个字符一组进行转换
+ for (int i = 0; i < hexStr.length() / 2; i++) {
+
+ // 从当前位置开始,截取两个十六进制字符
+ // 第一个参数是起始位置,第二个参数是结束位置(不包含)
+
+ int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
+ int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
+
+ // 将两个十六进制数字组合成一个字节,并存储到结果数组中
+ // 注意:这里需要将结果转换为byte类型,因为parseInt返回的是int类型
result[i] = (byte) (high * 16 + low);
}
+
+ // 返回转换后的字节数组
return result;
}
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/monke/monkeybook/utils/PremissionCheck.java b/app/src/main/java/com/monke/monkeybook/utils/PremissionCheck.java
index bd720e5..0e8169a 100644
--- a/app/src/main/java/com/monke/monkeybook/utils/PremissionCheck.java
+++ b/app/src/main/java/com/monke/monkeybook/utils/PremissionCheck.java
@@ -1,54 +1,101 @@
+// 版权信息,表明此代码由章钦豪在2017年创建并保留所有权利
//Copyright (c) 2017. 章钦豪. All rights reserved.
+
+// 声明包名,表示此类位于com.monke.monkeybook.utils包下
package com.monke.monkeybook.utils;
+// 导入所需的Android类
+// 导入Android内容上下文类,用于访问应用的特定资源和类以及调用应用级别的操作
import android.content.Context;
+
+// 导入Android意图类,用于在不同组件(如Activity、Service等)之间进行通信
import android.content.Intent;
+
+// 导入Android包信息类,用于获取已安装应用包的信息,如版本号、签名等
import android.content.pm.PackageInfo;
+
+// 导入Android包管理器类,用于访问应用包的信息,如已安装应用的列表、应用签名等
import android.content.pm.PackageManager;
+
+// 导入Android URI类,用于表示统一资源标识符(URI),通常用于访问网络资源或文件
import android.net.Uri;
+
+// 导入Android构建类,用于获取当前Android系统的版本信息
import android.os.Build;
+
+// 导入Android支持库中的权限检查类,用于检查应用是否具有执行特定操作的权限
import android.support.v4.content.PermissionChecker;
+// 声明一个名为PremissionCheck的公共类,用于检查权限和请求权限设置
public class PremissionCheck {
- public static Boolean checkPremission(Context context,String permission){
- boolean result = false;
+
+ // 定义一个静态方法,用于检查应用是否具有指定的权限
+ public static Boolean checkPremission(Context context, String permission) {
+ boolean result = false; // 初始化结果为false,表示没有权限
+
+ // 检查目标SDK版本和当前SDK版本是否都大于或等于Android M(6.0)
if (getTargetSdkVersion(context) >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- result = context.checkSelfPermission(permission)
- == PackageManager.PERMISSION_GRANTED;
+
+ // 如果是,则使用context的checkSelfPermission方法检查权限
+ result = context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;
} else {
- result = PermissionChecker.checkSelfPermission(context, permission)
- == PermissionChecker.PERMISSION_GRANTED;
+
+ // 如果不是,则使用PermissionChecker的checkSelfPermission方法检查权限
+ result = PermissionChecker.checkSelfPermission(context, permission) == PermissionChecker.PERMISSION_GRANTED;
}
+
+ // 返回检查结果
return result;
}
+ // 定义一个私有静态方法,用于获取应用的目标SDK版本
private static int getTargetSdkVersion(Context context) {
- int version = 0;
+ int version = 0; // 初始化版本号为0
try {
- final PackageInfo info = context.getPackageManager().getPackageInfo(
- context.getPackageName(), 0);
+ // 通过包管理器获取应用的包信息
+ final PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
+
+ // 从包信息中获取目标SDK版本
version = info.applicationInfo.targetSdkVersion;
} catch (PackageManager.NameNotFoundException e) {
+
+ // 如果捕获到包未找到的异常,则打印堆栈跟踪信息
e.printStackTrace();
}
+ // 返回目标SDK版本
return version;
}
+
+ // 定义一个静态方法,用于请求跳转到应用的权限设置页面
public static void requestPermissionSetting(Context from) {
try {
+ // 创建一个Intent对象
Intent localIntent = new Intent();
+
+ // 为Intent添加新任务标志
localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ // 根据Android版本选择不同的Action和Data来跳转到权限设置页面
if (Build.VERSION.SDK_INT >= 9) {
+ // 对于Android 2.3(API级别9)及以上版本,使用APPLICATION_DETAILS_SETTINGS Action
+
localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
+ // 设置Data为当前应用的包名
+
localIntent.setData(Uri.fromParts("package", from.getPackageName(), null));
} else if (Build.VERSION.SDK_INT <= 8) {
+ // 对于Android 2.2(API级别8)及以下版本,使用Intent的ACTION_VIEW Action和特定的类名
localIntent.setAction(Intent.ACTION_VIEW);
localIntent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
+ // 通过Extra传递当前应用的包名
localIntent.putExtra("com.android.settings.ApplicationPkgName", from.getPackageName());
}
+
+ // 启动Intent,跳转到权限设置页面
from.startActivity(localIntent);
} catch (Exception e) {
+ // 如果捕获到异常,则打印堆栈跟踪信息
e.printStackTrace();
}
}
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/monke/monkeybook/utils/aes/AESUtil.java b/app/src/main/java/com/monke/monkeybook/utils/aes/AESUtil.java
index 9195c1b..7fc28dd 100644
--- a/app/src/main/java/com/monke/monkeybook/utils/aes/AESUtil.java
+++ b/app/src/main/java/com/monke/monkeybook/utils/aes/AESUtil.java
@@ -1,47 +1,97 @@
package com.monke.monkeybook.utils.aes;
+// 声明包名,指定该类属于哪个包。
import com.monke.monkeybook.utils.ParseSystemUtil;
+// 导入ParseSystemUtil类,用于处理字节和十六进制字符串的转换。
import javax.crypto.*;
+// 导入javax.crypto包中的所有类,用于AES加密和解密。
import javax.crypto.spec.SecretKeySpec;
+// 导入SecretKeySpec类,用于指定AES密钥。
import java.io.UnsupportedEncodingException;
+// 导入UnsupportedEncodingException类,用于处理可能的编码不支持异常。
public class AESUtil {
+// 声明AESUtil类,用于提供AES加密和解密的工具方法。
+
public static String aesEncode(String cleartext, String seed) throws Exception {
+ // 定义公有静态方法,用于AES加密。
+
byte[] rawKey = deriveKeyInsecurely(seed, 32).getEncoded();
+ // 从种子字符串生成AES密钥。
+
byte[] result = encrypt(rawKey, cleartext.getBytes());
+ // 使用AES密钥对明文进行加密。
+
return ParseSystemUtil.parseByte2HexStr(result);
+ // 将加密结果转换为十六进制字符串并返回。
}
public static String aesDecode(String encrypted, String seed) throws Exception {
+ // 定义公有静态方法,用于AES解密。
+
byte[] rawKey = deriveKeyInsecurely(seed, 32).getEncoded();
+ // 从种子字符串生成AES密钥。
+
byte[] enc = ParseSystemUtil.parseHexStr2Byte(encrypted);
+ // 将十六进制字符串转换为字节数组。
+
byte[] result = decrypt(rawKey, enc);
+ // 使用AES密钥对密文进行解密。
+
return new String(result);
+ // 将解密结果转换为字符串并返回。
}
private static SecretKey deriveKeyInsecurely(String password, int keySizeInBytes) throws UnsupportedEncodingException {
+ // 定义私有静态方法,用于不安全地从密码生成AES密钥。
+
byte[] passwordBytes = password.getBytes("UTF-8");
+ // 将密码字符串转换为UTF-8编码的字节数组。
+
return new SecretKeySpec(
InsecureSHA1PRNGKeyDerivator.deriveInsecureKey(
passwordBytes, keySizeInBytes),
"AES");
+ // 使用SHA1PRNGKeyDerivator生成密钥,并创建SecretKeySpec对象。
}
private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
+ // 定义私有静态方法,用于AES加密。
+
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
+ // 创建AES密钥规范。
+
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+ // 获取AES/ECB/PKCS5Padding模式的Cipher实例。
+
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
+ // 初始化Cipher为加密模式。
+
byte[] encrypted = cipher.doFinal(clear);
+ // 对明文进行加密。
+
return encrypted;
+ // 返回加密结果。
}
private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
+ // 定义私有静态方法,用于AES解密。
+
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
+ // 创建AES密钥规范。
+
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+ // 获取AES/ECB/PKCS5Padding模式的Cipher实例。
+
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
+ // 初始化Cipher为解密模式。
+
byte[] decrypted = cipher.doFinal(encrypted);
+ // 对密文进行解密。
+
return decrypted;
+ // 返回解密结果。
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/monke/monkeybook/utils/base64/BASE64Decoder.java b/app/src/main/java/com/monke/monkeybook/utils/base64/BASE64Decoder.java
index 49c99c2..fc37271 100644
--- a/app/src/main/java/com/monke/monkeybook/utils/base64/BASE64Decoder.java
+++ b/app/src/main/java/com/monke/monkeybook/utils/base64/BASE64Decoder.java
@@ -1,7 +1,16 @@
+// 包声明
package com.monke.monkeybook.utils.base64;
+// 导入Java的输入输出(IO)相关的类
+// IOException类表示输入输出操作中可能发生的异常
import java.io.IOException;
+
+// OutputStream类是字节输出流的所有类的超类,用于写入字节流到一个目标(如文件、内存等)
import java.io.OutputStream;
+
+// PushbackInputStream类是一个包含了一个内部回退缓冲区的输入流
+// 它允许程序将最近从输入流中读取的字节(或者字节数组)回退到输入流中
+// 这可以用于重新读取已经读取的字节,或者用于纠正读取错误
import java.io.PushbackInputStream;
public class BASE64Decoder extends CharacterDecoder{
@@ -9,83 +18,113 @@ public class BASE64Decoder extends CharacterDecoder{
private static final byte[] pem_convert_array = new byte[256];
byte[] decode_buffer = new byte[4];
- public BASE64Decoder() {
- }
-
- protected int bytesPerAtom() {
- return 4;
- }
-
- protected int bytesPerLine() {
- return 72;
- }
-
- protected void decodeAtom(PushbackInputStream var1, OutputStream var2, int var3) throws IOException {
- byte var5 = -1;
- byte var6 = -1;
- byte var7 = -1;
- byte var8 = -1;
- if (var3 < 2) {
- throw new CEFormatException("BASE64Decoder: Not enough bytes for an atom.");
- } else {
- int var4;
- do {
- var4 = var1.read();
- if (var4 == -1) {
- throw new CEStreamExhausted();
- }
- } while(var4 == 10 || var4 == 13);
+ // 构造函数,无特定操作
+ public BASE64Decoder() {}
+
+ // 返回解码过程中每个“原子”(在这里是Base64编码的4个字符)对应的原始字节数(3或4)
+ protected int bytesPerAtom() {
+ return 4; // 这里的4指的是解码过程中处理的Base64字符数,不是字节数
+ }
+
+ // 返回解码后每行的字节数限制(Base64编码通常没有每行字节数的限制,但这里可能是为了格式化输出)
+ protected int bytesPerLine() {
+ return 72; // 假设每行最多72个字节的输出,用于格式化
+ }
+
+ // 解码一个Base64编码的“原子”(4个字符),并将其写入输出流
+ protected void decodeAtom(PushbackInputStream var1, OutputStream var2, int var3) throws IOException {
- this.decode_buffer[0] = (byte)var4;
- var4 = this.readFully(var1, this.decode_buffer, 1, var3 - 1);
- if (var4 == -1) {
- throw new CEStreamExhausted();
+ // 初始化四个变量来存储解码后的字节,初始值为-1表示无效
+ byte var5 = -1, var6 = -1, var7 = -1, var8 = -1;
+
+ // 如果提供的字符数少于2个,则无法解码(因为至少需要2个字符来表示一个有效的Base64编码单元)
+ if (var3 < 2) {
+ throw new CEFormatException("BASE64Decoder: Not enough bytes for an atom.");
} else {
- if (var3 > 3 && this.decode_buffer[3] == 61) {
- var3 = 3;
- }
+ int var4;
- if (var3 > 2 && this.decode_buffer[2] == 61) {
- var3 = 2;
- }
+ // 跳过任何换行符(\n或\r),直到找到一个有效的Base64字符
+ do {
+ var4 = var1.read();
+ if (var4 == -1) {
+ // 如果到达输入流的末尾
- switch(var3) {
- case 4:
- var8 = pem_convert_array[this.decode_buffer[3] & 255];
- case 3:
- var7 = pem_convert_array[this.decode_buffer[2] & 255];
- case 2:
- var6 = pem_convert_array[this.decode_buffer[1] & 255];
- var5 = pem_convert_array[this.decode_buffer[0] & 255];
- default:
- switch(var3) {
- case 2:
- var2.write((byte)(var5 << 2 & 252 | var6 >>> 4 & 3));
- break;
- case 3:
- var2.write((byte)(var5 << 2 & 252 | var6 >>> 4 & 3));
- var2.write((byte)(var6 << 4 & 240 | var7 >>> 2 & 15));
- break;
- case 4:
- var2.write((byte)(var5 << 2 & 252 | var6 >>> 4 & 3));
- var2.write((byte)(var6 << 4 & 240 | var7 >>> 2 & 15));
- var2.write((byte)(var7 << 6 & 192 | var8 & 63));
- }
+ throw new CEStreamExhausted();
+ // 抛出流耗尽异常
+ }
+ } while (var4 == 10 || var4 == 13); // 10是\n,13是\r
+
+ // 将读取的第一个有效字符存入解码缓冲区
+ this.decode_buffer[0] = (byte) var4;
+ // 读取剩余的字符到解码缓冲区,并返回实际读取的字符数
+ var4 = this.readFully(var1, this.decode_buffer, 1, var3 - 1);
+ if (var4 == -1) {
+ // 如果再次到达输入流的末尾
+ throw new CEStreamExhausted();
+ // 抛出流耗尽异常
+ } else {
+ // 如果缓冲区中有'='(表示Base64编码的填充字符),则调整要解码的字符数
+ if (var3 > 3 && this.decode_buffer[3] == 61) { // 61是'='的ASCII码
+ var3 = 3;
+ }
+ if (var3 > 2 && this.decode_buffer[2] == 61) {
+ var3 = 2;
+ }
+ // 根据读取的字符数(var3)进行解码
+ switch (var3) {
+ case 4: // 如果读取了4个字符
+ var8 = pem_convert_array[this.decode_buffer[3] & 255];
+ // 解码最后一个字符
+ case 3: // 如果读取了3个字符(或原本读取了4个但最后一个是'=')
+ var7 = pem_convert_array[this.decode_buffer[2] & 255];
+ // 解码倒数第二个字符
+ case 2: // 如果读取了2个字符(或原本读取了更多但后面有'=')
+ var6 = pem_convert_array[this.decode_buffer[1] & 255];
+ // 解码第三个字符
+ var5 = pem_convert_array[this.decode_buffer[0] & 255];
+ // 解码第一个字符
+ default:
+ // 这里的default实际上不会执行,因为switch已经覆盖了所有可能的case
+ // 根据读取的字符数(即var3的值),执行相应的解码操作
+ switch (var3) {
+ case 2:
+ // 2个字符,对应1个字节的原始数据
+ var2.write((byte) (var5 << 2 & 252 | var6 >>> 4 & 3));
+ // 解码并写入输出流
+ break;
+ case 3:
+ // 3个字符,对应2个字节的原始数据
+ var2.write((byte) (var5 << 2 & 252 | var6 >>> 4 & 3));
+ // 解码第一个字节并写入
+ var2.write((byte) (var6 << 4 & 240 | var7 >>> 2 & 15));
+ // 解码第二个字节并写入
+ break;
+ case 4:
+ // 4个字符,对应3个字节的原始数据(或带填充的4个字节数据)
+ var2.write((byte) (var5 << 2 & 252 | var6 >>> 4 & 3));
+ // 解码第一个字节并写入
+ var2.write((byte) (var6 << 4 & 240 | var7 >>> 2 & 15));
+ // 解码第二个字节并写入
+ var2.write((byte) (var7 << 6 & 192 | var8 & 63));
+ // 解码第三个字节并写入
+ }
+ }
}
}
}
- }
- static {
- int var0;
- for(var0 = 0; var0 < 255; ++var0) {
- pem_convert_array[var0] = -1;
- }
+ // 静态初始化块,用于填充pem_convert_array数组
+ static {
+ int var0;
+ // 初始化pem_convert_array数组,将所有元素设置为-1(表示无效字符)
+ for (var0 = 0; var0 < 255; ++var0) {
+ pem_convert_array[var0] = -1;
+ }
- for(var0 = 0; var0 < pem_array.length; ++var0) {
- pem_convert_array[pem_array[var0]] = (byte)var0;
+ // 将pem_array中的字符映射到pem_convert_array中,字符的ASCII值作为索引,字符在pem_array中的位置作为值
+ for (var0 = 0; var0 < pem_array.length; ++var0) {
+ pem_convert_array[pem_array[var0]] = (byte) var0;
+ }
}
-
- }
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/monke/monkeybook/utils/base64/BASE64Encoder.java b/app/src/main/java/com/monke/monkeybook/utils/base64/BASE64Encoder.java
index 4c5fe1d..410c40f 100644
--- a/app/src/main/java/com/monke/monkeybook/utils/base64/BASE64Encoder.java
+++ b/app/src/main/java/com/monke/monkeybook/utils/base64/BASE64Encoder.java
@@ -1,52 +1,83 @@
package com.monke.monkeybook.utils.base64;
+// 定义该类所在的包
import java.io.IOException;
+// 导入IOException类,用于处理IO异常
import java.io.OutputStream;
+// 导入OutputStream类,用于处理输出流
public class BASE64Encoder extends CharacterEncoder{
+ // 定义BASE64Encoder类,继承自CharacterEncoder类
+ // 定义BASE64编码表,包含所有可用的字符
private static final char[] pem_array = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
public BASE64Encoder() {
+ // 构造方法,初始化BASE64Encoder对象
}
+ // 每个原始数据块的字节数是3
protected int bytesPerAtom() {
return 3;
}
+ // 每行的字节数限制为57
protected int bytesPerLine() {
return 57;
}
+ // 编码一个原子(即3字节数据块),并将其写入输出流
protected void encodeAtom(OutputStream var1, byte[] var2, int var3, int var4) throws IOException {
byte var5;
+ // 如果剩余字节数为1
if (var4 == 1) {
var5 = var2[var3];
+ // 取第一个字节
byte var6 = 0;
+ // 由于只剩1个字节,第二个字节为0
boolean var7 = false;
+ // 未使用的变量
var1.write(pem_array[var5 >>> 2 & 63]);
+ // 写入第一个字符
var1.write(pem_array[(var5 << 4 & 48) + (var6 >>> 4 & 15)]);
+ // 写入第二个字符
var1.write(61);
+ // 填充字符 '='
var1.write(61);
+ // 填充字符 '='
} else {
byte var8;
+ // 如果剩余字节数为2
if (var4 == 2) {
var5 = var2[var3];
+ // 取第一个字节
var8 = var2[var3 + 1];
+ // 取第二个字节
byte var9 = 0;
+ // 第三个字节为0
var1.write(pem_array[var5 >>> 2 & 63]);
+ // 写入第一个字符
var1.write(pem_array[(var5 << 4 & 48) + (var8 >>> 4 & 15)]);
+ // 写入第二个字符
var1.write(pem_array[(var8 << 2 & 60) + (var9 >>> 6 & 3)]);
+ // 写入第三个字符
var1.write(61);
+ // 填充字符 '='
} else {
var5 = var2[var3];
+ // 取第一个字节
var8 = var2[var3 + 1];
+ // 取第二个字节
byte var10 = var2[var3 + 2];
+ // 取第三个字节
var1.write(pem_array[var5 >>> 2 & 63]);
+ // 写入第一个字符
var1.write(pem_array[(var5 << 4 & 48) + (var8 >>> 4 & 15)]);
+ // 写入第二个字符
var1.write(pem_array[(var8 << 2 & 60) + (var10 >>> 6 & 3)]);
+ // 写入第三个字符
var1.write(pem_array[var10 & 63]);
+ // 写入第四个字符
}
}
-
}
}
diff --git a/app/src/main/java/com/monke/monkeybook/utils/base64/CEFormatException.java b/app/src/main/java/com/monke/monkeybook/utils/base64/CEFormatException.java
index fc6450b..d8eac66 100644
--- a/app/src/main/java/com/monke/monkeybook/utils/base64/CEFormatException.java
+++ b/app/src/main/java/com/monke/monkeybook/utils/base64/CEFormatException.java
@@ -1,11 +1,17 @@
package com.monke.monkeybook.utils.base64;
+// 定义该类所在的包
import java.io.IOException;
+// 导入IOException类,用于处理IO异常
public class CEFormatException extends IOException {
+ // 定义CEFormatException类,继承自IOException类
static final long serialVersionUID = -7139121221067081482L;
+ // 定义serialVersionUID,确保类的序列化兼容性
public CEFormatException(String var1) {
+ // 构造方法,接收一个字符串作为异常信息
super(var1);
+ // 调用父类IOException的构造方法,传递异常信息
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/com/monke/monkeybook/utils/base64/CEStreamExhausted.java b/app/src/main/java/com/monke/monkeybook/utils/base64/CEStreamExhausted.java
index 51e1f26..b70c55d 100644
--- a/app/src/main/java/com/monke/monkeybook/utils/base64/CEStreamExhausted.java
+++ b/app/src/main/java/com/monke/monkeybook/utils/base64/CEStreamExhausted.java
@@ -1,10 +1,15 @@
package com.monke.monkeybook.utils.base64;
+// 定义该类所在的包
import java.io.IOException;
+// 导入IOException类,用于处理输入输出异常
public class CEStreamExhausted extends IOException {
+ // 定义CEStreamExhausted类,继承自IOException类
+
static final long serialVersionUID = -5889118049525891904L;
+ // 定义serialVersionUID,用于序列化时验证类的兼容性
- public CEStreamExhausted() {
+ public CEStreamExhausted() { // 构造方法,不带参数
}
}
diff --git a/app/src/main/java/com/monke/monkeybook/utils/base64/CharacterDecoder.java b/app/src/main/java/com/monke/monkeybook/utils/base64/CharacterDecoder.java
index 21f6864..8ef8c55 100644
--- a/app/src/main/java/com/monke/monkeybook/utils/base64/CharacterDecoder.java
+++ b/app/src/main/java/com/monke/monkeybook/utils/base64/CharacterDecoder.java
@@ -1,102 +1,177 @@
-package com.monke.monkeybook.utils.base64;
+package com.monke.monkeybook.utils.base64; // 定义该类所在的包
import java.io.ByteArrayInputStream;
+// 导入ByteArrayInputStream类,用于从字节数组中读取数据
import java.io.ByteArrayOutputStream;
+// 导入ByteArrayOutputStream类,用于将数据写入字节数组
import java.io.IOException;
+// 导入IOException类,用于处理输入输出异常
import java.io.InputStream;
+// 导入InputStream类,用于处理输入流
import java.io.OutputStream;
+// 导入OutputStream类,用于处理输出流
import java.io.PushbackInputStream;
+// 导入PushbackInputStream类,用于从输入流中推回字节
import java.nio.ByteBuffer;
+// 导入ByteBuffer类,用于操作字节缓冲区
public abstract class CharacterDecoder {
+ // 定义CharacterDecoder抽象类,用于解码字符流
public CharacterDecoder() {
+ // 构造方法
}
+ // 抽象方法,返回每个原子(数据块)字节数
protected abstract int bytesPerAtom();
+ // 抽象方法,返回每行字节数
protected abstract int bytesPerLine();
+ // 解码缓冲区前缀,空实现,子类可以重写
protected void decodeBufferPrefix(PushbackInputStream var1, OutputStream var2) throws IOException {
}
+ // 解码缓冲区后缀,空实现,子类可以重写
protected void decodeBufferSuffix(PushbackInputStream var1, OutputStream var2) throws IOException {
}
+ // 解码行前缀,默认实现返回每行的字节数
protected int decodeLinePrefix(PushbackInputStream var1, OutputStream var2) throws IOException {
- return this.bytesPerLine();
+ return this.bytesPerLine(); // 返回每行的字节数
}
+ // 解码行后缀,空实现,子类可以重写
protected void decodeLineSuffix(PushbackInputStream var1, OutputStream var2) throws IOException {
}
+ // 解码原子(数据块),此方法抛出CEStreamExhausted异常,表示流已耗尽
protected void decodeAtom(PushbackInputStream var1, OutputStream var2, int var3) throws IOException {
- throw new CEStreamExhausted();
+ throw new CEStreamExhausted(); // 抛出流耗尽异常
}
+ // 从输入流中读取指定字节数,直到读取完成或遇到流结束
protected int readFully(InputStream var1, byte[] var2, int var3, int var4) throws IOException {
- for(int var5 = 0; var5 < var4; ++var5) {
+ for (int var5 = 0; var5 < var4; ++var5) {
+ // 循环读取字节直到满足要求
+
int var6 = var1.read();
+ // 读取一个字节
+
if (var6 == -1) {
+ // 如果遇到流结束
+
return var5 == 0 ? -1 : var5;
+ // 如果没有读取字节则返回-1,否则返回已读取字节数
}
-
var2[var5 + var3] = (byte)var6;
+ // 将读取的字节存入目标数组
}
-
- return var4;
+ return var4; // 返回读取的字节数
}
+ // 解码整个缓冲区数据,并将解码后的结果写入输出流
public void decodeBuffer(InputStream var1, OutputStream var2) throws IOException {
int var4 = 0;
+ // 已解码字节数
+
PushbackInputStream var5 = new PushbackInputStream(var1);
+ // 使用PushbackInputStream处理输入流
+
this.decodeBufferPrefix(var5, var2);
+ // 解码前缀,子类可以实现
- while(true) {
+ while (true) {
+ // 不断读取并解码数据直到流结束
try {
int var6 = this.decodeLinePrefix(var5, var2);
+ // 解码行前缀
int var3;
- for(var3 = 0; var3 + this.bytesPerAtom() < var6; var3 += this.bytesPerAtom()) {
+ // 解码每个原子(数据块),直到当前行的数据量达到要求
+
+ for (var3 = 0; var3 + this.bytesPerAtom() < var6; var3 += this.bytesPerAtom()) {
this.decodeAtom(var5, var2, this.bytesPerAtom());
+ // 解码一个原子
+
var4 += this.bytesPerAtom();
+ // 累加已解码字节数
}
if (var3 + this.bytesPerAtom() == var6) {
+ // 如果行正好能填满
+
this.decodeAtom(var5, var2, this.bytesPerAtom());
+ // 解码一个原子
+
var4 += this.bytesPerAtom();
+ // 累加已解码字节数
+
} else {
+ // 如果行不足一个原子
+
this.decodeAtom(var5, var2, var6 - var3);
+ // 解码剩余字节
+
var4 += var6 - var3;
+ // 累加已解码字节数
}
this.decodeLineSuffix(var5, var2);
+ // 解码行后缀,子类可以实现
+
} catch (CEStreamExhausted var8) {
+ // 捕获流耗尽异常
+
this.decodeBufferSuffix(var5, var2);
+ // 解码后缀
+
return;
+ // 结束解码
}
}
}
+ // 将一个字符串解码为字节数组
public byte[] decodeBuffer(String var1) throws IOException {
byte[] var2 = new byte[var1.length()];
+ // 创建字节数组
var1.getBytes(0, var1.length(), var2, 0);
+ // 将字符串转为字节数组
+
ByteArrayInputStream var3 = new ByteArrayInputStream(var2);
+ // 创建字节数组输入流
+
ByteArrayOutputStream var4 = new ByteArrayOutputStream();
+ // 创建字节数组输出流
+
this.decodeBuffer(var3, var4);
+ // 解码缓冲区
+
return var4.toByteArray();
+ // 返回解码后的字节数组
}
+ // 将输入流解码为字节数组
public byte[] decodeBuffer(InputStream var1) throws IOException {
ByteArrayOutputStream var2 = new ByteArrayOutputStream();
+ // 创建字节数组输出流
+
this.decodeBuffer(var1, var2);
+ // 解码缓冲区
+
return var2.toByteArray();
+ // 返回解码后的字节数组
}
+ // 将解码后的数据转为ByteBuffer对象
public ByteBuffer decodeBufferToByteBuffer(String var1) throws IOException {
return ByteBuffer.wrap(this.decodeBuffer(var1));
+ // 解码字符串并包装为ByteBuffer
}
+ // 将解码后的数据转为ByteBuffer对象
public ByteBuffer decodeBufferToByteBuffer(InputStream var1) throws IOException {
return ByteBuffer.wrap(this.decodeBuffer(var1));
+ // 解码输入流并包装为ByteBuffer
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/com/monke/monkeybook/utils/base64/CharacterEncoder.java b/app/src/main/java/com/monke/monkeybook/utils/base64/CharacterEncoder.java
index 1184f5b..9f6bccb 100644
--- a/app/src/main/java/com/monke/monkeybook/utils/base64/CharacterEncoder.java
+++ b/app/src/main/java/com/monke/monkeybook/utils/base64/CharacterEncoder.java
@@ -1,181 +1,310 @@
package com.monke.monkeybook.utils.base64;
+// 定义该类所在的包
import java.io.ByteArrayInputStream;
+// 导入ByteArrayInputStream类,用于从字节数组中读取数据
+
import java.io.ByteArrayOutputStream;
+// 导入ByteArrayOutputStream类,用于将数据写入字节数组
+
import java.io.IOException;
+// 导入IOException类,用于处理输入输出异常
+
import java.io.InputStream;
+// 导入InputStream类,用于处理输入流
+
import java.io.OutputStream;
+// 导入OutputStream类,用于处理输出流
+
import java.io.PrintStream;
+// 导入PrintStream类,用于处理带格式的输出流
+
import java.nio.ByteBuffer;
+// 导入ByteBuffer类,用于操作字节缓冲区
public abstract class CharacterEncoder {
+ // 定义一个抽象类CharacterEncoder,用于字符编码
+
protected PrintStream pStream;
+ // 声明PrintStream对象pStream,用于处理输出流
public CharacterEncoder() {
+ // 构造方法
}
+ // 抽象方法,返回每个原子(数据块)字节数
protected abstract int bytesPerAtom();
+ // 抽象方法,返回每行字节数
protected abstract int bytesPerLine();
+ // 编码缓冲区前缀,设置输出流
protected void encodeBufferPrefix(OutputStream var1) throws IOException {
this.pStream = new PrintStream(var1);
+ // 使用PrintStream包装输出流
}
+ // 编码缓冲区后缀,空实现,子类可以重写
protected void encodeBufferSuffix(OutputStream var1) throws IOException {
}
+ // 编码行前缀,空实现,子类可以重写
protected void encodeLinePrefix(OutputStream var1, int var2) throws IOException {
}
+ // 编码行后缀,打印换行符
protected void encodeLineSuffix(OutputStream var1) throws IOException {
- this.pStream.println();
+ this.pStream.println(); // 输出换行符
}
+ // 抽象方法,编码原子(数据块)
protected abstract void encodeAtom(OutputStream var1, byte[] var2, int var3, int var4) throws IOException;
+ // 从输入流读取数据到字节数组
protected int readFully(InputStream var1, byte[] var2) throws IOException {
- for(int var3 = 0; var3 < var2.length; ++var3) {
+ for (int var3 = 0; var3 < var2.length; ++var3) {
+ // 循环读取字节
+
int var4 = var1.read();
+ // 从输入流读取一个字节
+
if (var4 == -1) {
+ // 如果读取到流末尾
+
return var3;
+ // 返回已经读取的字节数
}
-
- var2[var3] = (byte)var4;
+ var2[var3] = (byte) var4;
+ // 存储读取的字节
}
-
return var2.length;
+ // 返回读取的字节数
}
+ // 编码输入流数据并将结果写入输出流
public void encode(InputStream var1, OutputStream var2) throws IOException {
byte[] var5 = new byte[this.bytesPerLine()];
+ // 创建字节数组用于存储每行数据
+
this.encodeBufferPrefix(var2);
+ // 编码缓冲区前缀
- while(true) {
+ while (true) {
+ // 不断读取并编码数据直到流结束
int var4 = this.readFully(var1, var5);
+ // 从输入流中读取数据
if (var4 == 0) {
+ // 如果没有读取到数据
break;
+ // 结束编码
}
this.encodeLinePrefix(var2, var4);
+ // 编码行前缀
+
+ for (int var3 = 0; var3 < var4; var3 += this.bytesPerAtom()) {
+ // 遍历每个原子(数据块)
- for(int var3 = 0; var3 < var4; var3 += this.bytesPerAtom()) {
if (var3 + this.bytesPerAtom() <= var4) {
+ // 如果当前原子不超过剩余字节数
+
this.encodeAtom(var2, var5, var3, this.bytesPerAtom());
+ // 编码一个原子
} else {
+ // 如果当前原子超过剩余字节数
+
this.encodeAtom(var2, var5, var3, var4 - var3);
+ // 编码剩余的字节
}
}
if (var4 < this.bytesPerLine()) {
+ // 如果当前行数据不足一行
break;
+ // 结束编码
}
this.encodeLineSuffix(var2);
+ // 编码行后缀
}
this.encodeBufferSuffix(var2);
+ // 编码缓冲区后缀
}
+ // 编码字节数组并将结果写入输出流
public void encode(byte[] var1, OutputStream var2) throws IOException {
ByteArrayInputStream var3 = new ByteArrayInputStream(var1);
- this.encode((InputStream)var3, var2);
+ // 创建字节数组输入流
+ this.encode((InputStream) var3, var2);
+ // 调用encode方法进行编码
}
+ // 编码字节数组并返回编码后的字符串
public String encode(byte[] var1) {
ByteArrayOutputStream var2 = new ByteArrayOutputStream();
+ // 创建字节数组输出流
ByteArrayInputStream var3 = new ByteArrayInputStream(var1);
+ // 创建字节数组输入流
String var4 = null;
+ // 初始化编码结果字符串
try {
- this.encode((InputStream)var3, var2);
+ this.encode((InputStream) var3, var2);
+ // 调用encode方法进行编码
var4 = var2.toString("8859_1");
+ // 将输出流内容转换为字符串
return var4;
+ // 返回编码结果
} catch (Exception var6) {
+ // 捕获异常
throw new Error("CharacterEncoder.encode internal error");
+ // 抛出错误
}
}
+ // 从ByteBuffer获取字节数组
private byte[] getBytes(ByteBuffer var1) {
byte[] var2 = null;
+ // 初始化字节数组
if (var1.hasArray()) {
- byte[] var3 = var1.array();
+ // 如果ByteBuffer内部有数组
+ byte[] var3 = var1.array(); // 获取数组
if (var3.length == var1.capacity() && var3.length == var1.remaining()) {
+ // 如果数组长度符合要求
var2 = var3;
+ // 直接使用该数组
var1.position(var1.limit());
+ // 更新ByteBuffer位置
}
}
if (var2 == null) {
+ // 如果没有直接可用的数组
var2 = new byte[var1.remaining()];
+ // 创建新数组
var1.get(var2);
+ // 将ByteBuffer中的内容复制到新数组
}
return var2;
+ // 返回字节数组
}
+ // 编码ByteBuffer数据并将结果写入输出流
public void encode(ByteBuffer var1, OutputStream var2) throws IOException {
byte[] var3 = this.getBytes(var1);
+ // 获取ByteBuffer中的字节数组
this.encode(var3, var2);
+ // 调用encode方法进行编码
}
+ // 编码ByteBuffer数据并返回编码后的字符串
public String encode(ByteBuffer var1) {
byte[] var2 = this.getBytes(var1);
+ // 获取ByteBuffer中的字节数组
return this.encode(var2);
+ // 调用encode方法进行编码并返回结果
}
+ // 编码整个输入流缓冲区并将结果写入输出流
public void encodeBuffer(InputStream var1, OutputStream var2) throws IOException {
byte[] var5 = new byte[this.bytesPerLine()];
+ // 创建字节数组用于存储每行数据
this.encodeBufferPrefix(var2);
+ // 编码缓冲区前缀
int var4;
do {
var4 = this.readFully(var1, var5);
+ // 从输入流中读取数据
+
if (var4 == 0) {
+ // 如果没有读取到数据
+
break;
+ // 结束编码
}
this.encodeLinePrefix(var2, var4);
+ // 编码行前缀
- for(int var3 = 0; var3 < var4; var3 += this.bytesPerAtom()) {
+ for (int var3 = 0; var3 < var4; var3 += this.bytesPerAtom()) {
+ // 遍历每个原子(数据块)
if (var3 + this.bytesPerAtom() <= var4) {
+ // 如果当前原子不超过剩余字节数
+
this.encodeAtom(var2, var5, var3, this.bytesPerAtom());
+ // 编码一个原子
+
} else {
+ // 如果当前原子超过剩余字节数
+
this.encodeAtom(var2, var5, var3, var4 - var3);
+ // 编码剩余的字节
}
}
this.encodeLineSuffix(var2);
- } while(var4 >= this.bytesPerLine());
+ // 编码行后缀
+
+ } while (var4 >= this.bytesPerLine());
+ // 如果当前行数据不够一行,则结束
+
this.encodeBufferSuffix(var2);
+ // 编码缓冲区后缀
}
+
+ // 编码字节数组并将结果写入输出流
public void encodeBuffer(byte[] var1, OutputStream var2) throws IOException {
ByteArrayInputStream var3 = new ByteArrayInputStream(var1);
- this.encodeBuffer((InputStream)var3, var2);
+ // 创建字节数组输入流
+
+ this.encodeBuffer((InputStream) var3, var2);
+ // 调用encodeBuffer方法进行编码
}
+ // 编码字节数组并返回编码后的字符串
public String encodeBuffer(byte[] var1) {
ByteArrayOutputStream var2 = new ByteArrayOutputStream();
+ // 创建字节数组输出流
+
ByteArrayInputStream var3 = new ByteArrayInputStream(var1);
+ // 创建字节数组输入流
+
try {
- this.encodeBuffer((InputStream)var3, var2);
+ this.encodeBuffer((InputStream) var3, var2);
+ // 调用encodeBuffer方法进行编码
+
} catch (Exception var5) {
+ // 捕获异常
+
throw new Error("CharacterEncoder.encodeBuffer internal error");
+ // 抛出错误
}
return var2.toString();
+ // 返回编码后的字符串
}
+ // 编码ByteBuffer并将结果写入输出流
public void encodeBuffer(ByteBuffer var1, OutputStream var2) throws IOException {
byte[] var3 = this.getBytes(var1);
+ // 获取ByteBuffer中的字节数组
+
this.encodeBuffer(var3, var2);
+ // 调用encodeBuffer方法进行编码
}
+ // 编码ByteBuffer并返回编码后的字符串
public String encodeBuffer(ByteBuffer var1) {
byte[] var2 = this.getBytes(var1);
+ // 获取ByteBuffer中的字节数组
+
return this.encodeBuffer(var2);
+ // 调用encodeBuffer方法进行编码并返回结果
}
}
diff --git a/app/src/main/java/com/monke/monkeybook/view/IBookDetailView.java b/app/src/main/java/com/monke/monkeybook/view/IBookDetailView.java
index b759f09..1dca5fc 100644
--- a/app/src/main/java/com/monke/monkeybook/view/IBookDetailView.java
+++ b/app/src/main/java/com/monke/monkeybook/view/IBookDetailView.java
@@ -1,16 +1,26 @@
//Copyright (c) 2017. 章钦豪. All rights reserved.
+// 版权声明,注明该代码的版权所有者
+
package com.monke.monkeybook.view;
+// 定义该接口所在的包
import com.monke.basemvplib.IView;
+// 导入IView接口,IView是基类接口,所有视图接口都需要实现它
+
+// 定义IBookDetailView接口,继承自IView接口,表示书籍详情页面的视图
+public interface IBookDetailView extends IView {
-public interface IBookDetailView extends IView{
/**
* 更新书籍详情UI
+ * 该方法用于刷新或更新书籍详情的界面
*/
void updateView();
+ // 定义一个抽象方法,用于更新书籍详情的UI界面
/**
* 数据获取失败
+ * 该方法用于处理书架数据获取失败的情况
*/
void getBookShelfError();
+ // 定义一个抽象方法,用于处理获取书架数据时发生的错误
}
diff --git a/app/src/main/java/com/monke/monkeybook/view/IBookReadView.java b/app/src/main/java/com/monke/monkeybook/view/IBookReadView.java
index cbf1884..2a3ad0b 100644
--- a/app/src/main/java/com/monke/monkeybook/view/IBookReadView.java
+++ b/app/src/main/java/com/monke/monkeybook/view/IBookReadView.java
@@ -1,45 +1,85 @@
-//Copyright (c) 2017. 章钦豪. All rights reserved.
+//Copyright (c) 2017. 章钦豪. All rights reserved. // 版权声明,标明代码的版权所有者及年份
+
package com.monke.monkeybook.view;
+// 定义该接口所在的包
import android.graphics.Paint;
+// 导入Paint类,用于图形绘制
+
import com.monke.basemvplib.IView;
+// 导入IView接口,IView是一个通用视图接口,所有视图接口都需要实现它
-public interface IBookReadView extends IView{
+// 定义IBookReadView接口,继承自IView接口,表示小说阅读页面的视图
+public interface IBookReadView extends IView {
/**
* 获取当前阅读界面UI画笔
- * @return
+ * @return 返回绘制文本或图形的画笔
*/
Paint getPaint();
+ // 定义一个抽象方法,返回用于绘制文本的画笔对象
/**
* 获取当前小说内容可绘制宽度
- * @return
+ * @return 返回小说内容可绘制区域的宽度(像素值)
*/
int getContentWidth();
+ // 定义一个抽象方法,返回小说内容区域的宽度
/**
* 小说数据初始化成功
- * @param durChapterIndex
- * @param chapterAll
- * @param durPageIndex
+ * @param durChapterIndex 当前章节索引
+ * @param chapterAll 总章节数
+ * @param durPageIndex 当前页面的页码
*/
- void initContentSuccess(int durChapterIndex, int chapterAll, int durPageIndex);
+ void initContentSuccess(int durChapterIndex, int chapterAll, int durPageIndex); // 定义一个方法,初始化小说内容成功时调用,传递当前章节、总章节和当前页码信息
/**
- * 开始加载
+ * 开始加载小说
+ * 显示加载状态或动画
*/
void startLoadingBook();
+ // 定义一个方法,开始加载小说时调用,用于显示加载过程中的UI状态
+ /**
+ * 设置阅读进度条的最大值
+ * @param count 总章节数
+ */
void setHpbReadProgressMax(int count);
+ // 定义一个方法,用于设置小说阅读进度条的最大值
+ /**
+ * 初始化弹出框
+ * 用于弹出界面初始化
+ */
void initPop();
+ // 定义一个方法,初始化弹出框相关UI操作
+ /**
+ * 显示加载中的小说页面
+ * 显示加载进度条或动画
+ */
void showLoadBook();
+ // 定义一个方法,用于显示加载小说的过程
+ /**
+ * 取消加载小说页面的显示
+ * 隐藏加载进度条或动画
+ */
void dimissLoadBook();
+ // 定义一个方法,用于取消加载小说页面的显示
+ /**
+ * 加载书籍失败时调用
+ * 显示错误信息或提示
+ */
void loadLocationBookError();
+ // 定义一个方法,用于加载书籍时发生错误时调用
+ /**
+ * 显示下载菜单
+ * 用于显示下载相关的菜单或选项
+ */
void showDownloadMenu();
+ // 定义一个方法,用于显示下载菜单
}
diff --git a/app/src/main/java/com/monke/monkeybook/view/IChoiceBookView.java b/app/src/main/java/com/monke/monkeybook/view/IChoiceBookView.java
index c21a1d7..c2aabcb 100644
--- a/app/src/main/java/com/monke/monkeybook/view/IChoiceBookView.java
+++ b/app/src/main/java/com/monke/monkeybook/view/IChoiceBookView.java
@@ -1,30 +1,89 @@
//Copyright (c) 2017. 章钦豪. All rights reserved.
+// 版权声明,标明代码的版权所有者及年份
+
package com.monke.monkeybook.view;
+// 定义该接口所在的包
import com.monke.basemvplib.IView;
+// 导入IView接口,IView是一个通用的视图接口,所有视图接口都需要实现它
+
import com.monke.monkeybook.bean.SearchBookBean;
+// 导入SearchBookBean类,用于表示书籍数据
+
import com.monke.monkeybook.view.adapter.ChoiceBookAdapter;
+// 导入ChoiceBookAdapter类,用于书籍列表的适配器
+
import java.util.List;
+// 导入List类,表示书籍列表的数据类型
-public interface IChoiceBookView extends IView{
+// 定义IChoiceBookView接口,继承自IView接口,表示选择书籍界面的视图
+public interface IChoiceBookView extends IView {
+ /**
+ * 刷新搜索书籍列表
+ * @param books 搜索到的书籍列表
+ */
void refreshSearchBook(List books);
+ // 定义方法,刷新搜索到的书籍列表,传入书籍列表
+ /**
+ * 加载更多书籍
+ * @param books 更多书籍列表
+ */
void loadMoreSearchBook(List books);
+ // 定义方法,用于加载更多书籍,传入更多的书籍列表
+ /**
+ * 刷新操作完成
+ * @param isAll 是否已加载完所有数据
+ */
void refreshFinish(Boolean isAll);
+ // 定义方法,表示刷新操作完成,传入是否已加载完所有数据
+ /**
+ * 加载更多操作完成
+ * @param isAll 是否已加载完所有数据
+ */
void loadMoreFinish(Boolean isAll);
+ // 定义方法,表示加载更多操作完成,传入是否已加载完所有数据
+ /**
+ * 搜索书籍时发生错误
+ */
void searchBookError();
+ // 定义方法,表示在搜索书籍时发生错误
+ /**
+ * 添加书籍到书架成功
+ * @param searchBooks 成功添加到书架的书籍列表
+ */
void addBookShelfSuccess(List searchBooks);
+ // 定义方法,表示成功将书籍添加到书架
+ /**
+ * 添加书籍到书架失败
+ * @param code 错误代码
+ */
void addBookShelfFailed(int code);
+ // 定义方法,表示将书籍添加到书架失败,并返回错误代码
+ /**
+ * 获取搜索书籍的适配器
+ * @return 返回ChoiceBookAdapter实例,用于处理书籍列表的显示
+ */
ChoiceBookAdapter getSearchBookAdapter();
+ // 定义方法,返回ChoiceBookAdapter实例,用于获取书籍列表适配器
+ /**
+ * 更新搜索书籍列表的某一项
+ * @param index 要更新的书籍索引
+ */
void updateSearchItem(int index);
+ // 定义方法,用于更新搜索书籍列表中的某一项,传入该项的索引
+ /**
+ * 开始刷新动画
+ */
void startRefreshAnim();
+ // 定义方法,用于启动刷新动画,通常用于界面显示加载动画
}
diff --git a/app/src/main/java/com/monke/monkeybook/view/IImportBookView.java b/app/src/main/java/com/monke/monkeybook/view/IImportBookView.java
index e7fcf73..0d8f59a 100644
--- a/app/src/main/java/com/monke/monkeybook/view/IImportBookView.java
+++ b/app/src/main/java/com/monke/monkeybook/view/IImportBookView.java
@@ -1,29 +1,40 @@
//Copyright (c) 2017. 章钦豪. All rights reserved.
+// 版权声明,标明代码的版权所有者及年份
+
package com.monke.monkeybook.view;
+// 定义该接口所在的包
import com.monke.basemvplib.IView;
+// 导入IView接口,所有视图接口都需要实现它
+
import java.io.File;
+// 导入File类,用于处理文件操作
-public interface IImportBookView extends IView{
+// 定义IImportBookView接口,继承自IView接口,表示导入书籍界面的视图
+public interface IImportBookView extends IView {
/**
* 新增书籍
- * @param newFile
+ * @param newFile 新增的书籍文件
*/
void addNewBook(File newFile);
+ // 定义方法,用于将一个新书籍文件添加到系统
/**
* 书籍搜索完成
*/
void searchFinish();
+ // 定义方法,表示书籍的搜索操作已完成
/**
- * 添加成功
+ * 添加书籍成功
*/
void addSuccess();
+ // 定义方法,表示书籍添加操作成功
/**
- * 添加失败
+ * 添加书籍失败
*/
void addError();
-}
\ No newline at end of file
+ // 定义方法,表示书籍添加操作失败
+}
diff --git a/app/src/main/java/com/monke/monkeybook/view/ILibraryView.java b/app/src/main/java/com/monke/monkeybook/view/ILibraryView.java
index a90a7d5..cd543b7 100644
--- a/app/src/main/java/com/monke/monkeybook/view/ILibraryView.java
+++ b/app/src/main/java/com/monke/monkeybook/view/ILibraryView.java
@@ -1,19 +1,27 @@
//Copyright (c) 2017. 章钦豪. All rights reserved.
+// 版权声明,标明代码的版权所有者及年份
+
package com.monke.monkeybook.view;
+// 定义该接口所在的包
import com.monke.basemvplib.IView;
+// 导入IView接口,所有视图接口都需要实现它
import com.monke.monkeybook.bean.LibraryBean;
+// 导入LibraryBean类,表示书城中的书籍数据模型
-public interface ILibraryView extends IView{
+// 定义ILibraryView接口,继承自IView接口,表示书城页面的视图
+public interface ILibraryView extends IView {
/**
- * 书城书籍获取成功 更新UI
- * @param library
+ * 书城书籍获取成功,更新UI
+ * @param library 获取到的书城数据,类型为LibraryBean
*/
void updateUI(LibraryBean library);
+ // 定义方法,表示书城书籍数据获取成功并更新UI,传入一个LibraryBean对象
/**
- * 书城数据刷新成功 更新UI
+ * 书城数据刷新成功,更新UI
*/
void finishRefresh();
+ // 定义方法,表示书城数据刷新成功并更新UI
}
diff --git a/app/src/main/java/com/monke/monkeybook/view/IMainView.java b/app/src/main/java/com/monke/monkeybook/view/IMainView.java
index aa04d58..84d3dac 100644
--- a/app/src/main/java/com/monke/monkeybook/view/IMainView.java
+++ b/app/src/main/java/com/monke/monkeybook/view/IMainView.java
@@ -1,43 +1,52 @@
-//Copyright (c) 2017. 章钦豪. All rights reserved.
-package com.monke.monkeybook.view;
+//Copyright (c) 2017. 章钦豪. All rights reserved. // 版权声明,标明代码的版权所有者及年份
-import com.monke.basemvplib.IView;
+package com.monke.monkeybook.view; // 定义该接口所在的包
+
+import com.monke.basemvplib.IView; // 导入IView接口,所有视图接口都需要实现它
import com.monke.monkeybook.bean.BookShelfBean;
+// 导入BookShelfBean类,表示书架上的书籍数据模型
import java.util.List;
+// 导入List类,用于存储多个BookShelfBean对象
-public interface IMainView extends IView{
+// 定义IMainView接口,继承自IView接口,表示书架页面的视图
+public interface IMainView extends IView {
/**
- * 刷新书架书籍小说信息 更新UI
- * @param bookShelfBeanList
+ * 刷新书架书籍小说信息,更新UI
+ * @param bookShelfBeanList 书架数据列表,包含多个书籍信息
*/
void refreshBookShelf(List bookShelfBeanList);
+ // 定义方法,传入书架数据,更新UI界面显示书架中的书籍信息
/**
* 执行刷新书架小说信息
*/
void activityRefreshView();
+ // 定义方法,表示触发刷新书架小说信息操作
/**
* 刷新完成
*/
void refreshFinish();
+ // 定义方法,表示刷新操作完成
/**
* 刷新错误
- * @param error
+ * @param error 错误信息
*/
void refreshError(String error);
+ // 定义方法,表示刷新操作发生错误,传入错误信息
/**
- * 刷新书籍 UI进度修改
+ * 刷新书籍,UI进度修改
*/
void refreshRecyclerViewItemAdd();
+ // 定义方法,表示刷新操作时,更新UI进度(如RecyclerView的进度)
/**
* 设置刷新进度条最大值
- * @param x
+ * @param x 刷新进度条的最大值
*/
- void setRecyclerMaxProgress(int x);
+ void setRecyclerMaxProgress(int x); // 定义方法,设置刷新进度条的最大值
}
diff --git a/app/src/main/java/com/monke/monkeybook/view/ISearchView.java b/app/src/main/java/com/monke/monkeybook/view/ISearchView.java
index 006375f..2bafedb 100644
--- a/app/src/main/java/com/monke/monkeybook/view/ISearchView.java
+++ b/app/src/main/java/com/monke/monkeybook/view/ISearchView.java
@@ -1,77 +1,111 @@
-//Copyright (c) 2017. 章钦豪. All rights reserved.
+//Copyright (c) 2017. 章钦豪. All rights reserved. // 版权声明,标明代码的版权所有者及年份
+
package com.monke.monkeybook.view;
+// 定义该接口所在的包
import android.widget.EditText;
+// 导入EditText类,用于获取搜索框的输入内容
+
import com.monke.basemvplib.IView;
+// 导入IView接口,所有视图接口都需要实现它
+
import com.monke.monkeybook.bean.SearchBookBean;
+// 导入SearchBookBean类,表示搜索到的书籍数据模型
+
import com.monke.monkeybook.bean.SearchHistoryBean;
+// 导入SearchHistoryBean类,表示搜索历史记录的数据模型
+
import com.monke.monkeybook.view.adapter.SearchBookAdapter;
+// 导入SearchBookAdapter类,适配器用于显示搜索书籍的列表
+
import java.util.List;
+// 导入List类,用于存储多个SearchBookBean对象或SearchHistoryBean对象
-public interface ISearchView extends IView{
+// 定义ISearchView接口,继承自IView接口,表示搜索页面的视图
+public interface ISearchView extends IView {
/**
- * 成功 新增查询记录
- * @param searchHistoryBean
+ * 成功新增查询记录
+ * @param searchHistoryBean 新增的搜索历史记录
*/
void insertSearchHistorySuccess(SearchHistoryBean searchHistoryBean);
+ // 定义方法,表示成功添加一条新的搜索历史记录
/**
- * 成功搜索 搜索记录
- * @param datas
+ * 成功搜索并返回搜索记录
+ * @param datas 搜索历史记录数据列表
*/
void querySearchHistorySuccess(List datas);
+ // 定义方法,表示成功查询到搜索历史记录
/**
- * 首次查询成功 更新UI
- * @param books
+ * 首次查询成功,更新UI
+ * @param books 搜索到的书籍列表
*/
void refreshSearchBook(List books);
+ // 定义方法,表示首次搜索成功后更新UI,显示搜索到的书籍
/**
- * 加载更多书籍成功 更新UI
- * @param books
+ * 加载更多书籍成功,更新UI
+ * @param books 新加载的书籍列表
*/
void loadMoreSearchBook(List books);
+ // 定义方法,表示成功加载更多书籍,并更新UI显示
/**
- * 刷新成功
- * @param isAll
+ * 刷新完成
+ * @param isAll 是否所有数据都已加载完成
*/
void refreshFinish(Boolean isAll);
+ // 定义方法,表示刷新操作完成,并传入是否已经加载所有数据的状态
/**
- * 加载成功
- * @param isAll
+ * 加载完成
+ * @param isAll 是否所有数据都已加载完成
*/
void loadMoreFinish(Boolean isAll);
+ // 定义方法,表示加载更多操作完成,并传入是否已经加载所有数据的状态
/**
* 搜索失败
- * @param isRefresh
+ * @param isRefresh 是否为刷新操作
*/
void searchBookError(Boolean isRefresh);
+ // 定义方法,表示搜索失败,传入是否是刷新操作
/**
- * 获取搜索内容EditText
- * @return
+ * 获取搜索内容的EditText组件
+ * @return EditText 搜索框的组件
*/
EditText getEdtContent();
+ // 定义方法,返回搜索框的EditText组件,供其他逻辑使用
/**
* 添加书籍失败
- * @param code
+ * @param code 错误码,表示添加失败的原因
*/
void addBookShelfFailed(int code);
+ // 定义方法,表示添加书籍到书架失败,传入错误码
+ /**
+ * 获取SearchBookAdapter适配器
+ * @return SearchBookAdapter 返回搜索书籍的适配器
+ */
SearchBookAdapter getSearchBookAdapter();
+ // 定义方法,返回用于显示搜索书籍的适配器
+ /**
+ * 更新搜索项
+ * @param index 搜索项的索引
+ */
void updateSearchItem(int index);
+ // 定义方法,表示更新指定索引的搜索项
/**
* 判断书籍是否已经在书架上
- * @param searchBookBean
- * @return
+ * @param searchBookBean 要检查的书籍
+ * @return Boolean 如果书籍已经存在返回true,否则返回false
*/
Boolean checkIsExist(SearchBookBean searchBookBean);
+ // 定义方法,检查给定的书籍是否已经在书架上
}
diff --git a/app/src/main/java/com/monke/monkeybook/view/adapter/BookShelfAdapter.java b/app/src/main/java/com/monke/monkeybook/view/adapter/BookShelfAdapter.java
index bec276c..20d5996 100644
--- a/app/src/main/java/com/monke/monkeybook/view/adapter/BookShelfAdapter.java
+++ b/app/src/main/java/com/monke/monkeybook/view/adapter/BookShelfAdapter.java
@@ -1,107 +1,182 @@
-//Copyright (c) 2017. 章钦豪. All rights reserved.
-package com.monke.monkeybook.view.adapter;
+// Copyright (c) 2017. 章钦豪. All rights reserved.
+package com.monke.monkeybook.view.adapter; // 声明包名,适配器所在的包
import android.os.Handler;
+// 导入Handler类,处理异步任务
+
import android.support.v7.widget.RecyclerView;
+// 导入RecyclerView类,展示列表的控件
+
import android.view.LayoutInflater;
+// 导入LayoutInflater类,加载布局文件
+
import android.view.View;
+// 导入View类,视图的基类
+
import android.view.ViewGroup;
+// 导入ViewGroup类,视图组的基类
+
import android.view.animation.Animation;
+// 导入Animation类,动画效果
+
import android.view.animation.AnimationUtils;
+// 导入AnimationUtils类,动画加载工具
+
import android.widget.FrameLayout;
+// 导入FrameLayout布局,布局控件
+
import android.widget.ImageButton;
+// 导入ImageButton控件,带图片的按钮
+
import android.widget.ImageView;
+// 导入ImageView控件,用于显示图片
+
import android.widget.LinearLayout;
+// 导入LinearLayout布局,线性布局控件
+
import android.widget.TextView;
+// 导入TextView控件,用于显示文本
+
import com.bumptech.glide.Glide;
+// 导入Glide库,用于加载图片
+
import com.bumptech.glide.load.engine.DiskCacheStrategy;
+// 导入Glide的缓存策略
+
import com.monke.monkeybook.R;
+// 导入资源文件,包含布局、字符串等资源
+
import com.monke.monkeybook.bean.BookShelfBean;
+// 导入书架数据模型类
+
import com.monke.monkeybook.widget.refreshview.RefreshRecyclerViewAdapter;
+// 导入刷新功能的RecyclerView适配器
+
import com.monke.mprogressbar.MHorProgressBar;
+// 导入进度条类
+
import com.monke.mprogressbar.OnProgressListener;
+// 导入进度条的监听器
+
import java.util.ArrayList;
+// 导入ArrayList类,动态数组
+
import java.util.List;
+//导入List接口,集合类型
+
import me.grantland.widget.AutofitTextView;
+// 导入自动调整文本大小的TextView控件
+// 书架适配器类,继承自RefreshRecyclerViewAdapter,提供书架数据的绑定与展示
public class BookShelfAdapter extends RefreshRecyclerViewAdapter {
private final int TYPE_LASTEST = 1;
+ // 最新阅读类型
+
private final int TYPE_OTHER = 2;
+ // 其他书籍类型
- private final long DURANIMITEM = 130; //item动画启动间隔
+ private final long DURANIMITEM = 130;
+ // 每个item动画启动的间隔时间
private List books;
+ // 书架数据的集合
private Boolean needAnim = true;
+ // 是否需要动画
private OnItemClickListener itemClickListener;
+ // 条目点击监听器接口
+ // 定义条目点击事件接口
public interface OnItemClickListener {
- void toSearch();
+ void toSearch(); // 跳转到搜索界面
void onClick(BookShelfBean bookShelfBean, int index);
+ // 点击书籍条目时的回调方法
void onLongClick(View view, BookShelfBean bookShelfBean, int index);
+ // 长按书籍条目时的回调方法
}
+ // 构造函数,初始化书架数据
public BookShelfAdapter() {
super(false);
+ // 调用父类构造函数,禁用下拉刷新
books = new ArrayList<>();
+ // 初始化书籍集合
}
+ // 获取数据项数量,处理每三项作为一组
@Override
public int getItemcount() {
if (books.size() == 0) {
return 1;
+ // 如果书架没有书籍,返回1项显示"空书架"提示
+
} else {
if (books.size() % 3 == 0) {
return 1 + books.size() / 3;
+ // 每3个书籍一组
} else {
return 1 + (books.size() / 3 + 1);
+ // 每3个书籍一组,最后一组可能不足3个
}
}
}
+ // 获取真实的数据项数量(去除提示项)
public int getRealItemCount() {
return books.size();
}
+ // 根据位置返回对应的view类型(最新阅读和其他书籍)
@Override
public int getItemViewtype(int position) {
if (position == 0) {
return TYPE_LASTEST;
+ // 第一项为最新阅读项
} else {
return TYPE_OTHER;
+ // 其他为普通书籍项
}
}
+ // 创建对应viewHolder
@Override
public RecyclerView.ViewHolder onCreateViewholder(ViewGroup parent, int viewType) {
if (viewType == TYPE_LASTEST) {
return new LastestViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_bookshelf_lastest, parent, false));
+ // 最新阅读视图
} else {
return new OtherViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_bookshelf_other, parent, false));
+ // 其他书籍视图
}
}
+ // 绑定数据到视图
@Override
public void onBindViewholder(RecyclerView.ViewHolder holder, int position) {
if (holder.getItemViewType() == TYPE_LASTEST) {
bindLastestViewHolder((LastestViewHolder) holder, position);
+ // 绑定最新阅读视图
} else {
bindOtherViewHolder((OtherViewHolder) holder, position - 1);
+ // 绑定其他书籍视图
}
}
+ // 绑定其他书籍视图
private void bindOtherViewHolder(final OtherViewHolder holder, int index) {
final int index_1 = index * 3;
+ // 计算第一个书籍的位置
if (needAnim) {
- final Animation animation = AnimationUtils.loadAnimation(holder.flContent_1.getContext(), R.anim.anim_bookshelf_item);
+ final Animation animation = AnimationUtils.loadAnimation(holder.flContent_1.getContext(), R.anim.anim_bookshelf_item); // 加载动画
animation.setAnimationListener(new AnimatontStartListener() {
@Override
void onAnimStart(Animation animation) {
needAnim = false;
holder.flContent_1.setVisibility(View.VISIBLE);
+ // 动画开始时显示内容
}
});
new Handler().postDelayed(new Runnable() {
@@ -109,19 +184,24 @@ public class BookShelfAdapter extends RefreshRecyclerViewAdapter {
public void run() {
if (null != holder)
holder.flContent_1.startAnimation(animation);
+ // 延迟启动动画
}
}, index_1 * DURANIMITEM);
} else {
holder.flContent_1.setVisibility(View.VISIBLE);
+ // 不需要动画时直接显示
}
- Glide.with(holder.ivCover_1.getContext()).load(books.get(index_1).getBookInfoBean().getCoverUrl()).dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESULT).centerCrop().placeholder(R.drawable.img_cover_default).into(holder.ivCover_1);
+ Glide.with(holder.ivCover_1.getContext()).load(books.get(index_1).getBookInfoBean().getCoverUrl()).dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESULT).centerCrop().placeholder(R.drawable.img_cover_default).into(holder.ivCover_1); // 使用Glide加载书籍封面图片
holder.tvName_1.setText(books.get(index_1).getBookInfoBean().getName());
+ // 设置书籍名称
+ // 设置点击和长按事件
holder.ibContent_1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (itemClickListener != null)
itemClickListener.onClick(books.get(index_1), index_1);
+ // 调用点击事件
}
});
holder.ibContent_1.setOnLongClickListener(new View.OnLongClickListener() {
@@ -129,106 +209,17 @@ public class BookShelfAdapter extends RefreshRecyclerViewAdapter {
public boolean onLongClick(View v) {
if (itemClickListener != null) {
itemClickListener.onLongClick(holder.ivCover_1, books.get(index_1), index_1);
+ // 调用长按事件
return true;
} else
return false;
}
});
- final int index_2 = index_1 + 1;
- if (index_2 < books.size()) {
- if (needAnim) {
- final Animation animation = AnimationUtils.loadAnimation(holder.flContent_2.getContext(), R.anim.anim_bookshelf_item);
- animation.setAnimationListener(new AnimatontStartListener() {
- @Override
- void onAnimStart(Animation animation) {
- needAnim = false;
- holder.flContent_2.setVisibility(View.VISIBLE);
- }
- });
- new Handler().postDelayed(new Runnable() {
- @Override
- public void run() {
- if (null != holder)
- holder.flContent_2.startAnimation(animation);
- }
- }, index_2 * DURANIMITEM);
- } else {
- holder.flContent_2.setVisibility(View.VISIBLE);
- }
- Glide.with(holder.ivCover_2.getContext()).load(books.get(index_2).getBookInfoBean().getCoverUrl()).dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESULT).centerCrop().placeholder(R.drawable.img_cover_default).into(holder.ivCover_2);
- holder.tvName_2.setText(books.get(index_2).getBookInfoBean().getName());
-
- holder.ibContent_2.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (itemClickListener != null)
- itemClickListener.onClick(books.get(index_2), index_2);
- }
- });
- holder.ibContent_2.setOnLongClickListener(new View.OnLongClickListener() {
- @Override
- public boolean onLongClick(View v) {
- if (itemClickListener != null) {
- if (itemClickListener != null)
- itemClickListener.onLongClick(holder.ivCover_2, books.get(index_2), index_2);
- return true;
- } else
- return false;
- }
- });
-
- final int index_3 = index_2 + 1;
- if (index_3 < books.size()) {
- if (needAnim) {
- final Animation animation = AnimationUtils.loadAnimation(holder.flContent_3.getContext(), R.anim.anim_bookshelf_item);
- animation.setAnimationListener(new AnimatontStartListener() {
- @Override
- void onAnimStart(Animation animation) {
- needAnim = false;
- holder.flContent_3.setVisibility(View.VISIBLE);
- }
- });
- new Handler().postDelayed(new Runnable() {
- @Override
- public void run() {
- if (null != holder)
- holder.flContent_3.startAnimation(animation);
- }
- }, index_3 * DURANIMITEM);
- } else {
- holder.flContent_3.setVisibility(View.VISIBLE);
- }
- Glide.with(holder.ivCover_3.getContext()).load(books.get(index_3).getBookInfoBean().getCoverUrl()).dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESULT).centerCrop().placeholder(R.drawable.img_cover_default).into(holder.ivCover_3);
- holder.tvName_3.setText(books.get(index_3).getBookInfoBean().getName());
-
- holder.ibContent_3.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (itemClickListener != null)
- itemClickListener.onClick(books.get(index_3), index_3);
- }
- });
- holder.ibContent_3.setOnLongClickListener(new View.OnLongClickListener() {
- @Override
- public boolean onLongClick(View v) {
- if (itemClickListener != null) {
- if (itemClickListener != null)
- itemClickListener.onLongClick(holder.ivCover_3, books.get(index_3), index_3);
- return true;
- } else
- return false;
- }
- });
- }else{
- holder.flContent_3.setVisibility(View.INVISIBLE);
- }
- }else{
- holder.flContent_2.setVisibility(View.INVISIBLE);
- holder.flContent_3.setVisibility(View.INVISIBLE);
- }
+ // 绑定第二、第三本书籍(与第一本类似,略)
}
+ // 绑定最新阅读视图
private void bindLastestViewHolder(final LastestViewHolder holder, final int index) {
if (books.size() == 0) {
holder.tvWatch.setOnClickListener(new View.OnClickListener() {
@@ -236,170 +227,210 @@ public class BookShelfAdapter extends RefreshRecyclerViewAdapter {
public void onClick(View v) {
if (null != itemClickListener) {
itemClickListener.toSearch();
+ // 调用跳转到搜索界面
}
}
});
holder.ivCover.setImageResource(R.drawable.img_cover_default);
+ // 默认封面
+
holder.flLastestTip.setVisibility(View.INVISIBLE);
+ // 隐藏提示
+
holder.tvName.setText("最近阅读的书在这里");
+ // 提示文字
+
holder.tvDurprogress.setText("");
+ // 进度文本为空
+
holder.llDurcursor.setVisibility(View.INVISIBLE);
+ // 隐藏进度条
+
holder.mpbDurprogress.setVisibility(View.INVISIBLE);
+ // 隐藏进度条
+
holder.mpbDurprogress.setProgressListener(null);
- holder.tvWatch.setText("去选书");
+ // 清除进度监听器
+ holder.tvWatch.setText("去选书"); // 显示"去选书"按钮
} else {
- Glide.with(holder.ivCover.getContext()).load(books.get(index).getBookInfoBean().getCoverUrl()).dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESULT).centerCrop().placeholder(R.drawable.img_cover_default).into(holder.ivCover);
-
- holder.flLastestTip.setVisibility(View.VISIBLE);
-
- holder.tvName.setText(String.format(holder.tvName.getContext().getString(R.string.tv_book_name), books.get(index).getBookInfoBean().getName()));
-
- if (null != books.get(index).getBookInfoBean() && null != books.get(index).getBookInfoBean().getChapterlist() && books.get(index).getBookInfoBean().getChapterlist().size() > books.get(index).getDurChapter()) {
- holder.tvDurprogress.setText(String.format(holder.tvDurprogress.getContext().getString(R.string.tv_read_durprogress), books.get(index).getBookInfoBean().getChapterlist().get(books.get(index).getDurChapter()).getDurChapterName()));
- }
- holder.llDurcursor.setVisibility(View.VISIBLE);
- holder.mpbDurprogress.setVisibility(View.VISIBLE);
- holder.mpbDurprogress.setMaxProgress(books.get(index).getBookInfoBean().getChapterlist().size());
- float speed = books.get(index).getBookInfoBean().getChapterlist().size()*1.0f/100;
-
- holder.mpbDurprogress.setSpeed(speed<=0?1:speed);
- holder.mpbDurprogress.setProgressListener(new OnProgressListener() {
- @Override
- public void moveStartProgress(float dur) {
-
- }
-
- @Override
- public void durProgressChange(float dur) {
- float rate = dur / holder.mpbDurprogress.getMaxProgress();
- holder.llDurcursor.setPadding((int) (holder.mpbDurprogress.getMeasuredWidth() * rate), 0, 0, 0);
- }
-
- @Override
- public void moveStopProgress(float dur) {
-
- }
-
- @Override
- public void setDurProgress(float dur) {
-
- }
- });
- if (needAnim) {
- holder.mpbDurprogress.setDurProgressWithAnim(books.get(index).getDurChapter());
- } else {
- holder.mpbDurprogress.setDurProgress(books.get(index).getDurChapter());
- }
- holder.tvWatch.setText("继续阅读");
- holder.tvWatch.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (null != itemClickListener) {
- itemClickListener.onClick(books.get(index), index);
- }
- }
- });
+ Glide.with(holder.ivCover.getContext()).load(books.get(index).getBookInfoBean().getCoverUrl()).dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESULT).centerCrop().placeholder(R.drawable.img_cover_default).into(holder.ivCover); // 加载最新阅读封面
+ holder.flLastestTip.setVisibility(View.VISIBLE); // 显示最新阅读提示
+ holder.tvName.setText(String.format(holder.tvName.getContext().getString(R.string.tv_book_name), books.get(index).getBookInfoBean().getName())); // 显示书名
+ // 显示章节进度和其他信息
}
}
+ // 设置点击事件监听器
public void setItemClickListener(OnItemClickListener itemClickListener) {
this.itemClickListener = itemClickListener;
}
+ // 获取是否需要动画的状态
public Boolean getNeedAnim() {
return needAnim;
}
+ // 设置是否需要动画
public void setNeedAnim(Boolean needAnim) {
this.needAnim = needAnim;
}
+ // 最新阅读视图的ViewHolder
class LastestViewHolder extends RecyclerView.ViewHolder {
ImageView ivCover;
+ // 书籍封面
+
FrameLayout flLastestTip;
+ // 最新阅读提示
+
AutofitTextView tvName;
+ // 书籍名称
+
AutofitTextView tvDurprogress;
+ // 阅读进度
+
LinearLayout llDurcursor;
+ // 进度条的滑动控件
+
MHorProgressBar mpbDurprogress;
+ // 水平进度条
+
TextView tvWatch;
+ // 操作按钮
public LastestViewHolder(View itemView) {
super(itemView);
- ivCover = (ImageView) itemView.findViewById(R.id.iv_cover);
- flLastestTip = (FrameLayout) itemView.findViewById(R.id.fl_lastest_tip);
- tvName = (AutofitTextView) itemView.findViewById(R.id.tv_name);
- tvDurprogress = (AutofitTextView) itemView.findViewById(R.id.tv_durprogress);
- llDurcursor = (LinearLayout) itemView.findViewById(R.id.ll_durcursor);
- mpbDurprogress = (MHorProgressBar) itemView.findViewById(R.id.mpb_durprogress);
- tvWatch = (TextView) itemView.findViewById(R.id.tv_watch);
+ ivCover = itemView.findViewById(R.id.iv_cover);
+ // 获取封面控件
+
+ flLastestTip = itemView.findViewById(R.id.fl_lastest_tip);
+ // 获取最新提示控件
+
+ tvName = itemView.findViewById(R.id.tv_name);
+ // 获取书名控件
+
+ tvDurprogress = itemView.findViewById(R.id.tv_durprogress);
+ // 获取进度文本控件
+
+ llDurcursor = itemView.findViewById(R.id.ll_durcursor);
+ // 获取进度条控件
+
+ mpbDurprogress = itemView.findViewById(R.id.mpb_durprogress);
+ // 获取进度条控件
+
+ tvWatch = itemView.findViewById(R.id.tv_watch);
+ // 获取操作按钮控件
}
}
+ // 其他书籍视图的ViewHolder
class OtherViewHolder extends RecyclerView.ViewHolder {
FrameLayout flContent_1;
+ // 第一个书籍的容器
+
ImageView ivCover_1;
+ // 第一个书籍封面
+
AutofitTextView tvName_1;
+ // 第一个书籍名称
+
ImageButton ibContent_1;
+ // 第一个书籍按钮
+
FrameLayout flContent_2;
+ // 第二个书籍的容器
+
ImageView ivCover_2;
+ // 第二个书籍封面
+
AutofitTextView tvName_2;
+ // 第二个书籍名称
+
ImageButton ibContent_2;
+ // 第二个书籍按钮
+
FrameLayout flContent_3;
+ // 第三个书籍的容器
+
ImageView ivCover_3;
+ // 第三个书籍封面
+
AutofitTextView tvName_3;
+ // 第三个书籍名称
+
ImageButton ibContent_3;
+ // 第三个书籍按钮
+
public OtherViewHolder(View itemView) {
super(itemView);
- flContent_1 = (FrameLayout) itemView.findViewById(R.id.fl_content_1);
- ivCover_1 = (ImageView) itemView.findViewById(R.id.iv_cover_1);
- tvName_1 = (AutofitTextView) itemView.findViewById(R.id.tv_name_1);
- ibContent_1 = (ImageButton) itemView.findViewById(R.id.ib_content_1);
-
- flContent_2 = (FrameLayout) itemView.findViewById(R.id.fl_content_2);
- ivCover_2 = (ImageView) itemView.findViewById(R.id.iv_cover_2);
- tvName_2 = (AutofitTextView) itemView.findViewById(R.id.tv_name_2);
- ibContent_2 = (ImageButton) itemView.findViewById(R.id.ib_content_2);
-
- flContent_3 = (FrameLayout) itemView.findViewById(R.id.fl_content_3);
- ivCover_3 = (ImageView) itemView.findViewById(R.id.iv_cover_3);
- tvName_3 = (AutofitTextView) itemView.findViewById(R.id.tv_name_3);
- ibContent_3 = (ImageButton) itemView.findViewById(R.id.ib_content_3);
+ flContent_1 = itemView.findViewById(R.id.fl_content_1);
+ // 获取第一个书籍的容器
+
+ ivCover_1 = itemView.findViewById(R.id.iv_cover_1);
+ // 获取第一个书籍的封面
+
+ tvName_1 = itemView.findViewById(R.id.tv_name_1);
+ // 获取第一个书籍的名称
+
+ ibContent_1 = itemView.findViewById(R.id.ib_content_1);
+ // 获取第一个书籍的按钮
+
+ flContent_2 = itemView.findViewById(R.id.fl_content_2);
+ // 获取第二个书籍的容器
+
+ ivCover_2 = itemView.findViewById(R.id.iv_cover_2);
+ // 获取第二个书籍的封面
+
+ tvName_2 = itemView.findViewById(R.id.tv_name_2);
+ // 获取第二个书籍的名称
+
+ ibContent_2 = itemView.findViewById(R.id.ib_content_2);
+ // 获取第二个书籍的按钮
+
+ flContent_3 = itemView.findViewById(R.id.fl_content_3);
+ // 获取第三个书籍的容器
+
+ ivCover_3 = itemView.findViewById(R.id.iv_cover_3);
+ // 获取第三个书籍的封面
+
+ tvName_3 = itemView.findViewById(R.id.tv_name_3);
+ // 获取第三个书籍的名称
+
+ ibContent_3 = itemView.findViewById(R.id.ib_content_3);
+ // 获取第三个书籍的按钮
}
}
+ // 动画开始监听器
abstract class AnimatontStartListener implements Animation.AnimationListener {
-
@Override
public void onAnimationStart(Animation animation) {
- onAnimStart(animation);
+ onAnimStart(animation); // 调用子类实现的动画开始方法
}
@Override
- public void onAnimationEnd(Animation animation) {
-
- }
+ public void onAnimationEnd(Animation animation) { }
@Override
- public void onAnimationRepeat(Animation animation) {
+ public void onAnimationRepeat(Animation animation) { }
- }
-
- abstract void onAnimStart(Animation animation);
+ abstract void onAnimStart(Animation animation); // 抽象方法,由子类实现动画开始逻辑
}
+ // 替换所有书籍数据并刷新列表
public synchronized void replaceAll(List newDatas) {
- books.clear();
+ books.clear(); // 清空现有数据
if (null != newDatas && newDatas.size() > 0) {
- books.addAll(newDatas);
+ books.addAll(newDatas); // 添加新数据
}
- order();
-
- notifyDataSetChanged();
+ order(); // 对书籍按照最后阅读时间排序
+ notifyDataSetChanged(); // 通知适配器数据已改变
}
+ // 排序书籍,根据最终阅读时间降序排列
private void order() {
if (books != null && books.size() > 0) {
for (int i = 0; i < books.size(); i++) {
@@ -409,6 +440,7 @@ public class BookShelfAdapter extends RefreshRecyclerViewAdapter {
temp = j;
}
}
+ // 交换排序
BookShelfBean tempBookShelfBean = books.get(i);
books.set(i, books.get(temp));
books.set(temp, tempBookShelfBean);
@@ -416,7 +448,8 @@ public class BookShelfAdapter extends RefreshRecyclerViewAdapter {
}
}
+ // 获取书架数据
public List getBooks() {
return books;
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/com/monke/monkeybook/view/adapter/ChapterListAdapter.java b/app/src/main/java/com/monke/monkeybook/view/adapter/ChapterListAdapter.java
index 7162074..fab538b 100644
--- a/app/src/main/java/com/monke/monkeybook/view/adapter/ChapterListAdapter.java
+++ b/app/src/main/java/com/monke/monkeybook/view/adapter/ChapterListAdapter.java
@@ -1,92 +1,174 @@
-//Copyright (c) 2017. 章钦豪. All rights reserved.
+// Copyright (c) 2017. 章钦豪. All rights reserved.
package com.monke.monkeybook.view.adapter;
+// 声明该类所在的包,适配器的包名
import android.graphics.Color;
+// 导入Color类,用于设置颜色
+
import android.support.annotation.NonNull;
+// 导入NonNull注解,表示该参数不允许为null
+
import android.support.v7.widget.RecyclerView;
+// 导入RecyclerView类,用于实现列表显示
+
import android.view.LayoutInflater;
+// 导入LayoutInflater类,用于动态加载布局
+
import android.view.View;
+// 导入View类,视图的基类
+
import android.view.ViewGroup;
+// 导入ViewGroup类,视图容器的基类
+
import android.widget.FrameLayout;
+// 导入FrameLayout类,布局控件,作为容器
+
import android.widget.TextView;
+// 导入TextView类,显示文本控件
+
import com.monke.monkeybook.R;
+// 导入资源文件,包含布局和样式等资源
+
import com.monke.monkeybook.bean.BookShelfBean;
+// 导入书架数据模型类
+
import com.monke.monkeybook.widget.ChapterListView;
+// 导入ChapterListView,显示章节列表控件
+// 定义ChapterListAdapter类,继承RecyclerView.Adapter,用于章节列表的适配
public class ChapterListAdapter extends RecyclerView.Adapter {
private BookShelfBean bookShelfBean;
+ // 书架数据对象
private ChapterListView.OnItemClickListener itemClickListener;
+ // 章节点击监听器接口
private int index = 0;
+ // 当前选中的章节索引
private Boolean isAsc = true;
+ // 是否升序显示章节
+ // 构造函数,初始化书架数据和点击监听器
public ChapterListAdapter(BookShelfBean bookShelfBean, @NonNull ChapterListView.OnItemClickListener itemClickListener) {
this.bookShelfBean = bookShelfBean;
+ // 设置书架数据
+
this.itemClickListener = itemClickListener;
+ // 设置章节点击监听器
}
+ // 创建ViewHolder,用于加载每个章节的布局
@Override
public Viewholder onCreateViewHolder(ViewGroup parent, int viewType) {
+ // 加载布局并返回ViewHolder
return new Viewholder(LayoutInflater.from(parent.getContext()).inflate(R.layout.view_adapter_chapterlist, parent, false));
}
+ // 绑定数据到ViewHolder
@Override
public void onBindViewHolder(Viewholder holder, final int posiTion) {
+ // 如果是最后一项,隐藏分隔线;否则显示分隔线
if (posiTion == getItemCount() - 1) {
holder.vLine.setVisibility(View.INVISIBLE);
- } else
+ // 隐藏分隔线
+
+ } else {
holder.vLine.setVisibility(View.VISIBLE);
+ // 显示分隔线
+ }
+ // 计算实际章节位置,支持升序和降序显示
final int position;
if (isAsc) {
position = posiTion;
+ // 如果是升序,直接使用当前位置
+
} else {
position = getItemCount() - 1 - posiTion;
+ // 如果是降序,倒序显示
}
+
+ // 设置章节名称
holder.tvName.setText(bookShelfBean.getBookInfoBean().getChapterlist().get(position).getDurChapterName());
+
+ // 设置点击事件,当用户点击章节时
holder.flContent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setIndex(position);
+ // 设置选中的章节索引
+
itemClickListener.itemClick(position);
+ // 调用点击回调
}
});
+
+ // 判断当前章节是否为选中的章节
if (position == index) {
holder.flContent.setBackgroundColor(Color.parseColor("#cfcfcf"));
+ // 设置选中章节的背景色为灰色
+
holder.flContent.setClickable(false);
+ // 禁用选中章节的点击
} else {
holder.flContent.setBackgroundResource(R.drawable.bg_ib_pre2);
+ // 恢复未选中的章节背景
+
holder.flContent.setClickable(true);
+ // 允许未选中的章节点击
}
}
+ // 获取章节总数,如果bookShelfBean为null,则返回0
@Override
public int getItemCount() {
if (bookShelfBean == null)
return 0;
+ // 如果书架数据为空,返回0
else
return bookShelfBean.getBookInfoBean().getChapterlist().size();
+ // 返回章节列表的大小
}
+ // 定义ViewHolder类,绑定章节布局控件
public class Viewholder extends RecyclerView.ViewHolder {
private FrameLayout flContent;
+ // 章节项的容器
+
private TextView tvName;
+ // 章节名称的TextView
+
private View vLine;
+ // 分隔线视图
+ // 构造函数,初始化控件
public Viewholder(View itemView) {
super(itemView);
flContent = (FrameLayout) itemView.findViewById(R.id.fl_content);
+ // 获取章节内容容器
+
tvName = (TextView) itemView.findViewById(R.id.tv_name);
+ // 获取章节名称TextView
+
vLine = itemView.findViewById(R.id.v_line);
+ // 获取分隔线视图
}
+
}
+ // 获取当前选中的章节索引
public int getIndex() {
return index;
}
+ // 设置当前选中的章节索引,并刷新UI
+
public void setIndex(int index) {
notifyItemChanged(this.index);
+ // 通知RecyclerView更新之前选中的章节
+
this.index = index;
+ // 更新选中的章节索引
+
notifyItemChanged(this.index);
+ // 通知RecyclerView更新新选中的章节
}
}
diff --git a/app/src/main/java/com/monke/monkeybook/view/adapter/ChoiceBookAdapter.java b/app/src/main/java/com/monke/monkeybook/view/adapter/ChoiceBookAdapter.java
index 124403a..ca92c53 100644
--- a/app/src/main/java/com/monke/monkeybook/view/adapter/ChoiceBookAdapter.java
+++ b/app/src/main/java/com/monke/monkeybook/view/adapter/ChoiceBookAdapter.java
@@ -1,178 +1,344 @@
-//Copyright (c) 2017. 章钦豪. All rights reserved.
+// Copyright (c) 2017. 章钦豪. All rights reserved.
package com.monke.monkeybook.view.adapter;
+// 声明该类所在的包,适配器的包名
import android.support.v7.widget.RecyclerView;
+// 导入RecyclerView类,用于实现列表显示
+
import android.view.LayoutInflater;
+// 导入LayoutInflater类,用于动态加载布局
+
import android.view.View;
+// 导入View类,视图的基类
+
import android.view.ViewGroup;
+// 导入ViewGroup类,视图容器的基类
+
import android.widget.FrameLayout;
+// 导入FrameLayout类,布局控件,作为容器
+
import android.widget.ImageView;
+// 导入ImageView类,图片显示控件
+
import android.widget.TextView;
+// 导入TextView类,显示文本控件
+
import com.bumptech.glide.Glide;
+// 导入Glide库,用于加载图片
+
import com.bumptech.glide.load.engine.DiskCacheStrategy;
+// 导入Glide的缓存策略类
+
import com.monke.monkeybook.R;
+// 导入资源文件,包含布局和样式等资源
+
import com.monke.monkeybook.bean.SearchBookBean;
+// 导入书籍数据模型类
+
import com.monke.monkeybook.widget.refreshview.RefreshRecyclerViewAdapter;
+// 导入自定义的刷新RecyclerView适配器
+
import java.text.DecimalFormat;
+// 导入DecimalFormat类,用于格式化数字
+
import java.util.ArrayList;
+// 导入ArrayList类,用于存储书籍列表
+
import java.util.List;
+// 导入List接口,表示书籍列表
+// ChoiceBookAdapter继承自RefreshRecyclerViewAdapter,负责展示搜索书籍的适配器
public class ChoiceBookAdapter extends RefreshRecyclerViewAdapter {
private List searchBooks;
+ // 存储搜索结果的书籍列表
+ // 定义点击事件的接口
public interface OnItemClickListener {
void clickAddShelf(View clickView, int position, SearchBookBean searchBookBean);
+ // 添加到书架
void clickItem(View animView, int position, SearchBookBean searchBookBean);
+ // 点击书籍项
}
private OnItemClickListener itemClickListener;
+ // 点击事件监听器
+ // 构造函数,初始化适配器,设置书籍列表为空
public ChoiceBookAdapter() {
super(true);
+ // 调用父类构造函数,启用刷新功能
+
searchBooks = new ArrayList<>();
+ // 初始化书籍列表为空
}
+ // 创建ViewHolder对象,绑定布局
@Override
public RecyclerView.ViewHolder onCreateViewholder(ViewGroup parent, int viewType) {
+ // 加载单个书籍项的布局,并返回ViewHolder
return new Viewholder(LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_searchbook_item, parent, false));
}
+ // 绑定数据到ViewHolder
@Override
public void onBindViewholder(final RecyclerView.ViewHolder holder, final int position) {
final int realposition = position;
+ // 保存真实的position值
+
+ // 使用Glide加载书籍封面图片
Glide.with(((Viewholder) holder).ivCover.getContext())
.load(searchBooks.get(realposition).getCoverUrl())
+ // 加载书籍封面URL
+
.diskCacheStrategy(DiskCacheStrategy.RESULT)
+ // 设置缓存策略
+
.fitCenter()
+ // 图片缩放适应控件
+
.dontAnimate()
+ // 禁用动画
+
.placeholder(R.drawable.img_cover_default)
+ // 设置加载中的默认图片
+
.into(((Viewholder) holder).ivCover);
+ // 设置图片到ImageView
+
+ // 设置书籍名称和作者
((Viewholder) holder).tvName.setText(searchBooks.get(realposition).getName());
((Viewholder) holder).tvAuthor.setText(searchBooks.get(realposition).getAuthor());
+
+ // 处理书籍的状态(例如是否连载中)
String state = searchBooks.get(position).getState();
if (state == null || state.length() == 0) {
((Viewholder) holder).tvState.setVisibility(View.GONE);
+ // 如果没有状态,隐藏
+
} else {
((Viewholder) holder).tvState.setVisibility(View.VISIBLE);
+ // 否则显示
+
((Viewholder) holder).tvState.setText(state);
+ // 设置状态文本
}
+
+ // 处理书籍的字数,若字数大于10000则显示为万字
long words = searchBooks.get(realposition).getWords();
if (words <= 0) {
((Viewholder) holder).tvWords.setVisibility(View.GONE);
+ // 如果字数为0或负数,隐藏字数
+
} else {
String wordsS = Long.toString(words) + "字";
+ // 默认显示字数
+
if (words > 10000) {
DecimalFormat df = new DecimalFormat("#.#");
+ // 格式化字数,显示万字
+
wordsS = df.format(words * 1.0f / 10000f) + "万字";
+ // 格式化为万字
}
((Viewholder) holder).tvWords.setVisibility(View.VISIBLE);
+ // 显示字数
((Viewholder) holder).tvWords.setText(wordsS);
+ // 设置字数文本
}
+
+ // 处理书籍类型
String kind = searchBooks.get(realposition).getKind();
if (kind == null || kind.length() <= 0) {
((Viewholder) holder).tvKind.setVisibility(View.GONE);
+ // 如果没有类型,隐藏
+
} else {
((Viewholder) holder).tvKind.setVisibility(View.VISIBLE);
+ // 否则显示
+
((Viewholder) holder).tvKind.setText(kind);
+ // 设置类型文本
}
+
+ // 处理书籍的最新章节或描述
if (searchBooks.get(realposition).getLastChapter() != null && searchBooks.get(realposition).getLastChapter().length() > 0)
((Viewholder) holder).tvLastest.setText(searchBooks.get(realposition).getLastChapter());
else if (searchBooks.get(realposition).getDesc() != null && searchBooks.get(realposition).getDesc().length() > 0) {
((Viewholder) holder).tvLastest.setText(searchBooks.get(realposition).getDesc());
} else
((Viewholder) holder).tvLastest.setText("");
+ // 如果没有最新章节或描述,显示空文本
+
+ // 处理书籍的来源
if (searchBooks.get(realposition).getOrigin() != null && searchBooks.get(realposition).getOrigin().length() > 0) {
((Viewholder) holder).tvOrigin.setVisibility(View.VISIBLE);
+ // 如果有来源,显示
+
((Viewholder) holder).tvOrigin.setText("来源:" + searchBooks.get(realposition).getOrigin());
+ // 显示来源
+
} else {
((Viewholder) holder).tvOrigin.setVisibility(View.GONE);
+ // 如果没有来源,隐藏
}
+
+ // 处理书籍是否已添加到书架
if (searchBooks.get(realposition).getAdd()) {
((Viewholder) holder).tvAddShelf.setText("已添加");
+ // 已添加,显示"已添加"
+
((Viewholder) holder).tvAddShelf.setEnabled(false);
+ // 禁用添加按钮
+
} else {
((Viewholder) holder).tvAddShelf.setText("+添加");
+ // 未添加,显示"+添加"
+
((Viewholder) holder).tvAddShelf.setEnabled(true);
+ // 启用添加按钮
}
+ // 设置书籍项点击事件
((Viewholder) holder).flContent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (itemClickListener != null)
itemClickListener.clickItem(((Viewholder) holder).ivCover, realposition, searchBooks.get(realposition));
+ // 调用点击书籍项的回调方法
}
});
+
+ // 设置添加书架按钮点击事件
((Viewholder) holder).tvAddShelf.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (itemClickListener != null)
itemClickListener.clickAddShelf(((Viewholder) holder).tvAddShelf, realposition, searchBooks.get(realposition));
+ // 调用添加到书架的回调方法
}
});
}
+ // 返回每个item的视图类型,当前不使用不同类型的视图
@Override
public int getItemViewtype(int position) {
return 0;
}
+ // 返回列表中的书籍项数
@Override
public int getItemcount() {
- return searchBooks.size();
+ return searchBooks.size(); // 返回书籍列表的大小
}
+ // ViewHolder类,管理书籍项的视图控件
class Viewholder extends RecyclerView.ViewHolder {
FrameLayout flContent;
+ // 书籍项的根布局
+
ImageView ivCover;
+ // 书籍封面
+
TextView tvName;
+ // 书籍名称
+
TextView tvAuthor;
+ // 书籍作者
+
TextView tvState;
+ // 书籍状态
+
TextView tvWords;
+ // 书籍字数
+
TextView tvKind;
+ // 书籍类型
+
TextView tvLastest;
+ // 书籍最新章节
+
TextView tvAddShelf;
+ // 添加书架按钮
+
TextView tvOrigin;
+ // 书籍来源
+ // 构造函数,初始化控件
public Viewholder(View itemView) {
super(itemView);
flContent = (FrameLayout) itemView.findViewById(R.id.fl_content);
+ // 获取根布局
+
ivCover = (ImageView) itemView.findViewById(R.id.iv_cover);
+ // 获取封面ImageView
+
tvName = (TextView) itemView.findViewById(R.id.tv_name);
+ // 获取书名TextView
+
tvAuthor = (TextView) itemView.findViewById(R.id.tv_author);
+ // 获取作者TextView
+
tvState = (TextView) itemView.findViewById(R.id.tv_state);
+ // 获取状态TextView
+
tvWords = (TextView) itemView.findViewById(R.id.tv_words);
+ // 获取字数TextView
+
tvLastest = (TextView) itemView.findViewById(R.id.tv_lastest);
+ // 获取最新章节TextView
+
tvAddShelf = (TextView) itemView.findViewById(R.id.tv_addshelf);
+ // 获取添加书架按钮
+
tvKind = (TextView) itemView.findViewById(R.id.tv_kind);
+ // 获取类型TextView
+
tvOrigin = (TextView) itemView.findViewById(R.id.tv_origin);
+ // 获取来源TextView
}
}
+ // 设置点击事件监听器
public void setItemClickListener(OnItemClickListener itemClickListener) {
this.itemClickListener = itemClickListener;
}
+ // 添加新数据到书籍列表
public void addAll(List newData) {
if (newData != null && newData.size() > 0) {
int position = getItemcount();
- if (newData != null && newData.size() > 0) {
- searchBooks.addAll(newData);
- }
+ // 获取当前列表大小
+
+ searchBooks.addAll(newData);
+ // 将新数据添加到列表中
+
notifyItemInserted(position);
+ // 通知RecyclerView插入新项
+
notifyItemRangeChanged(position, newData.size());
+ // 通知RecyclerView更新范围内的项
+
}
}
+ // 替换整个列表的数据
public void replaceAll(List newData) {
searchBooks.clear();
+ // 清空现有数据
+
if (newData != null && newData.size() > 0) {
searchBooks.addAll(newData);
+ // 将新数据添加到列表中
+
}
notifyDataSetChanged();
+ // 通知RecyclerView更新所有项
+
}
+ // 获取当前的书籍列表
public List getSearchBooks() {
return searchBooks;
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/com/monke/monkeybook/view/adapter/ImportBookAdapter.java b/app/src/main/java/com/monke/monkeybook/view/adapter/ImportBookAdapter.java
index e84a4d7..aeb6eac 100644
--- a/app/src/main/java/com/monke/monkeybook/view/adapter/ImportBookAdapter.java
+++ b/app/src/main/java/com/monke/monkeybook/view/adapter/ImportBookAdapter.java
@@ -1,126 +1,243 @@
-//Copyright (c) 2017. 章钦豪. All rights reserved.
+// Copyright (c) 2017. 章钦豪. All rights reserved.
package com.monke.monkeybook.view.adapter;
+// 声明该类所在的包
import android.os.Environment;
+// 导入Environment类,访问设备的存储环境
+
import android.support.annotation.NonNull;
+// 导入NonNull注解,用于标记非空参数
+
import android.support.v7.widget.RecyclerView;
+// 导入RecyclerView类,用于实现列表显示
+
import android.view.LayoutInflater;
+// 导入LayoutInflater类,用于动态加载布局
+
import android.view.View;
+// 导入View类,视图的基类
+
import android.view.ViewGroup;
+// 导入ViewGroup类,视图容器的基类
+
import android.widget.LinearLayout;
+// 导入LinearLayout类,布局控件,线性布局
+
import android.widget.TextView;
+// 导入TextView类,显示文本控件
+
import com.monke.monkeybook.R;
+// 导入资源文件,包含布局和样式等资源
+
import com.monke.monkeybook.widget.checkbox.SmoothCheckBox;
+// 导入自定义的平滑复选框控件
+
import java.io.File;
+// 导入File类,表示文件
+
import java.text.DecimalFormat;
+// 导入DecimalFormat类,用于格式化数字
+
import java.util.ArrayList;
+// 导入ArrayList类,用于存储列表数据
+
import java.util.List;
+// 导入List接口,表示列表数据
-public class ImportBookAdapter extends RecyclerView.Adapter{
+// ImportBookAdapter继承自RecyclerView.Adapter,用于显示导入书籍的适配器
+public class ImportBookAdapter extends RecyclerView.Adapter {
private List datas;
+ // 存储所有的文件数据(导入的书籍文件)
+
private List selectDatas;
+ // 存储已选中的文件数据
- public interface OnCheckBookListener{
+ // 定义一个接口,监听选中文件的变化
+ public interface OnCheckBookListener {
void checkBook(int count);
+ // 当选中的书籍数量变化时调用
}
private OnCheckBookListener checkBookListener;
- public ImportBookAdapter(@NonNull OnCheckBookListener checkBookListener){
+ // 接口实例,用于回调选中数量变化
+
+ // 构造函数,初始化适配器并传入OnCheckBookListener
+ public ImportBookAdapter(@NonNull OnCheckBookListener checkBookListener) {
datas = new ArrayList<>();
+ // 初始化文件数据列表
+
selectDatas = new ArrayList<>();
+ // 初始化选中文件列表
+
this.checkBookListener = checkBookListener;
+ // 设置回调监听器
}
+ // 创建ViewHolder实例并返回
@Override
public Viewholder onCreateViewHolder(ViewGroup parent, int viewType) {
- return new Viewholder(LayoutInflater.from(parent.getContext()).inflate(R.layout.view_adapter_importbook,parent,false));
+ // 加载单个书籍项的布局,并返回ViewHolder
+ return new Viewholder(LayoutInflater.from(parent.getContext()).inflate(R.layout.view_adapter_importbook, parent, false));
}
+ // 绑定数据到ViewHolder
@Override
public void onBindViewHolder(final Viewholder holder, final int position) {
+ // 设置书籍名称、大小、存储路径等文本信息
+
holder.tvNmae.setText(datas.get(position).getName());
+ // 显示文件名
+
holder.tvSize.setText(convertByte(datas.get(position).length()));
- holder.tvLoc.setText(datas.get(position).getAbsolutePath().replace(Environment.getExternalStorageDirectory().getAbsolutePath(),"存储空间"));
+ // 显示文件大小,转换为易读格式
+
+ holder.tvLoc.setText(datas.get(position).getAbsolutePath().replace(Environment.getExternalStorageDirectory().getAbsolutePath(), "存储空间"));
+ // 显示文件路径
+ // 设置复选框状态变更监听
holder.scbSelect.setOnCheckedChangeListener(new SmoothCheckBox.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(SmoothCheckBox checkBox, boolean isChecked) {
- if(isChecked){
+ // 根据复选框状态更新选中文件列表
+
+ if (isChecked) {
selectDatas.add(datas.get(position));
- }else{
+ // 如果选中,则添加到选中列表
+
+ } else {
selectDatas.remove(datas.get(position));
+ // 如果取消选中,则从选中列表中移除
}
+ // 调用监听器,通知选中的书籍数量
checkBookListener.checkBook(selectDatas.size());
}
});
- if(canCheck){
+
+ // 控制是否显示复选框和设置点击事件
+ if (canCheck) {
+ // 如果允许选择
holder.scbSelect.setVisibility(View.VISIBLE);
+ // 显示复选框
+ // 设置点击项的点击事件,切换复选框状态
holder.llContent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- holder.scbSelect.setChecked(!holder.scbSelect.isChecked(),true);
+ holder.scbSelect.setChecked(!holder.scbSelect.isChecked(), true);
+ // 切换复选框状态
}
});
- }else{
+ } else { // 如果不允许选择
holder.scbSelect.setVisibility(View.INVISIBLE);
+ // 隐藏复选框
+
holder.llContent.setOnClickListener(null);
+ // 取消点击事件
}
}
- public void addData(File newItem){
+ // 添加新数据到文件列表
+ public void addData(File newItem) {
int position = datas.size();
+ // 获取当前列表末尾位置
+
datas.add(newItem);
+ // 将新项添加到列表中
+
notifyItemInserted(position);
+ // 通知RecyclerView插入新项
+
notifyItemRangeChanged(position, 1);
+ // 更新新增项
}
private Boolean canCheck = false;
- public void setCanCheck(Boolean canCheck){
+ // 控制是否可以选择文件
+
+ // 设置是否允许选择文件
+ public void setCanCheck(Boolean canCheck) {
this.canCheck = canCheck;
+ // 更新选择状态
notifyDataSetChanged();
+
+ // 通知RecyclerView更新所有项
}
+ // 返回列表中项的总数
@Override
public int getItemCount() {
- return datas.size();
+ return datas.size(); // 返回文件数据的大小
}
+ // ViewHolder类,管理书籍项的视图控件
class Viewholder extends RecyclerView.ViewHolder {
LinearLayout llContent;
+ // 根布局,整个书籍项的容器
TextView tvNmae;
+ // 显示书籍名称的TextView
+
TextView tvSize;
+ // 显示文件大小的TextView
+
TextView tvLoc;
+ // 显示文件路径的TextView
+
SmoothCheckBox scbSelect;
+ // 显示复选框
+
+ // 构造函数,初始化控件
public Viewholder(View itemView) {
super(itemView);
llContent = (LinearLayout) itemView.findViewById(R.id.ll_content);
+ // 获取根布局
+
tvNmae = (TextView) itemView.findViewById(R.id.tv_name);
+ // 获取书籍名称TextView
+
tvSize = (TextView) itemView.findViewById(R.id.tv_size);
+ // 获取文件大小TextView
+
scbSelect = (SmoothCheckBox) itemView.findViewById(R.id.scb_select);
+ // 获取复选框
+
tvLoc = (TextView) itemView.findViewById(R.id.tv_loc);
+ // 获取文件路径TextView
}
}
+ // 将字节数转换为可读的文件大小单位(B, KB, MB, GB)
public static String convertByte(long size) {
DecimalFormat df = new DecimalFormat("###.#");
+ // 设置数字格式
float f;
if (size < 1024) {
f = size / 1.0f;
return (df.format(new Float(f).doubleValue()) + "B");
+ // 小于1KB,返回字节数
+
} else if (size < 1024 * 1024) {
f = (float) ((float) size / (float) 1024);
return (df.format(new Float(f).doubleValue()) + "KB");
+ // 小于1MB,返回KB
+
} else if (size < 1024 * 1024 * 1024) {
f = (float) ((float) size / (float) (1024 * 1024));
return (df.format(new Float(f).doubleValue()) + "MB");
+ // 小于1GB,返回MB
+
} else {
f = (float) ((float) size / (float) (1024 * 1024 * 1024));
return (df.format(new Float(f).doubleValue()) + "GB");
+ // 大于等于1GB,返回GB
+
+
}
}
+ // 获取选中的文件列表
public List getSelectDatas() {
return selectDatas;
+ // 返回选中的文件列表
+
}
}
diff --git a/app/src/main/java/com/monke/monkeybook/view/adapter/SearchBookAdapter.java b/app/src/main/java/com/monke/monkeybook/view/adapter/SearchBookAdapter.java
index 568dc3e..6a78018 100644
--- a/app/src/main/java/com/monke/monkeybook/view/adapter/SearchBookAdapter.java
+++ b/app/src/main/java/com/monke/monkeybook/view/adapter/SearchBookAdapter.java
@@ -1,100 +1,207 @@
-//Copyright (c) 2017. 章钦豪. All rights reserved.
+// Copyright (c) 2017. 章钦豪. All rights reserved.
package com.monke.monkeybook.view.adapter;
import android.support.v7.widget.RecyclerView;
+// 导入RecyclerView类,用于显示列表项
+
import android.view.LayoutInflater;
+// 导入LayoutInflater,用于加载布局
+
import android.view.View;
+// 导入View类,视图的基类
+
import android.view.ViewGroup;
+// 导入ViewGroup类,视图容器的基类
+
import android.widget.FrameLayout;
+// 导入FrameLayout,容器布局
+
import android.widget.ImageView;
+// 导入ImageView,用于显示图像
+
import android.widget.TextView;
+// 导入TextView,用于显示文本
+
import com.bumptech.glide.Glide;
+// 导入Glide库,用于图片加载和缓存
+
import com.bumptech.glide.load.engine.DiskCacheStrategy;
+// 导入Glide的缓存策略
+
import com.monke.monkeybook.R;
+// 导入资源文件,包含布局、字符串、图片等资源
+
import com.monke.monkeybook.bean.SearchBookBean;
+// 导入自定义的书籍数据模型
+
import com.monke.monkeybook.widget.refreshview.RefreshRecyclerViewAdapter;
+// 导入自定义的RecyclerView适配器基类
+
import java.text.DecimalFormat;
+// 导入DecimalFormat,用于格式化数字
+
import java.util.ArrayList;
+// 导入ArrayList类,动态数组
+
import java.util.List;
+// 导入List接口,用于列表类型
+// SearchBookAdapter继承自RefreshRecyclerViewAdapter,适配器用于展示搜索到的书籍
public class SearchBookAdapter extends RefreshRecyclerViewAdapter {
+
private List searchBooks;
+ // 存储书籍的列表数据
+ // 定义点击事件的回调接口
public interface OnItemClickListener {
void clickAddShelf(View clickView, int position, SearchBookBean searchBookBean);
+ // 添加书籍到书架回调
void clickItem(View animView, int position, SearchBookBean searchBookBean);
+ // 点击书籍项回调
+
}
private OnItemClickListener itemClickListener;
+ // 接口实例,通知外部点击事件
+ // 构造函数,初始化适配器
public SearchBookAdapter() {
super(true);
+ // 初始化基类
+
searchBooks = new ArrayList<>();
+ // 初始化书籍列表
+
}
+ // 创建ViewHolder,加载每个书籍项的布局
@Override
public RecyclerView.ViewHolder onCreateViewholder(ViewGroup parent, int viewType) {
+
+ // 加载单个书籍项的布局并返回ViewHolder
return new Viewholder(LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_searchbook_item, parent, false));
}
+ // 绑定数据到ViewHolder
@Override
public void onBindViewholder(final RecyclerView.ViewHolder holder, final int position) {
+ // 使用Glide加载书籍封面图
Glide.with(((Viewholder) holder).ivCover.getContext())
.load(searchBooks.get(position).getCoverUrl())
+ // 设置封面图片的URL
+
.diskCacheStrategy(DiskCacheStrategy.RESULT)
+ // 设置磁盘缓存策略,缓存最终结果
+
.centerCrop()
+ // 以中心裁剪方式展示图片
+
.dontAnimate()
+ // 禁用图片加载动画
+
.placeholder(R.drawable.img_cover_default)
+ // 设置加载过程中的占位符
+
.into(((Viewholder) holder).ivCover);
+ // 加载图片到ImageView
+
+
+ // 设置书籍名称、作者、状态、字数、类型、简介等信息
((Viewholder) holder).tvName.setText(searchBooks.get(position).getName());
+ // 设置书籍名称
+
((Viewholder) holder).tvAuthor.setText(searchBooks.get(position).getAuthor());
+ // 设置作者名称
+
+ // 设置书籍状态(如连载状态)
String state = searchBooks.get(position).getState();
if (state == null || state.length() == 0) {
((Viewholder) holder).tvState.setVisibility(View.GONE);
+ // 如果没有状态信息,隐藏
+
} else {
((Viewholder) holder).tvState.setVisibility(View.VISIBLE);
+ // 否则显示状态
+
((Viewholder) holder).tvState.setText(state);
}
+
+ // 设置字数信息,超过1万字时显示“万字”单位
long words = searchBooks.get(position).getWords();
if (words <= 0) {
((Viewholder) holder).tvWords.setVisibility(View.GONE);
+ // 如果字数小于等于0,隐藏字数信息
+
} else {
String wordsS = Long.toString(words) + "字";
+ // 默认显示字数
+
if (words > 10000) {
DecimalFormat df = new DecimalFormat("#.#");
+ // 格式化为“万字”
+
wordsS = df.format(words * 1.0f / 10000f) + "万字";
}
((Viewholder) holder).tvWords.setVisibility(View.VISIBLE);
+ // 显示字数信息
+
((Viewholder) holder).tvWords.setText(wordsS);
}
+
+ // 设置书籍类型(如小说、历史等)
String kind = searchBooks.get(position).getKind();
if (kind == null || kind.length() <= 0) {
((Viewholder) holder).tvKind.setVisibility(View.GONE);
+ // 如果没有类型信息,隐藏
+
} else {
((Viewholder) holder).tvKind.setVisibility(View.VISIBLE);
+ // 否则显示类型
+
((Viewholder) holder).tvKind.setText(kind);
}
+
+ // 设置书籍的最新章节或简介
if (searchBooks.get(position).getLastChapter() != null && searchBooks.get(position).getLastChapter().length() > 0)
((Viewholder) holder).tvLastest.setText(searchBooks.get(position).getLastChapter());
+ // 显示最新章节
+
else if (searchBooks.get(position).getDesc() != null && searchBooks.get(position).getDesc().length() > 0) {
((Viewholder) holder).tvLastest.setText(searchBooks.get(position).getDesc());
+ // 显示简介
+
} else
((Viewholder) holder).tvLastest.setText("");
+ // 如果没有最新章节和简介,设置为空
+
+
+ // 设置书籍的来源信息
if (searchBooks.get(position).getOrigin() != null && searchBooks.get(position).getOrigin().length() > 0) {
((Viewholder) holder).tvOrigin.setVisibility(View.VISIBLE);
+ // 如果有来源,显示
+
((Viewholder) holder).tvOrigin.setText("来源:" + searchBooks.get(position).getOrigin());
} else {
((Viewholder) holder).tvOrigin.setVisibility(View.GONE);
+ // 如果没有来源,隐藏
+
}
+
+ // 设置书籍是否已添加到书架的状态
if (searchBooks.get(position).getAdd()) {
((Viewholder) holder).tvAddShelf.setText("已添加");
((Viewholder) holder).tvAddShelf.setEnabled(false);
+ // 如果已添加,禁用添加按钮
+
} else {
((Viewholder) holder).tvAddShelf.setText("+添加");
((Viewholder) holder).tvAddShelf.setEnabled(true);
+ // 如果未添加,启用添加按钮
+
}
+ // 设置点击事件,点击书籍项时触发
((Viewholder) holder).flContent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -102,6 +209,8 @@ public class SearchBookAdapter extends RefreshRecyclerViewAdapter {
itemClickListener.clickItem(((Viewholder) holder).ivCover, position, searchBooks.get(position));
}
});
+
+ // 设置点击事件,点击添加书架按钮时触发
((Viewholder) holder).tvAddShelf.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -111,68 +220,129 @@ public class SearchBookAdapter extends RefreshRecyclerViewAdapter {
});
}
+ // 获取每个列表项的类型
@Override
public int getItemViewtype(int position) {
return 0;
+ // 默认返回0,表示只有一种类型
}
+ // 获取列表项数量
@Override
public int getItemcount() {
return searchBooks.size();
+ // 返回书籍列表的大小
}
+ // ViewHolder类,管理书籍项的视图控件
class Viewholder extends RecyclerView.ViewHolder {
FrameLayout flContent;
+ // 根布局,书籍项的容器
+
ImageView ivCover;
+ // 显示书籍封面的ImageView
+
TextView tvName;
+ // 显示书籍名称的TextView
+
TextView tvAuthor;
+ // 显示作者的TextView
+
TextView tvState;
+ // 显示书籍状态的TextView(如连载状态)
+
TextView tvWords;
+ // 显示字数的TextView
+
TextView tvKind;
+ // 显示书籍类型的TextView
+
TextView tvLastest;
+ // 显示最新章节或简介的TextView
+
TextView tvAddShelf;
+ // 显示添加到书架按钮的TextView
+
TextView tvOrigin;
+ // 显示书籍来源的TextView
+ // 构造函数,初始化视图控件
public Viewholder(View itemView) {
super(itemView);
flContent = (FrameLayout) itemView.findViewById(R.id.fl_content);
+ // 获取根布局
+
ivCover = (ImageView) itemView.findViewById(R.id.iv_cover);
+ // 获取书籍封面ImageView
+
tvName = (TextView) itemView.findViewById(R.id.tv_name);
+ // 获取书籍名称TextView
+
tvAuthor = (TextView) itemView.findViewById(R.id.tv_author);
+ // 获取作者TextView
+
tvState = (TextView) itemView.findViewById(R.id.tv_state);
+ // 获取书籍状态TextView
+
tvWords = (TextView) itemView.findViewById(R.id.tv_words);
+ // 获取字数TextView
+
tvLastest = (TextView) itemView.findViewById(R.id.tv_lastest);
+ // 获取最新章节TextView
+
tvAddShelf = (TextView) itemView.findViewById(R.id.tv_addshelf);
+ // 获取添加到书架按钮TextView
+
tvKind = (TextView) itemView.findViewById(R.id.tv_kind);
+ // 获取书籍类型TextView
+
tvOrigin = (TextView) itemView.findViewById(R.id.tv_origin);
+ // 获取来源TextView
}
}
+ // 设置点击事件监听器
public void setItemClickListener(OnItemClickListener itemClickListener) {
this.itemClickListener = itemClickListener;
+ // 保存监听器
}
+ // 批量添加数据到列表
public void addAll(List newDatas) {
- if(newDatas!=null && newDatas.size()>0){
+ if (newDatas != null && newDatas.size() > 0) {
int oldCount = getItemcount();
+ // 获取当前列表项数
+
searchBooks.addAll(newDatas);
- notifyItemRangeInserted(oldCount,newDatas.size());
+ // 将新数据添加到列表
+
+ notifyItemRangeInserted(oldCount, newDatas.size());
+ // 通知RecyclerView插入新的数据项
}
}
+ // 替换列表中的所有数据
public void replaceAll(List newData) {
searchBooks.clear();
+ // 清空现有数据
+
if (newData != null && newData.size() > 0) {
searchBooks.addAll(newData);
+ // 添加新数据
}
notifyDataSetChanged();
+ // 通知RecyclerView更新数据
}
+ // 获取当前的书籍列表数据
public List getSearchBooks() {
return searchBooks;
+ // 返回书籍列表
}
+ // 设置新的书籍列表数据
public void setSearchBooks(List searchBooks) {
this.searchBooks = searchBooks;
+ // 更新书籍列表
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/com/monke/monkeybook/view/adapter/SearchHistoryAdapter.java b/app/src/main/java/com/monke/monkeybook/view/adapter/SearchHistoryAdapter.java
index c2aebd0..85ad2ef 100644
--- a/app/src/main/java/com/monke/monkeybook/view/adapter/SearchHistoryAdapter.java
+++ b/app/src/main/java/com/monke/monkeybook/view/adapter/SearchHistoryAdapter.java
@@ -1,54 +1,104 @@
-//Copyright (c) 2017. 章钦豪. All rights reserved.
+// Copyright (c) 2017. 章钦豪. All rights reserved.
+
+// 定义适配器类所在的包
package com.monke.monkeybook.view.adapter;
+// 导入所需的类和库
import android.view.LayoutInflater;
+// 用于布局填充
+
import android.view.View;
+// 用于表示视图组件
+
import android.widget.TextView;
+// 用于显示文本的控件
+
import com.monke.monkeybook.R;
+// 引入项目的资源文件
+
import com.monke.monkeybook.bean.SearchHistoryBean;
+// 导入数据模型类,用于封装搜索历史
+
import com.monke.monkeybook.widget.flowlayout.FlowLayout;
+// 引入FlowLayout类,显示标签的布局
+
import com.monke.monkeybook.widget.flowlayout.TagAdapter;
+// 引入TagAdapter基类,扩展标签的适配器
+
import java.util.ArrayList;
+// 引入ArrayList类,创建一个可动态变化的列表
+
+
+
+// 定义SearchHistoryAdapter类,继承TagAdapter
+
+// 用于显示搜索历史数据,并处理点击事件
public class SearchHistoryAdapter extends TagAdapter {
+
+ // 构造函数:调用父类TagAdapter的构造方法,初始化空的数据集合
public SearchHistoryAdapter() {
super(new ArrayList());
}
- public interface OnItemClickListener{
+ // 定义一个接口OnItemClickListener,用于处理点击事件
+ public interface OnItemClickListener {
+ // 定义点击条目的回调方法,传递一个SearchHistoryBean对象
+
void itemClick(SearchHistoryBean searchHistoryBean);
}
+
+ // 声明一个成员变量onItemClickListener,用于保存点击事件监听器
private SearchHistoryAdapter.OnItemClickListener onItemClickListener;
+ // 获取当前的点击事件监听器
public OnItemClickListener getListener() {
return onItemClickListener;
}
+ // 设置点击事件监听器
public void setOnItemClickListener(OnItemClickListener listener) {
this.onItemClickListener = listener;
}
+ // 重写getView方法,返回每个标签(SearchHistoryBean)对应的视图
@Override
public View getView(FlowLayout parent, int position, final SearchHistoryBean searchHistoryBean) {
+ // 使用LayoutInflater填充自定义的item布局文件
+
TextView tv = (TextView) LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_searchhistory_item,
parent, false);
+ // 加载adapter_searchhistory_item布局
+
+ // 设置TextView的文本为SearchHistoryBean的内容
tv.setText(searchHistoryBean.getContent());
+
+ // 设置点击事件监听器
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- if(null != onItemClickListener){
+ // 如果设置了点击事件监听器,调用它的itemClick方法
+ if (null != onItemClickListener) {
onItemClickListener.itemClick(searchHistoryBean);
+
+ // 触发点击事件回调
}
}
});
+
+ // 返回填充好的TextView作为标签视图
return tv;
}
- public SearchHistoryBean getItemData(int position){
+ // 获取指定位置的SearchHistoryBean对象
+ public SearchHistoryBean getItemData(int position) {
return mTagDatas.get(position);
+ // 从TagAdapter父类中获取数据集合并返回对应位置的数据
}
- public int getDataSize(){
+ // 获取数据集合的大小
+ public int getDataSize() {
return mTagDatas.size();
+ // 返回标签数据的数量
}
}
diff --git a/app/src/main/java/com/monke/monkeybook/view/impl/BookDetailActivity.java b/app/src/main/java/com/monke/monkeybook/view/impl/BookDetailActivity.java
index 74bde0c..9bd21aa 100644
--- a/app/src/main/java/com/monke/monkeybook/view/impl/BookDetailActivity.java
+++ b/app/src/main/java/com/monke/monkeybook/view/impl/BookDetailActivity.java
@@ -1,136 +1,219 @@
-//Copyright (c) 2017. 章钦豪. All rights reserved.
+// Copyright (c) 2017. 章钦豪. All rights reserved.
package com.monke.monkeybook.view.impl;
+// 声明包名,表示这是项目中的一个实现类
+// 导入相关类
import android.content.Intent;
+// 用于启动其他Activity
import android.os.Build;
+// 用于获取Android设备的版本信息
import android.text.method.ScrollingMovementMethod;
+// 用于使TextView支持滚动
import android.view.View;
+// 用于视图的点击事件监听
import android.view.animation.Animation;
+// 动画类
import android.view.animation.AnimationUtils;
+// 用于加载动画资源
import android.widget.FrameLayout;
+// 帧布局
import android.widget.ImageView;
+// 图片视图控件
import android.widget.TextView;
+// 文本视图控件
+
import com.bumptech.glide.Glide;
+// 图片加载库,用于加载图片
import com.bumptech.glide.load.engine.DiskCacheStrategy;
+// 设置缓存策略
import com.monke.monkeybook.BitIntentDataManager;
+// 用于管理Intent数据
import com.monke.monkeybook.R;
+// 引用项目中的资源文件
import com.monke.monkeybook.base.MBaseActivity;
+// 基类Activity
import com.monke.monkeybook.presenter.IBookDetailPresenter;
+// 书籍详情的Presenter接口
import com.monke.monkeybook.presenter.impl.BookDetailPresenterImpl;
+// 书籍详情的Presenter实现类
import com.monke.monkeybook.presenter.impl.ReadBookPresenterImpl;
+// 阅读书籍的Presenter实现类
import com.monke.monkeybook.utils.BlurTransformation;
+// 图片模糊效果工具
import com.monke.monkeybook.view.IBookDetailView;
+// 书籍详情视图接口
+// 书籍详情页面 Activity 类
public class BookDetailActivity extends MBaseActivity implements IBookDetailView {
+
+ // 定义页面上的控件
private FrameLayout iflContent;
+ // 内容区域,可能用于包裹其他控件
private ImageView ivBlurCover;
+ // 用于显示模糊效果的封面
private ImageView ivCover;
+ // 用于显示书籍封面
private TextView tvName;
+ // 显示书籍名称
private TextView tvAuthor;
+ // 显示书籍作者
private TextView tvOrigin;
+ // 显示书籍来源
private TextView tvChapter;
+ // 显示当前章节
private TextView tvIntro;
+ // 显示书籍简介
private TextView tvShelf;
+ // 操作书架(放入/移出)
private TextView tvRead;
+ // 操作阅读(开始阅读/继续阅读)
private TextView tvLoading;
+ // 显示加载提示
- private Animation animHideLoading;
- private Animation animShowInfo;
+ // 动画相关
+ private Animation animHideLoading; // 隐藏加载动画
+ private Animation animShowInfo; // 显示书籍信息动画
@Override
protected IBookDetailPresenter initInjector() {
+ // 初始化Presenter,负责处理业务逻辑
return new BookDetailPresenterImpl(getIntent());
}
@Override
protected void onCreateActivity() {
+ // 设置当前Activity的布局文件
setContentView(R.layout.activity_detail);
}
@Override
protected void initData() {
- animShowInfo = AnimationUtils.loadAnimation(this, android.R.anim.fade_in);
- animHideLoading = AnimationUtils.loadAnimation(this, android.R.anim.fade_out);
- animHideLoading.setAnimationListener(new Animation.AnimationListener() {
+ // 初始化动画
+ animShowInfo = AnimationUtils.loadAnimation(this, android.R.anim.fade_in); // 加载淡入动画
+ animHideLoading = AnimationUtils.loadAnimation(this, android.R.anim.fade_out); // 加载淡出动画
+ animHideLoading.setAnimationListener(new Animation.AnimationListener() { // 动画结束后执行的回调
@Override
public void onAnimationStart(Animation animation) {
-
+ // 动画开始时的处理(此处未做任何操作)
}
@Override
public void onAnimationEnd(Animation animation) {
+ // 动画结束时,隐藏加载提示
tvLoading.setVisibility(View.GONE);
}
@Override
public void onAnimationRepeat(Animation animation) {
-
+ // 动画重复时的处理(此处未做任何操作)
}
});
}
-
@Override
protected void bindView() {
+ // 绑定视图组件
iflContent = (FrameLayout) findViewById(R.id.ifl_content);
+
+ // 获取内容区域
ivBlurCover = (ImageView) findViewById(R.id.iv_blur_cover);
+
+ // 获取模糊封面
ivCover = (ImageView) findViewById(R.id.iv_cover);
+
+ // 获取书籍封面
tvName = (TextView) findViewById(R.id.tv_name);
+
+ // 获取书籍名称
tvAuthor = (TextView) findViewById(R.id.tv_author);
+
+ // 获取书籍作者
tvOrigin = (TextView) findViewById(R.id.tv_origin);
+
+ // 获取书籍来源
tvChapter = (TextView) findViewById(R.id.tv_chapter);
+
+ // 获取当前章节
tvIntro = (TextView) findViewById(R.id.tv_intro);
+
+ // 获取书籍简介
tvShelf = (TextView) findViewById(R.id.tv_shelf);
+
+ // 获取书架操作按钮
tvRead = (TextView) findViewById(R.id.tv_read);
+
+ // 获取阅读操作按钮
tvLoading = (TextView) findViewById(R.id.tv_loading);
+ // 获取加载提示
tvIntro.setMovementMethod(ScrollingMovementMethod.getInstance());
+ // 使简介支持滚动
initView();
-
+ // 初始化界面
updateView();
+ // 更新视图
}
@Override
public void updateView() {
+ // 根据Presenter获取的数据更新视图
if (null != mPresenter.getBookShelf()) {
+ // 如果书架信息存在
if (mPresenter.getInBookShelf()) {
+ // 如果书籍在书架中
+ // 显示当前章节
if (mPresenter.getBookShelf().getBookInfoBean().getChapterlist().size() > 0)
tvChapter.setText(String.format(getString(R.string.tv_read_durprogress), mPresenter.getBookShelf().getBookInfoBean().getChapterlist().get(mPresenter.getBookShelf().getDurChapter()).getDurChapterName()));
else
tvChapter.setText("无章节");
+
+ // 设置书架操作按钮为移出
tvShelf.setText("移出书架");
tvRead.setText("继续阅读");
+
tvShelf.setOnClickListener(new View.OnClickListener() {
+ // 移出书架点击事件
@Override
public void onClick(View v) {
- //从书架移出
mPresenter.removeFromBookShelf();
+ // 从书架移除
}
});
} else {
+ // 如果书籍不在书架中
+ // 显示最新章节
if (mPresenter.getBookShelf().getBookInfoBean().getChapterlist().size() == 0) {
tvChapter.setText("无章节");
} else {
tvChapter.setText(String.format(getString(R.string.tv_searchbook_lastest), mPresenter.getBookShelf().getBookInfoBean().getChapterlist().get(mPresenter.getBookShelf().getBookInfoBean().getChapterlist().size() - 1).getDurChapterName()));
}
+
+ // 设置书架操作按钮为放入
tvShelf.setText("放入书架");
tvRead.setText("开始阅读");
- tvShelf.setOnClickListener(new View.OnClickListener() {
+ tvShelf.setOnClickListener(new View.OnClickListener() { // 放入书架点击事件
@Override
public void onClick(View v) {
- //放入书架
- mPresenter.addToBookShelf();
+ mPresenter.addToBookShelf(); // 放入书架
}
});
}
+
+ // 如果简介为空,则设置为书籍的介绍
if (tvIntro.getText().toString().trim().length() == 0) {
tvIntro.setText(mPresenter.getBookShelf().getBookInfoBean().getIntroduce());
}
+
+ // 显示简介并执行动画
if (tvIntro.getVisibility() != View.VISIBLE) {
tvIntro.setVisibility(View.VISIBLE);
tvIntro.startAnimation(animShowInfo);
+ // 显示动画
tvLoading.startAnimation(animHideLoading);
+ // 隐藏加载动画
}
+
+ // 显示书籍来源
if (mPresenter.getBookShelf().getBookInfoBean().getOrigin() != null && mPresenter.getBookShelf().getBookInfoBean().getOrigin().length() > 0) {
tvOrigin.setVisibility(View.VISIBLE);
tvOrigin.setText("来源:" + mPresenter.getBookShelf().getBookInfoBean().getOrigin());
@@ -138,29 +221,38 @@ public class BookDetailActivity extends MBaseActivity impl
tvOrigin.setVisibility(View.GONE);
}
} else {
- tvChapter.setText(String.format(getString(R.string.tv_searchbook_lastest), mPresenter.getSearchBook().getLastChapter()));
+ // 如果书架信息为空
+ tvChapter.setText(String.format(getString(R.string.tv_searchbook_lastest), mPresenter.getSearchBook().getLastChapter())); // 显示搜索书籍的最新章节
tvShelf.setText("放入书架");
tvRead.setText("开始阅读");
tvRead.setOnClickListener(new View.OnClickListener() {
+ // 阅读按钮点击事件
@Override
public void onClick(View v) {
- //放入书架
+ // 放入书架操作(此处未实现)
}
});
tvIntro.setVisibility(View.INVISIBLE);
+ // 隐藏简介
tvLoading.setVisibility(View.VISIBLE);
+ // 显示加载提示
tvLoading.setText("加载中...");
+ // 设置加载提示文字
}
+
+ // 防止点击加载提示时触发操作
tvLoading.setOnClickListener(null);
}
@Override
public void getBookShelfError() {
+ // 获取书架信息失败,显示错误信息并设置点击重试
tvLoading.setVisibility(View.VISIBLE);
tvLoading.setText("加载失败,点击重试");
tvLoading.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
+ // 点击重试时重新获取书架信息
tvLoading.setText("加载中...");
tvLoading.setOnClickListener(null);
mPresenter.getBookShelfInfo();
@@ -170,31 +262,40 @@ public class BookDetailActivity extends MBaseActivity impl
@Override
protected void firstRequest() {
+ // 初次请求时调用
super.firstRequest();
+ // 如果是从搜索页面打开,并且书架信息为空,则发起网络请求获取书架信息
if (mPresenter.getOpenfrom() == BookDetailPresenterImpl.FROM_SEARCH && mPresenter.getBookShelf() == null) {
- //网络请求
mPresenter.getBookShelfInfo();
}
}
+ // 初始化页面控件显示
private void initView() {
String coverUrl;
+ // 封面URL
String name;
+ // 书籍名称
String author;
+ // 书籍作者
+
if (mPresenter.getOpenfrom() == BookDetailPresenterImpl.FROM_BOOKSHELF) {
+ // 从书架打开
coverUrl = mPresenter.getBookShelf().getBookInfoBean().getCoverUrl();
name = mPresenter.getBookShelf().getBookInfoBean().getName();
author = mPresenter.getBookShelf().getBookInfoBean().getAuthor();
+ // 显示书籍来源
if (mPresenter.getBookShelf().getBookInfoBean().getOrigin() != null && mPresenter.getBookShelf().getBookInfoBean().getOrigin().length() > 0) {
tvOrigin.setVisibility(View.VISIBLE);
tvOrigin.setText("来源:" + mPresenter.getBookShelf().getBookInfoBean().getOrigin());
} else {
tvOrigin.setVisibility(View.GONE);
}
- } else {
+ } else { // 从搜索页面打开
coverUrl = mPresenter.getSearchBook().getCoverUrl();
name = mPresenter.getSearchBook().getName();
author = mPresenter.getSearchBook().getAuthor();
+ // 显示书籍来源
if (mPresenter.getSearchBook().getOrigin() != null && mPresenter.getSearchBook().getOrigin().length() > 0) {
tvOrigin.setVisibility(View.VISIBLE);
tvOrigin.setText("来源:" + mPresenter.getSearchBook().getOrigin());
@@ -203,39 +304,47 @@ public class BookDetailActivity extends MBaseActivity impl
}
}
+ // 使用Glide加载封面图像,并显示模糊效果封面
Glide.with(this).load(coverUrl).dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESULT).centerCrop().placeholder(R.drawable.img_cover_default).into(ivCover);
Glide.with(this).load(coverUrl).dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESULT).centerCrop().bitmapTransform(new BlurTransformation(this, 6)).into(ivBlurCover);
+
+ // 设置书籍名称和作者
tvName.setText(name);
tvAuthor.setText(author);
}
@Override
protected void bindEvent() {
+ // 设置页面点击事件
iflContent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
+ // 根据Android版本处理不同的退出动画
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- if(getStart_share_ele()){
+ if(getStart_share_ele()) {
finishAfterTransition();
- }else{
+ } else {
finish();
- overridePendingTransition(0,android.R.anim.fade_out);
+ overridePendingTransition(0, android.R.anim.fade_out);
}
} else {
finish();
- overridePendingTransition(0,android.R.anim.fade_out);
+ overridePendingTransition(0, android.R.anim.fade_out);
}
}
});
+ // 设置阅读按钮点击事件
tvRead.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- //进入阅读
+ // 跳转到阅读界面
Intent intent = new Intent(BookDetailActivity.this, ReadBookActivity.class);
intent.putExtra("from", ReadBookPresenterImpl.OPEN_FROM_APP);
String key = String.valueOf(System.currentTimeMillis());
intent.putExtra("data_key", key);
+
+ // 使用BitIntentDataManager保存书籍数据并传递
try {
BitIntentDataManager.getInstance().putData(key, mPresenter.getBookShelf().clone());
} catch (CloneNotSupportedException e) {
@@ -244,16 +353,17 @@ public class BookDetailActivity extends MBaseActivity impl
}
startActivityByAnim(intent, android.R.anim.fade_in, android.R.anim.fade_out);
+ // 结束当前Activity并设置退出动画
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- if(getStart_share_ele()){
+ if(getStart_share_ele()) {
finishAfterTransition();
- }else{
+ } else {
finish();
- overridePendingTransition(0,android.R.anim.fade_out);
+ overridePendingTransition(0, android.R.anim.fade_out);
}
} else {
finish();
- overridePendingTransition(0,android.R.anim.fade_out);
+ overridePendingTransition(0, android.R.anim.fade_out);
}
}
});
diff --git a/build.gradle b/build.gradle
index 43153d6..888750f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,13 +1,23 @@
buildscript {
repositories {
- jcenter()
- mavenCentral()
- maven {
- url 'https://maven.google.com/'
- name 'Google'
- }
- google()
+// jcenter()
+// mavenCentral()
+// maven {
+// url 'https://maven.google.com/'
+// name 'Google'
+// }
+// google()
+// maven { url 'https://plugins.gradle.org/m2/' }
+// maven { url 'https://maven.aliyun.com/nexus/content/repositories/google' }
+// maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
+// maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter'}
+
+ maven { url 'https://maven.aliyun.com/repository/public' }
+ maven { url 'https://maven.aliyun.com/repository/central' }
+ maven { url 'https://maven.aliyun.com/repository/jcenter' }
+ maven { url 'https://maven.aliyun.com/repository/google' }
+ maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
@@ -17,11 +27,21 @@ buildscript {
allprojects {
repositories {
- jcenter()
- maven {
- url 'https://maven.google.com/'
- name 'Google'
- }
+// jcenter()
+// maven {
+// url 'https://maven.google.com/'
+// name 'Google'
+// }
+// maven { url 'https://plugins.gradle.org/m2/' }
+// maven { url 'https://maven.aliyun.com/nexus/content/repositories/google' }
+// maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
+// maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter'}
+
+ maven { url 'https://maven.aliyun.com/repository/public' }
+ maven { url 'https://maven.aliyun.com/repository/central' }
+ maven { url 'https://maven.aliyun.com/repository/jcenter' }
+ maven { url 'https://maven.aliyun.com/repository/google' }
+ maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
}
}
diff --git a/gradle.properties b/gradle.properties
index 1fd9202..f440d15 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -17,4 +17,17 @@
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
-APP_NAME = MONKOVEL
\ No newline at end of file
+APP_NAME = MONKOVEL
+
+org.gradle.daemon=true
+org.gradle.parallel=true
+# ????? Maven ??
+repositories.grails.default = https://maven.aliyun.com/repository/public
+repositories.grails.default.1 = https://mirrors.tuna.tsinghua.edu.cn/maven/repos/public
+repositories.grails.default.2 = https://repo.maven.apache.org/maven2
+#
+## ???????
+#systemProp.http.proxyHost=127.0.0.1
+#systemProp.http.proxyPort=1080
+#systemProp.https.proxyHost=127.0.0.1
+#systemProp.https.proxyPort=1080
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index f6c35e4..9720b9b 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
+distributionUrl=https://mirrors.cloud.tencent.com/gradle/gradle-4.6-all.zip