一枚のサムネイル画像を作成して、キャッシュディレクトリに保存する。
public class MyAsyncTask extends AsyncTask< String,Object,Object > {
private MyMainData mMainData;
private RecyclerView mRecyclerView;
private File mCacheDir;
private final int vID;
private final static int SAVE_SIZE = 160;
public MyAsyncTask( MyMainData data, RecyclerView rv, int id ) {
super();
mMainData = data;
mRecyclerView = rv ;
vID = id;
mCacheDir = data.getCacheDir(true); // キャッシュディレクトリ取得
}
// メインスレッドで実行
@Override
protected void onPreExecute() {
// 必要な(前)処理
}
// 別のスレッドで実行
@Override
protected Object doInBackground(String... p) { // MyTask.execute(引数);で呼ばれる
File souFile = new File(p[0]);
if ( !souFile.exists() || !souFile.isFile() ) return false;
if ( !mCacheDir.exists() && !mCacheDir.mkdirs() ) return false;
File cacheFile = new File( mCacheDir, souFile.getName() );
if ( cacheFile.exists() ) return false; // キャッシュファイルが無いからここに来ているけど..
return bitmapToThumbnaile(souFile, cacheFile);
}
private boolean bitmapToThumbnaile( File souFile, File destfile ) {
Bitmap bitmap = thumbnaileImage( souFile );
if ( bitmap != null ) {
try {
FileOutputStream fos = new FileOutputStream( destfile );
Bitmap.CompressFormat bcf = getCompressFormat( souFile.getName() );
if ( bcf != null ) bitmap.compress( bcf, 85, fos );
fos.close();
} catch (IOException e) {
return false;
}
if ( !bitmap.isRecycled() ) bitmap.recycle();
}
return true;
}
private Bitmap thumbnaileImage( File souFile ) {
Bitmap scaleBitmap = null;
try {
BitmapFactory.Options op = new BitmapFactory.Options();
op.inJustDecodeBounds = true;
InputStream istream = new FileInputStream( souFile );
BitmapFactory.decodeStream( istream, null, op );
op.inSampleSize = calculateInSampleSize( op );
op.inJustDecodeBounds = false;
istream.close();
istream = new FileInputStream( souFile );
scaleBitmap = BitmapFactory.decodeStream( istream, null, op );
istream.close();
if ( scaleBitmap == null ) return null;
Matrix matrix = new Matrix();
float mag = calcMag( scaleBitmap.getWidth(), scaleBitmap.getHeight() );
matrix.postScale( mag, mag );
scaleBitmap = Bitmap.createBitmap( scaleBitmap, 0, 0, scaleBitmap.getWidth(), scaleBitmap.getHeight(), matrix, true);
} catch (OutOfMemoryError | IOException ignored) {
return null;
}
return scaleBitmap;
}
private int calculateInSampleSize(BitmapFactory.Options op) {
int height = op.outHeight;
int width = op.outWidth;
int inSamplSize = 1;
int border = SAVE_SIZE;
if ( height > border || width > border) {
int halfHeight = height / 2;
int halfWidth = width / 2;
while ( ( halfHeight / inSamplSize ) >= border &&
( halfWidth / inSamplSize ) >= border
) {
inSamplSize *= 2;
}
}
return inSamplSize;
}
private 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;
}
private float calcMag( int souX, int souY ) {
float magW = (float)SAVE_SIZE / (float)souX;
float magH = (float)SAVE_SIZE / (float)souY;
return Math.min(magW, magH);
}
// 途中経過、メインスレッドで実行
@Override
protected void onProgressUpdate(Object... o) {
// 経過表示
}
// 終了後、メインスレッドで実行
@Override
protected void onPostExecute( Object result ) {
if ( (boolean)result ) {
if (Objects.equals(mRecyclerView.getAdapter(), mMainData.getThumbnailPage().getRecyclerView().getAdapter()))
// アダプターが更新されていない時
Objects.requireNonNull(mRecyclerView.getAdapter()).notifyItemChanged(vID);
}
finish();
}
private void finish() { // 念のため参照切り
mCacheDir = null;
mRecyclerView = null;
mMainData = null;
}
}