キャッシュフォルダに元画像ファイルのディレクトリ階層を構築して、サムネイル画像を保存する。
recyclerView のアダプタの imageView セットでファイル読み出しかサムネイル作成か。その部分。
File file = new File( fName ); // フルパス画像ファイル名
if ( !file.exists() || !file.isFile() ) return null; // 存在を確認
File cDir = mContext.getCacheDir(); // getCacheDir() が使えないときは、Contextを引っ張る
String text = cDir.getAbsolutePath() + file.getAbsolutePath(); // スレッドで構築されているはずのフルパス
File cf = new File( text );
Bitmap scaleBitmap = null;
if ( cf.exists() ) { // キャッシュにサムネイルが存在するか確認
scaleBitmap = BitmapFactory.decodeFile(cf.getAbsolutePath());
} else {
// サムネイル作成プログラム
}
File cf = new File( text );が上手く機能しない場合は、 new File( dir, child ); で試す。
理由は分からないが、File情報が取得できない事があった。画像ファイルはそこにあるのに。
スレッド実行のタイミングは試行を繰り返して良い場所を探す?
ディレクトリ内のファイルリスト作成場所に組み込んでみた。
MyThumbnailRunnable mtr = new MyThumbnailRunnable( mMainData, dir );
Thread thread = new Thread( mtr );
thread.start();
【MyThumbnailRunnable クラス】
public class MyThumbnailRunnable implements Runnable {
private MyMainData mMainData;
private File mTargetDir = null;
private ArrayList< String> mFileNameList = new ArrayList< >();
public MyThumbnailRunnable( MyMainData mainData, File dir ) {
mMainData = mainData; // Context 他を受け渡す
mTargetDir = dir; // 対象ディレクトリ
}
@Override
public void run() {
if ( mMainData.getMakingThumbnailesDirPath().equals( mTargetDir.getAbsolutePath() ) )
return;
mMainData.setMakingThumbnailesDirPath( mTargetDir.getAbsolutePath() ); // フラグ
fileNameList( mTargetDir );
createThumbnail();
mMainData.setMakingThumbnailesDirPath( "" ); // フラグ初期化
finish(); // run() が終了で消滅するらしいが、念のため明確に参照は切っておく
}
/////
MyMainData クラスは、Context とフラグを受け渡すため。スレッド終了時には参照を切る。
引数の dir は、対象ディレクトリ。この中の画像ファイルをサムネイルにしてキャッシュに保存する。
処理が長時間になる場合は、アクティビティー上の参照はしない事。最悪、値をコピーして参照は切る。
スレッドは注意が必要らしい。
/////
【画像ファイル名をリストアップ】
private void fileNameList( File f ) {
String fName;
String[] mList = f.list();
if ( mList != null ) {
mFileNameList.clear();
for (String s : mList) {
fName = s.toLowerCase(); //小文字に変換;
if (fName.endsWith(".jpg") || fName.endsWith(".png")) { //画像ファイル選択
mFileNameList.add(s);
}
}
}
}
public void createThumbnail() {
if ( mFileNameList == null || mFileNameList.size() == 0 ) return;
List< String> dirList = disassemblyPath( mTargetDir );
File mCacheDir = assemblyCachePath( dirList );
if ( mCacheDir == null ) return;
makeCacheDirectory( dirList );
for ( int i = mFileNameList.size()-1; i >= 0 ; i-- ) {
bitmapToThumbnaile( new File( mCacheDir, mFileNameList.get(i) ) );
}
}
【サムネイル画像を保存】
private void bitmapToThumbnaile( File cfile ) {
Bitmap bitmap;
if ( !cfile.exists() ) {
bitmap = thumbnaileImage( cfile.getName() );
if ( bitmap != null ) {
try {
FileOutputStream fos = new FileOutputStream( cfile );
Bitmap.CompressFormat bcf = getCompressFormat( cfile.getName() );
if ( bcf != null ) bitmap.compress( bcf, 100, fos );
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
if ( !bitmap.isRecycled() ) bitmap.recycle();
}
bitmap = null;
}
}
【拡張子から形式を割り出す】
public Bitmap.CompressFormat getCompressFormat(String name ) {
String t = name.toLowerCase();
if ( t.endsWith( ".jpg" ) ) return Bitmap.CompressFormat.JPEG;
if ( t.endsWith( ".png" ) ) return Bitmap.CompressFormat.PNG;
return null;
}
【キャッシュフォルダにディレクトリ階層を構築】
public void makeCacheDirectory( List< String> list ) {
int len;
if ( list == null || ( len = list.size() ) == 0 ) return;
File cacheDir = mMainData.getContext().getCacheDir();
for ( int i = list.size()-1; i >= 0; i-- ) {
cacheDir = new File( cacheDir, list.get(i) );
if ( !cacheDir.exists() ) {
boolean b = cacheDir.mkdir();
}
}
}
【フルパスを分解、文字配列作成】
public List< String> disassemblyPath(File f ) {
List list = new ArrayList< String>();
File path = f;
do {
list.add(path.getName());
path = path.getParentFile();
} while ( path != null && !path.getName().equals(""));
return list;
}
【文字配列をキャッシュフォルダ上に組み立て階層を作る】
public File assemblyCachePath(List< String> list ) {
int len;
if ( list == null || ( len = list.size() ) == 0 ) return null;
File cacheDir = mMainData.getContext().getCacheDir();
String t;
for ( len-=1; len >= 0; len-- ) {
t = list.get(len);
cacheDir = new File( cacheDir, t );
}
return cacheDir;
}
残りのメソッドは次へ続く。