Skip to content

Commit 645f5a5

Browse files
authored
Merge pull request #75 from rosuH/dev
0.6.3
2 parents b3db86c + 9fa4c3d commit 645f5a5

17 files changed

Lines changed: 214 additions & 97 deletions

File tree

filepicker/src/main/java/me/rosuh/filepicker/FilePickerActivity.kt

Lines changed: 55 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ import me.rosuh.filepicker.utils.FileUtils
3333
import me.rosuh.filepicker.utils.ScreenUtils
3434
import me.rosuh.filepicker.widget.PosLinearLayoutManager
3535
import java.io.File
36+
import java.util.concurrent.BlockingQueue
37+
import java.util.concurrent.LinkedBlockingQueue
38+
import java.util.concurrent.ThreadPoolExecutor
39+
import java.util.concurrent.TimeUnit
3640

3741
@SuppressLint("ShowToast")
3842
class FilePickerActivity : AppCompatActivity(), View.OnClickListener,
@@ -41,7 +45,28 @@ class FilePickerActivity : AppCompatActivity(), View.OnClickListener,
4145

4246
private var mainHandler = Handler(Looper.getMainLooper())
4347

44-
private var loadFileThread: Thread? = null
48+
private val loadingFileWorkerQueue: BlockingQueue<Runnable> = LinkedBlockingQueue()
49+
50+
// Creates a thread pool manager
51+
private var loadingThreadPool: ThreadPoolExecutor = ThreadPoolExecutor(
52+
1, // Initial pool size
53+
1, // Max pool size
54+
KEEP_ALIVE_TIME,
55+
TimeUnit.MINUTES,
56+
loadingFileWorkerQueue
57+
)
58+
get() {
59+
if (field.isShutdown) {
60+
field = ThreadPoolExecutor(
61+
1,
62+
1,
63+
KEEP_ALIVE_TIME,
64+
TimeUnit.MINUTES,
65+
loadingFileWorkerQueue
66+
)
67+
}
68+
return field
69+
}
4570

4671
private val loadFileRunnable: Runnable by lazy {
4772
Runnable {
@@ -96,19 +121,20 @@ class FilePickerActivity : AppCompatActivity(), View.OnClickListener,
96121
setTheme(pickerConfig.themeId)
97122
super.onCreate(savedInstanceState)
98123
setContentView(R.layout.main_activity_for_file_picker)
124+
initView()
99125
// 核验权限
100126
// checking permission
101127
if (isPermissionGrated()) {
102-
prepareLauncher()
128+
loadList()
103129
} else {
104130
requestPermission()
105131
}
106132
}
107133

108134
override fun onDestroy() {
109135
super.onDestroy()
110-
if (loadFileThread?.isAlive == true) {
111-
loadFileThread?.interrupt()
136+
if (!loadingThreadPool.isShutdown){
137+
loadingThreadPool.shutdown()
112138
}
113139
}
114140

@@ -141,26 +167,14 @@ class FilePickerActivity : AppCompatActivity(), View.OnClickListener,
141167
getString(string.file_picker_request_permission_failed),
142168
Toast.LENGTH_SHORT
143169
).show()
170+
setLoadingFinish()
144171
} else {
145-
prepareLauncher()
172+
loadList()
146173
}
147174
}
148175
}
149176
}
150177

