Edited at

Android端末内の「画像ファイルを含むフォルダ」を表示する際にキャッシュを利用して高速化する


背景

画像ギャラリーアプリなどのフォルダ一覧表示機能は端末内の「画像ファイルを含むフォルダ」を検知し表示している

自身で作成してみたが (ここ)、しかしフォルダ探査に時間がかかりアプリ起動からファイル一覧表示まで時間がかかる

そこで「画像ファイルを含むフォルダ」のリストをキャッシュし表示を高速化する


やったこと・フロー図

前回は、アプリ起動→端末内の画像を含むフォルダ探査→リストビュー表示としていた

しかし、これだとフォルダ探査に時間がかかりフォルダリストを画面にスムーズに表示できないので以下のフロー図のようにキャッシュを作成することでアプリ起動2回目以降での表示を高速化

cache.PNG


コード

キャッシュありの場合は「キャッシュ読み込み→リストビュー表示」と「キャッシュの更新」を行う、キャッシュ更新時のフォルダ探索に時間がかかるため更新はルーチンで非同期処理する

キャッシュなしの場合は「フォルダ探索→キャッシュ書き込み→キャッシュ読み込み→リストビューに表示」を行う


MainActivity.kt


/*キャッシュ用の配列*/
val dirurllist: ArrayList<String> = ArrayList<String>()
var memolist:ArrayList<String>

/*キャッシュファイル読み込み*/
memolist=cacheread(dirurllist)

/*キャッシュありの時*/
if(!memolist.isEmpty()) {
println("キャッシュファイルあり")
displey(memolist) //リストビューに出力/

GlobalScope.launch { /非同期処理/
if (cacheupdate(memolist)) {/キャッシュ更新処理/
} else { println("キャッシュ更新なし") }
}
println("終了")
}
/*キャッシュなしの時*/
else{
println("キャッシュファイルなし")
cachewrite() //キャッシュ書き込み処理/
memolist=cacheread(dirurllist)//キャッシュ再読み込み/
displey(memolist) //リストビューに出力/
}



キャッシュファイル作成:cachewrite()

File()の第一引数にcacheDirを指定するとアプリ内のキャッシュディレクトリ

を指定できる、第二引数にはキャッシュ記録用のファイル名(なんでもいい)を指定

imgserch.imgfileserch()とimgserch.dirurllist()は前回作成(ここ)したクラスのメソッド

・imgfileserch()は画像ファイルを含むフォルダ名とフォルダ内最新ファイル名を探索するメソッド

・dirurllist()はimgfileserch()で探索したフォルダ名とフォルダ内最新ファイル名のリストを返すメソッド


MainActivity.kt

 /*キャッシュファイル書き込みメソッド*/

fun cachewrite() {

/*内部ストレージのパス取得*/
val path = Environment.getExternalStorageDirectory().getPath()
val dir = File(path)

/*内部ストレージのパスを渡して画像ディレクトリ検知*/
val imgserch = ImgFilecon()
imgserch.imgfileserch(dir.toString())

try{
val filew=File(cacheDir,"dirurlcache00.txt")//*キャッシュファイル*//
filew.createNewFile()
if(filew.exists()){
val src =filew.absoluteFile
/*画像含むディレクトリリストをキャッシュファイルに書き込み*/
imgserch.dirurllist().forEach { src.appendText(it.imgurl+"\n") }
println("書き込み完了")
}
}catch (e:IOException){println("キャッシュファイル書き込みエラー")}
}



キャッシュファイル読み込み:cacheread()

cacheread()は空のリストを引数として受け取りキャッシュがあればキャッシュリストを返す、キャッシュなしなら空のリストのまま返す


MainActivity.kt

    /*キャッシュファイル読み込みメソッド*/

fun cacheread(readlist: ArrayList<String>): ArrayList<String> {

/*キャッシュファイル読み込み*/
try {
val file = File(cacheDir, "dirurlcache00.txt")
if (file.exists()) {
/*ファイルから一行ずつ読み込んで空白でなくNuLLでない文字列をlistに*/
val lines=file.absoluteFile.readLines().filter(String::isNotBlank).toList()
lines.forEach{readlist.add(it)}
println("読み込み完了")
}
return readlist
} catch (e: IOException) {
println("キャッシュファイル読み込み失敗")
return readlist
}
}



キャッシュファイル更新:cacheupdate()

キャッシュを読み込むだけでは端末内のフォルダが更新された時に整合性が取れないのでキャッシュの更新処理を行う

cacheupdate()はキャッシュリストを引数として受け取り、現在のフォルダリストとキャッシュリストが違う時にキャッシュファイルを更新してtrueを返す


MainActivity.kt


/*キャッシュファイルの更新判定と更新を行うメソッド*/
fun cacheupdate(cachelist:ArrayList<String>):Boolean{

/*内部ストレージのパス取得*/
val path = Environment.getExternalStorageDirectory().getPath()
val dir = File(path)

/*内部ストレージのパスを渡して画像を含むディレクトリ検知*/
val imgserch = ImgFilecon()
imgserch.imgfileserch(dir.toString())

/*端末内の現在のフォルダ用リスト*/
var updatelist:ArrayList<String> =ArrayList<String>()

/*現在のフォルダ一覧をリストにadd*/
imgserch.dirurllist().forEach { updatelist.add(it.imgurl) }

/*現在のフォルダ一覧とキャッシュリストを比較*/
if(cachelist.containsAll(updatelist) && updatelist.containsAll(cachelist)){return false}
else{/*一致しない時キャッシュ更新*/
try {
val filew = File(cacheDir, "dirurlcache00.txt")
filew.delete() //*旧キャッシュファイルを消す*//

val newfilew=File(cacheDir, "dirurlcache00.txt")
newfilew.createNewFile() //*新しいキャッシュファイル作成*//

/*新しいキャッシュファイルに書き込み*/
if(newfilew.exists()){
val src =newfilew.absoluteFile
updatelist.forEach { src.appendText(it+"\n")}
println("書き込み完了")
return true
}
}
catch (e:IOException){println("キャッシュ更新エラー")}
}
return false
}



デモ

画像を含むフォルダ一覧を検知してフォルダ内の最新の画像ファイルのURLを表示、詳細を以下の画像に示す

アプリスクショ


結果

キャッシュを用いることでキャッシュなしの場合と比較して表示速度が3倍程度早くなった


終わりに

コード

GitHub


参考文献

kotlin公式リファレンス

Kotlinのコーディングが捗る標準ライブラリ

kotlinでandroid入門 内部ストレージ