Я заполняю ListView
настраиваемым адаптером курсора, который получает набор результатов курсора из базы данных. Отображение всего 20 просмотров может занять до 10–12 секунд!
Вот класс CursorAdater, в котором курсор предоставляет строки и представление изображения base 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
А в классе List-view курсор получается в фоновом методе Async Class, а адаптер устанавливается в 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;
РЕДАКТИРОВАТЬ: напишите асинхронный класс для обработки преобразования базы 64 в растровое изображение, затем в представлении изображения после выполнения установлено растровое изображение. Этот внутренний класс вызывается из метода bindView класса cursoradpter. Проблема в том, что изображение заполняется только последним представлением !!
//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
Этот внутренний класс вызывается в методе bindView класса CursorAdpter:
//get bitmap image from base 64 string, and set to image view using asynch class thread
new getBitmapImage().execute(diveImagePath);