我使用自定义游标适配器填充ListView
,该适配器从数据库接收游标结果集。显示20个视图最多可能需要10-12秒!
这是 CursorAdater 类,其中光标将字符串和基本64图像表示提供给一系列文本视图和图像视图对于每个视图:
public void bindView(View v, Context context, Cursor c) {
String diveSite = c.getString(c.getColumnIndexOrThrow(diveDataBase.KEY_DIVESITE));
String date = c.getString(c.getColumnIndexOrThrow(diveDataBase.KEY__DIVEDATE));
String diveNumber= c.getString(c.getColumnIndexOrThrow(diveDataBase.KEY__DIVENUMBER));
String diveImagePath = c.getString(c.getColumnIndex(diveDataBase.KEY_DIVEPICTURE));
String rating = c.getString(c.getColumnIndexOrThrow(diveDataBase.KEY_DIVERATING));
c.moveToLast();
noOfRows = Integer.parseInt(c.getString(c.getColumnIndex(diveDataBase.KEY__DIVENUMBER)));
/**
* Next set the dive site name
*/
TextView title_text = (TextView) v.findViewById(R.id.tv_DiveSiteListView);
if (title_text!= null) {
title_text.setText(diveSite);
}
/**
* Set Date of dive in smaller textView font
*/
TextView date_text = (TextView) v.findViewById(R.id.tv_diveDateList);
if (date_text!= null) {
date_text.setText(date);
}
/**
* Display the dive number in larger red font
*/
TextView dive_no = (TextView) v.findViewById(R.id.tv_diveNumberListView);
if (diveNumber!= null ) {
dive_no.setText(diveNumber+"/"+noOfRows);//+1 as rows start at zero
}
/*
* Display the rating of the dive
*/
RatingBar bar = (RatingBar) v.findViewById(R.id.ratingBarListView);
bar.setNumStars(5);
bar.setRating( Float.parseFloat(rating));
/**
* Display the image only of image not null
* First get image from Strimg pathname as a file, then convert to Bitmap and resize
*
*/
ImageView displayImage = (ImageView) v.findViewById(R.id.iv_list_image);
//set image here once taken form external string path, and resized bitmap conversion
imagePathFile = new File(diveImagePath);
try {
FileInputStream streamIn = new FileInputStream(imagePathFile);
Bitmap bitmap = BitmapFactory.decodeStream(streamIn);//retrun null if can't convert
if(bitmap!=null){
displayImage.setBackground(null);
resizedImage = reSizeImage(bitmap);
displayImage.setImageBitmap(resizedImage);
}else{
displayImage.setBackgroundResource(R.drawable.logdive3);
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
}//end try catch
}//end newView
在列表视图类中,光标是在异步类的背景化方法中获取的,并且适配器在on-post中设置-execute:
@Override
protected Cursor doInBackground(Void... params) {
// get the cursor from database
ViewListOfDives.data = new diveDataBase(ViewListOfDives.this);
ViewListOfDives.data.open();
// get cursor object holding all data, use a asynch inner class to load
cursor = data.getCursorData();
//ViewListOfDives.data.close();
return cursor;
}
//set the adapter to list view
@Override
protected void onPostExecute(Cursor cursor) {
//check if data available
if(cursor!=null && cursor.getCount()>0){
// get customised array adoater list
adapter = new ItemAdapter(ViewListOfDives.this, cursor);
}else{
//display o dives in data base message and finish this activity
displayDialog();
}
ViewListOfDives.this.setListAdapter(adapter);
ViewListOfDives.data.close();
super.onPostExecute(cursor);
// dispose dialog
if(pd.isShowing()){
pd.dismiss();
}
}
一直在研究分配,在性能优化游标适配器上找不到多少所以任何输入都会非常感激!!
编辑:包括我用来调整图片大小的方法:
public Bitmap reSizeImage(Bitmap bitmapImage) {
// resize bitmap image passed and rerun new one
Bitmap resizedImage = null;
float factorH = h / (float) bitmapImage.getHeight();
float factorW = w / (float) bitmapImage.getWidth();
float factorToUse = (factorH> factorW)? factorW : factorH;
try {
resizedImage = Bitmap.createScaledBitmap(bitmapImage,
(int) (bitmapImage.getWidth() * factorToUse),
(int) (bitmapImage.getHeight() * factorToUse), false);
} catch (IllegalArgumentException e) {
Log.d(TAG, "Problem resizing Image @Line 510+");
e.printStackTrace();
}
Log.d(TAG,
"in resixed, value of resized image: "
+ resizedImage.toString());
return resizedImage;
}// end reSize
h和w:
// for image resizing
static int w = 250;
static int h = 280;
编辑:使用asynch类来处理base 64到bitmap的转换,然后在post执行图像视图中设置为位图。这个内部类被称为cursoradpter类的bindView方法。问题是现在只有最后一个视图用图像填充!!
//asynch class to load nase 64 image and convert to bitmap and set imageview
private class getBitmapImage extends AsyncTask<String, Void, Bitmap>{
@Override
protected Bitmap doInBackground(String... imagePath) {
// get image path and decode to bitmap
String diveImagePath = imagePath[0];
//String diveImagePath = c.getString(c.getColumnIndex(diveDataBase.KEY_DIVEPICTURE));
File imagePathFile = new File(diveImagePath);
try {
FileInputStream streamIn = new FileInputStream(imagePathFile);
bitmap = BitmapFactory.decodeStream(streamIn);//retrun null if cant convert
}catch (FileNotFoundException e) {
e.printStackTrace();
//Toast.makeText(context, "No Image Found!! Usimng default", Toast.LENGTH_LONG).show();
}//end try catch
return bitmap;
}//end do in background
@Override
protected void onPostExecute(Bitmap bitmap) {
if(bitmap!=null){
displayImage.setBackground(null);
resizedImage = reSizeImage(bitmap);
displayImage.setImageBitmap(resizedImage);
}else{
//Toast.makeText(context, "No Image Found!! Usimng default", Toast.LENGTH_LONG).show();
displayImage.setBackgroundResource(R.drawable.logdive3);
}
}//end onPOstExecute
}//end getBitmap asynch
这个内部类在CursorAdpter类的bindView方法中调用:
//get bitmap image from base 64 string, and set to image view using asynch class thread
new getBitmapImage().execute(diveImagePath);
答案 0 :(得分:2)
首先将文字放在屏幕上。也许是默认的drawables来显示正在加载的内容。
从文件加载20位图至少需要几秒钟。您应该异步加载这些(从填充列表视图的线程)。只有您的UI线程可以设置imageview,但您可以在工作线程中加载位图,这是最重要的工作。
您还应该使用采样加载位图,这样您就不会以高于可以显示的分辨率加载它们,否则您将读取的数据超出您的需要。
有效加载大型位图请参阅android tutorial。
答案 1 :(得分:1)
将游标适配器与loader一起使用。当我拥有超过8000条记录的数据库时,它帮助我快速加载。我希望它会对你有所帮助 参考:http://developer.android.com/guide/components/loaders.html