151-
/**
152-
* 在做完权限申请之后开始的真正的工作
153-
*/
154-
private fun prepareLauncher() {
155-
if (Environment.getExternalStorageState() != MEDIA_MOUNTED) {
156-
throw Throwable(cause = IllegalStateException("External storage is not available ====>>> Environment.getExternalStorageState() != MEDIA_MOUNTED"))
157-
}
158-
initView()
159-
// 加载中布局
160-
initLoadingView()
161-
loadList()
162-
}
163-
164178
private fun initView() {
165179
btn_go_back_file_picker.setOnClickListener(this@FilePickerActivity)
166180

@@ -178,6 +192,7 @@ class FilePickerActivity : AppCompatActivity(), View.OnClickListener,
178192
btn_confirm_file_picker.apply {
179193
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
180194
// 小于 4.4 的样式兼容
195+
// compatible with 4.4 api
181196
layoutParams = RelativeLayout.LayoutParams(
182197
RelativeLayout.LayoutParams.WRAP_CONTENT,
183198
RelativeLayout.LayoutParams.WRAP_CONTENT
@@ -198,23 +213,10 @@ class FilePickerActivity : AppCompatActivity(), View.OnClickListener,
198213
} else {
199214
View.VISIBLE
200215
}
201-
}
202-
203-
private fun loadList() {
204-
if (loadFileThread?.isAlive == true) {
205-
loadFileThread?.interrupt()
206-
}
207-
loadFileThread = Thread(loadFileRunnable)
208-
loadFileThread?.start()
209-
}
210-
211-
private fun setLoadingFinish() {
212-
swipe_refresh_layout?.isRefreshing = false
213-
}
214216

215-
private fun initLoadingView() {
216217
swipe_refresh_layout?.apply {
217218
setOnRefreshListener {
219+
resetViewState()
218220
loadList()
219221
}
220222
isRefreshing = true
@@ -239,6 +241,17 @@ class FilePickerActivity : AppCompatActivity(), View.OnClickListener,
239241
}
240242
}
241243

244+
private fun loadList() {
245+
if (!isPermissionGrated()){
246+
requestPermission()
247+
return
248+
}
249+
if (Environment.getExternalStorageState() != MEDIA_MOUNTED) {
250+
throw Throwable(cause = IllegalStateException("External storage is not available ====>>> Environment.getExternalStorageState() != MEDIA_MOUNTED"))
251+
}
252+
loadingThreadPool.submit(loadFileRunnable)
253+
}
254+
242255
private fun initRv(
243256
listData: ArrayList<FileItemBeanImpl>?,
244257
navDataList: ArrayList<FileNavBeanImpl>
@@ -271,6 +284,10 @@ class FilePickerActivity : AppCompatActivity(), View.OnClickListener,
271284
}
272285
}
273286

287+
private fun setLoadingFinish() {
288+
swipe_refresh_layout?.isRefreshing = false
289+
}
290+
274291
/**
275292
* 获取两个列表的监听器
276293
*/
@@ -425,7 +442,7 @@ class FilePickerActivity : AppCompatActivity(), View.OnClickListener,
425442
*/
426443
private fun enterDirAndUpdateUI(fileBean: FileBean) {
427444
// 清除当前选中状态
428-
cleanStatus()
445+
resetViewState()
429446

430447
// 获取文件夹文件
431448
val nextFiles = File(fileBean.filePath)
@@ -474,7 +491,7 @@ class FilePickerActivity : AppCompatActivity(), View.OnClickListener,
474491
btn_selected_all_file_picker?.isEnabled = isEnable
475492
}
476493

477-
private fun cleanStatus() {
494+
private fun resetViewState() {
478495
selectedCount = 1
479496
updateItemUI(false)
480497
}
@@ -543,26 +560,17 @@ class FilePickerActivity : AppCompatActivity(), View.OnClickListener,
543560
finish()
544561
}
545562
R.id.btn_go_back_file_picker -> {
546-
finish()
563+
onBackPressed()
547564
}
548565
}
549566
}
550567

551-
private fun getAvailableCount(): Long {
552-
var count: Long = 0
553-
for (item in listAdapter!!.dataList!!) {
554-
val file = File(item.filePath)
555-
if (pickerConfig.isSkipDir && file.exists() && file.isDirectory) {
556-
continue
557-
}
558-
count++
559-
}
560-
return count
561-
}
562-
563568
private fun isCanSelect() = selectedCount < maxSelectable
564569

