前回の作業ディレクトリ、画像ファイルだけのRecyclerView 使用は、1つのディレクトリに数十枚の画像であれば、十分の処理速度でストレスは感じられない。
別スレッドでのサムネイル作成では、1枚完了ごとにRecyclerViewのサムネイル画像を更新するから作業が止まって見える事はない。
今回は、1つのディレクトリに子ディレクトリとファイルを混在したサムネイルを表示するRecyclerViewの構築。
ファイル部分は前回のを利用。ディレクトリとファイルのリストを別に用意して、先にディレクトリ、後にファイルのリストで合成。
本体リストと別に識別用リストの2本を用意。
ディレクトリのアイコンはリソースからの設定が一般的だと思う。しかし、ディレクトリの中に画像が有ったら、それを使いたい。
これが意外と面倒で時間がかかる。だいぶ前のキャッシュディレクトリにディレクトリの構造をそのまま構築するのは利用価値が大きく有用。ただ、ストレージの領域を浪費する。
作業ディレクトリで1つのディレクトリのキャッシュ情報を使い捨てするともったいない。使用頻度で再利用とかできたらいいんだけれど。
ディレクトリのアイコンだけも特別に保存する方法を考えないと時間短縮は望めなさそう。今後の課題。
とりあえず、ディレクトリ内の画像をアイコンに使用する草案。
RecyclerViewのアダプターとRunnableで他は省略。
public class MyDirectoryListAdapter extends RecyclerView.Adapter< MyDirectoryListAdapter.ViewHolder> {
public static class MyRunnableData { // Runnable データ引き渡し用クラス
private File mTargetDir = null;
private File mCacheDir = null;
private List< String> mListType = null;
private List< String> mListName = null;
private RecyclerView myRecyclerView = null;
MyRunnableData( File tDir, File cDir, List< String> lt, List< String> ln ) {
mTargetDir = tDir;
mCacheDir = cDir;
mListType = new ArrayList<>(lt);
mListName = new ArrayList<>(ln);
}
public File getTargetDir() { return mTargetDir; }
public File getCacheDir() { return mCacheDir; }
public List< String> getListType() { return mListType; }
public List< String> getListName() { return mListName; }
public void setNotifyItemChanged( int val ) {
if ( myRecyclerView != null ) {
myRecyclerView.post(new Runnable() {
@Override
public void run() {
MyDirectoryListAdapter adapter = (MyDirectoryListAdapter) myRecyclerView.getAdapter();
if (adapter != null) adapter.notifyItemChanged(val);
}
});
}
}
public void setRecyclerView(RecyclerView myRecyclerView) {
this.myRecyclerView = myRecyclerView;
}
public void clear() {
mListType.clear();
mListType = null;
mListName.clear();
mListName = null;
}
}
private MyRunnableData myRunnableData = null;
// アダプター本体
private MyMainData mMainData = null;
private LayoutInflater myInflater = null;
private RecyclerView myRecyclerView = null;
private View.OnClickListener myListener = null;
private List< String> listType = null;
private List< String> listName = null;
private File myCacheDir = null;
MyDirectoryListAdapter( MyMainData mainData ) {
mMainData = mainData;
myInflater = LayoutInflater.from( mainData.getContext() );
myRecyclerView = null;
listName = new ArrayList<>();
listType = new ArrayList<>();
setTempBufferDir( new File( mainData.getContext().getCacheDir(), "tempThumb" ) );
}
省略
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Bitmap bitmap = loadImage( position );
if (bitmap != null)
holder.imageView.setImageBitmap(bitmap);
holder.textView.setText( listName.get(position) );
holder.linearLayout.setId( holder.getAdapterPosition() );
holder.linearLayout.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
myListener.onClick(v);
}
});
}
public Bitmap loadImage( int position ) {
Bitmap bitmap = null;
if ( listType.get(position).equals("D") ) { // 識別:ディレクトリ
String name = listName.get(position) + ".jpg";
File cacheFile = new File( myCacheDir, name );
if (cacheFile.exists()) {
bitmap = BitmapFactory.decodeFile( cacheFile.getAbsolutePath() );
}
return ( bitmap != null )? bitmap:
BitmapFactory.decodeResource(mMainData.getContext().getResources(), R.drawable.folder );
}
if ( listType.get(position).equals("F") ) { // 識別:ファイル
File file = new File( myCacheDir, listName.get(position) );
if (file.exists())
bitmap = BitmapFactory.decodeFile( file.getAbsolutePath() );
return ( bitmap != null )? bitmap:
BitmapFactory.decodeResource(mMainData.getContext().getResources(), R.drawable.not_find);
}
return null;
}
public void addAll( MyDirData dirData ) {
clear();
listType.addAll( dirData.getDirTypeListForAdapter() );
listName.addAll( dirData.getDirNameListForAdapter() );
if ( myRunnableData != null ) myRunnableData.clear();
myRunnableData = new MyRunnableData( dirData.getTargetDir(), myCacheDir, listType, listName );
myRunnableData.setRecyclerView(myRecyclerView);
new Thread( new MyDirectoryIconRunnable( myRunnableData ) ).start();
notifyDataSetChanged();
}
public void setNotifyItemChanged( int position ) {
if ( position < 0 || position >= listName.size() ) return;
notifyItemChanged( position );
}
public void setTempBufferDir( File dir ) {
if ( !dir.exists() && !dir.mkdirs() ) return;
myCacheDir = dir;
}
省略
}