我是 Android 开发的初学者。我想从 SD 卡中以小尺寸显示图像。由于大图像速度很慢,所以我需要使用 a LruCache
,但它不起作用。我也在使用 SwipeView。这是一个 FileExplorer 示例。
这是我的ListFragment
:
public class Windows extends ListFragment {
private File currentDir = new File(Environment.getExternalStorageDirectory().getPath() + "/Pictures/pic/");
private FileArrayAdapter adapter;
int fragNum;
private LruCache<String, Bitmap> mMemoryCache;
static Windows init(int val) {
Windows List = new Windows();
Bundle args = new Bundle();
args.putInt("val", val);
List.setArguments(args);
return List;
}
public class FileArrayAdapter extends ArrayAdapter<Albumb> {
private Context c;
private int id;
private List<Albumb> items;
public FileArrayAdapter(Context context, int textViewResourceId, List<Albumb> objects) {
super(context, textViewResourceId, objects);
c = context;
id = textViewResourceId;
items = objects;
}
public Albumb getItem(int i) {
return items.get(i);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(id, null);
}
final Albumb item = items.get(position);
if (item != null) {
TextView t1 = (TextView) v.findViewById(R.id.TextView01);
TextView t2 = (TextView) v.findViewById(R.id.TextView02);
TextView t3 = (TextView) v.findViewById(R.id.TextViewDate);
ImageView imageCity = (ImageView) v.findViewById(R.id.fd_Icon1);
String type = item.getImage();
if (type.equalsIgnoreCase("directory_icon")) {
String uri = "drawable/" + item.getImage();
int imageResource = c.getResources().getIdentifier(uri, null, c.getPackageName());
Drawable image = c.getResources().getDrawable(imageResource);
imageCity.setImageDrawable(image);
} else {
final String imageKey = item.getName();
final Bitmap bm = getBitmapFromMemCache(currentDir + imageKey);
if (bm == null) {
BitmapWorkerTask task = new BitmapWorkerTask(imageCity);
task.execute(imageKey);
}
}
if (t1 != null)
t1.setText(item.getName());
if (t2 != null)
t2.setText(item.getData());
if (t3 != null)
t3.setText(item.getDate());
}
return v;
}
public Bitmap decodeSampledBitmapFromUri(String path, int reqWidth, int reqHeight) {
Bitmap bm = null;
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
bm = BitmapFactory.decodeFile(path, options);
return bm;
}
public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
if (width > height) {
inSampleSize = Math.round((float) height / (float) reqHeight);
} else {
inSampleSize = Math.round((float) width / (float) reqWidth);
}
}
return inSampleSize;
}
class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
public BitmapWorkerTask(ImageView imageView) {
imageViewReference = new WeakReference<ImageView>(imageView);
}
@Override
protected Bitmap doInBackground(String... params) {
final Bitmap bitmap = decodeSampledBitmapFromUri(params[0], 80, 80);
addBitmapToMemoryCache(params[0], bitmap);
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = (ImageView) imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fragNum = getArguments() != null ? getArguments().getInt("val") : 1;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View layoutView = inflater.inflate(R.layout.windows_frag,
container, false);
final int memClass
= ((ActivityManager) layoutView.getContext().getSystemService(Context.ACTIVITY_SERVICE))
.getMemoryClass();
// Use 1/8th of the available memory for this memory cache.
final int cacheSize = 1024 * 1024 * memClass / 8;
mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
// The cache size will be measured in bytes rather than number of items.
return bitmap.getByteCount();
}
};
fill(currentDir);
return layoutView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
private void fill(File f) {
File[] dirs = f.listFiles();
List<Albumb> dir = new ArrayList<Albumb>();
List<Albumb> fls = new ArrayList<Albumb>();
try {
for (File ff : dirs) {
String name = ff.getName();
Date lastModDate = new Date(ff.lastModified());
DateFormat formater = DateFormat.getDateTimeInstance();
String date_modify = formater.format(lastModDate);
/*
* Note: Remove this
* name.equalsIgnoreCase("Personal" if u
* want to list all ur sd card file and folder
*/
if (ff.isDirectory()) {
File[] fbuf = ff.listFiles();
int buf = 0;
if (fbuf != null) {
buf = fbuf.length;
} else
buf = 0;
String num_item = String.valueOf(buf);
if (buf == 0)
num_item = num_item + " item";
else
num_item = num_item + " items";
// String formated = lastModDate.toString();
dir.add(new Albumb(ff.getName(), num_item, date_modify, ff
.getAbsolutePath(), "directory_icon"));
} else {
/*
* Note: Remove this
* f.getName().equalsIgnoreCase("Personal"
* if u want to list all ur sd card file and folder
*/
fls.add(new Albumb(ff.getName(), ff.length() / 1024 + " KByte",
date_modify, ff.getAbsolutePath(), "file_icon"));
}
}
} catch (Exception e) {
}
Collections.sort(dir);
Collections.sort(fls);
dir.addAll(fls);
if (!f.getName().equalsIgnoreCase(Environment.getExternalStorageDirectory().getName() + "/Pictures/pic"))
dir.add(0, new Albumb("..", "Parent Directory", "", f.getParent(),
"directory_up"));
adapter = new FileArrayAdapter(getActivity(), R.layout.file_view, dir);
this.setListAdapter(adapter);
}
public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
if (getBitmapFromMemCache(key) == null) {
mMemoryCache.put(key, bitmap);
}
}
public Bitmap getBitmapFromMemCache(String key) {
return (Bitmap) mMemoryCache.get(key);
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Albumb o = adapter.getItem(position);
if (o.getImage().equalsIgnoreCase("directory_icon")
|| o.getImage().equalsIgnoreCase("directory_up")) {
currentDir = new File(o.getPath());
fill(currentDir);
}
}
}
这是我的视图模型ArrayAdapter
:
public class Albumb implements Comparable<Albumb> {
private String name;
private String data;
private String date;
private String path;
private String image;
public Albumb(String name, String date, String dt, String path, String image) {
this.name = name;
this.data = date;
this.path = path;
this.image = image;
}
public String getName() {
return name;
}
public String getData() {
return data;
}
public String getDate() {
return date;
}
public String getPath() {
return path;
}
public String getImage() {
return image;
}
public int compareTo(Albumb o) {
if (this.name != null)
return this.name.toLowerCase().compareTo(o.getName().toLowerCase());
else
throw new IllegalArgumentException();
}
}
日志猫:
05-01 23:43:08.257: E/AndroidRuntime(12687): FATAL EXCEPTION: AsyncTask #4
05-01 23:43:08.257: E/AndroidRuntime(12687): java.lang.RuntimeException: An error occured while executing doInBackground()
05-01 23:43:08.257: E/AndroidRuntime(12687): at android.os.AsyncTask$3.done(AsyncTask.java:299)
05-01 23:43:08.257: E/AndroidRuntime(12687): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
05-01 23:43:08.257: E/AndroidRuntime(12687): at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
05-01 23:43:08.257: E/AndroidRuntime(12687): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
05-01 23:43:08.257: E/AndroidRuntime(12687): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
05-01 23:43:08.257: E/AndroidRuntime(12687): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
05-01 23:43:08.257: E/AndroidRuntime(12687): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
05-01 23:43:08.257: E/AndroidRuntime(12687): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
05-01 23:43:08.257: E/AndroidRuntime(12687): at java.lang.Thread.run(Thread.java:856)
05-01 23:43:08.257: E/AndroidRuntime(12687): Caused by: java.lang.NullPointerException: key == null || value == null
05-01 23:43:08.257: E/AndroidRuntime(12687): at android.support.v4.util.LruCache.put(LruCache.java:117)
05-01 23:43:08.257: E/AndroidRuntime(12687): at com.example.swipetab.Windows.addBitmapToMemoryCache(Windows.java:349)
05-01 23:43:08.257: E/AndroidRuntime(12687): at com.example.swipetab.Windows$FileArrayAdapter$BitmapWorkerTask.doInBackground(Windows.java:216)
05-01 23:43:08.257: E/AndroidRuntime(12687): at com.example.swipetab.Windows$FileArrayAdapter$BitmapWorkerTask.doInBackground(Windows.java:1)
05-01 23:43:08.257: E/AndroidRuntime(12687): at android.os.AsyncTask$2.call(AsyncTask.java:287)
05-01 23:43:08.257: E/AndroidRuntime(12687): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
谢谢您的帮助。