565570
companion object {
566571
private const val FILE_PICKER_PERMISSION_REQUEST_CODE = 10201
572+
573+
// Sets the amount of time an idle thread waits before terminating
574+
private const val KEEP_ALIVE_TIME = 10L
567575
}
568576
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package me.rosuh.filepicker.config
2+
3+
import me.rosuh.filepicker.bean.FileItemBeanImpl
4+
import me.rosuh.filepicker.filetype.FileType
5+
6+
/**
7+
*
8+
* @author rosu
9+
* @date 2020/06/25
10+
* 这个类用于注册你自己的文件类型检测方法。您需要遵循下列步骤:
11+
* 1. 实现您自己的文件类型[FileType],也就是其中的[FileType.verify]方法
12+
* 2. 构建此类的一个子类,并在[AbstractFileDetector.fillFileType] 中,检测文件类型,并赋值给[FileItemBeanImpl.fileType]属性
13+
* ===================================================================================================================
14+
* This class is used to register your own file type detection methods. You need to follow the following steps:
15+
* 1. implement your own file type [FileType], which is the [FileType.verify] method of the [FileType].
16+
* 2. Construct a subclass of this class and, in [AbstractFileDetector.fillFileType], detect the file type and assign it to [FileItemBeanImpl.fileType] property.
17+
*
18+
*/
19+
abstract class AbstractFileDetector {
20+
/**
21+
* 自定义文件类型识别方法,传入 @param itemBeanImpl 条目数据对象,
22+
* 由实现者来实现文件类型的甄别,返回填充了 fileType 的方法
23+
*/
24+
abstract fun fillFileType(itemBeanImpl: FileItemBeanImpl): FileItemBeanImpl
25+
}

filepicker/src/main/java/me/rosuh/filepicker/config/AbstractFileType.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ import me.rosuh.filepicker.bean.FileItemBeanImpl
77
* @author rosu
88
* @date 2018/11/27
99
*/
10+
@Deprecated(
11+
"Because the class name was confused.",
12+
ReplaceWith("AbstractFileDetector", "me.rosuh.filepicker.config")
13+
)
1014
abstract class AbstractFileType {
1115
/**
1216
* 自定义文件类型识别方法,传入 @param itemBeanImpl 条目数据对象,

filepicker/src/main/java/me/rosuh/filepicker/config/DefaultFileType.kt renamed to filepicker/src/main/java/me/rosuh/filepicker/config/DefaultFileDetector.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import me.rosuh.filepicker.filetype.*
88
* @author rosu
99
* @date 2018/11/27
1010
*/
11-
class DefaultFileType : AbstractFileType() {
11+
class DefaultFileDetector : AbstractFileDetector() {
1212

1313
private val allDefaultFileType: ArrayList<FileType> by lazy {
1414
val fileTypes = ArrayList<FileType>()

filepicker/src/main/java/me/rosuh/filepicker/config/FilePickerConfig.kt

Lines changed: 55 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,69 +19,98 @@ class FilePickerConfig(private val pickerManager: FilePickerManager) {
1919
* 是否显示隐藏文件,默认隐藏
2020
* 以符号 . 开头的文件或文件夹视为隐藏
2121
*/
22-
internal var isShowHiddenFiles = false
22+
var isShowHiddenFiles = false
23+
private set
24+
2325
/**
2426
* 是否显示选中框,默认显示
2527
*/
26-
internal var isShowingCheckBox = true
28+
var isShowingCheckBox = true
29+
private set
30+
2731
/**
2832
* 在选中时是否忽略文件夹
2933
*/
30-
internal var isSkipDir = true
34+
var isSkipDir = true
35+
private set
36+
3137
/**
3238
* 是否是单选
3339
* 如果是单选,则隐藏顶部【全选/取消全选按钮】
3440
*/
35-
internal var singleChoice = false
41+
var singleChoice = false
42+
private set
43+
3644
/**
3745
* 最大可被选中数量
3846
*/
39-
internal var maxSelectable = Int.MAX_VALUE
47+
var maxSelectable = Int.MAX_VALUE
48+
private set
49+
4050
/**
4151
* 存储类型
4252
*/
43-
internal var mediaStorageName = contextRes.getString(R.string.file_picker_tv_sd_card)
53+
var mediaStorageName = contextRes.getString(R.string.file_picker_tv_sd_card)
54+
private set
4455

4556
/**
4657
* 自定义存储类型,根据此返回根目录
4758
*/
4859
@get:StorageMediaType
4960
@set:StorageMediaType
50-
internal var mediaStorageType: String = STORAGE_EXTERNAL_STORAGE
61+
var mediaStorageType: String = STORAGE_EXTERNAL_STORAGE
62+
private set
63+
5164
/**
5265
* 自定义根目录路径,需要先设置 [mediaStorageType] 为 [STORAGE_CUSTOM_ROOT_PATH]
5366
*/
54-
internal var customRootPath: String = ""
67+
var customRootPath: String = ""
68+
private set
69+
5570
/**
5671
* 自定义过滤器
5772
*/
58-
internal var selfFilter: AbstractFileFilter? = null
73+
var selfFilter: AbstractFileFilter? = null
74+
private set
75+
5976
/**
6077
* 自定文件类型甄别器和默认类型甄别器
6178
*/
62-
internal var selfFileType: AbstractFileType? = null
63-
internal val defaultFileType: DefaultFileType by lazy { DefaultFileType() }
79+
var customDetector: AbstractFileDetector? = null
80+
private set
81+
val defaultFileDetector: DefaultFileDetector by lazy { DefaultFileDetector() }
82+
6483
/**
6584
* 点击操作接口,采用默认实现
6685
*/
67-
internal var fileItemOnClickListener: FileItemOnClickListener? = null
86+
var fileItemOnClickListener: FileItemOnClickListener? = null
87+
private set
88+
6889
/**
6990
* 主题
7091
*/
71-
internal var themeId: Int = R.style.FilePickerThemeRail
92+
var themeId: Int = R.style.FilePickerThemeRail
93+
private set
94+
7295
/**
7396
* 全选文字,取消全选文字,返回文字,已选择文字,确认按钮,选择限制提示语,空列表提示
7497
*/
75-
internal var selectAllText: String = contextRes.getString(R.string.file_picker_tv_select_all)
98+
var selectAllText: String = contextRes.getString(R.string.file_picker_tv_select_all)
99+
private set
100+
var deSelectAllText: String = contextRes.getString(R.string.file_picker_tv_deselect_all)
101+
private set
76102

77-
internal var deSelectAllText: String =
78-
contextRes.getString(R.string.file_picker_tv_deselect_all)
79103
@StringRes
80-
internal var hadSelectedText: Int = R.string.file_picker_selected_count
81-
internal var confirmText: String = contextRes.getString(R.string.file_picker_tv_select_done)
104+
var hadSelectedText: Int = R.string.file_picker_selected_count
105+
private set
106+
var confirmText: String = contextRes.getString(R.string.file_picker_tv_select_done)
107+
private set
108+
82109
@StringRes
83-
internal var maxSelectCountTips: Int = R.string.max_select_count_tips
84-
internal var emptyListTips: String = contextRes.getString(R.string.empty_list_tips_file_picker)
110+
var maxSelectCountTips: Int = R.string.max_select_count_tips
111+
private set
112+
var emptyListTips: String = contextRes.getString(R.string.empty_list_tips_file_picker)
113+
private set
85114

86115
fun showHiddenFiles(isShow: Boolean): FilePickerConfig {
87116
isShowHiddenFiles = isShow
@@ -120,8 +149,12 @@ class FilePickerConfig(private val pickerManager: FilePickerManager) {
120149
return this
121150
}
122151

123-
fun fileType(fileType: AbstractFileType): FilePickerConfig {
124-
selfFileType = fileType
152+
/**
153+
* 实现 [AbstractFileDetector] 以自定义您自己的文件类型检测器
154+
* Custom your file detector by implementing [AbstractFileDetector]
155+
*/
156+
fun customDetector(detector: AbstractFileDetector): FilePickerConfig {
157+
customDetector = detector
125158
return this
126159
}
127160

filepicker/src/main/java/me/rosuh/filepicker/utils/FileUtils.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ class FileUtils {
7777
beanSubscriber
7878
)
7979
// 如果调用者没有实现文件类型甄别器,则使用的默认甄别器
80-
FilePickerManager.config.selfFileType?.fillFileType(itemBean)
81-
?: FilePickerManager.config.defaultFileType.fillFileType(itemBean)
80+
FilePickerManager.config.customDetector?.fillFileType(itemBean)
81+
?: FilePickerManager.config.defaultFileDetector.fillFileType(itemBean)
8282
listData.add(itemBean)
8383
}
8484
listData.run {

0 commit comments

Comments
 (0)