У меня есть ListView, чьими элементами являются фотографии, которые мне нужно загрузить из удаленного API, который я использую для доступа к loopj.Android: асинхронные загруженные растровые изображения случайно не отображаются в ImageView после ImageView.setBitmapDrawable (..)
После того, как loopj загружает данные фото, я использую AsyncTask для обработки данных в масштабированном растровом изображении.
Это, как правило, отлично работает, однако ..
Проблема
В моем методе onPostExecute AsyncTask, я называю setImageBitmap на ImageView. Иногда растровое изображение просто не появляется в ImageView после вызова ImageView.setImageBitmap. Я проверил через журналы, а также отладчик, что ImageView.setImageBitmap действительно вызван нарушением ImageView.
Если я немного прокручиваю список, элемент списка перерисовывается, и изображение загружается из кеша памяти и правильно отображается в ImageView.
Вот мой код:
public void setPersonImage(final ImageView personImageView, final Person p) {
personImageView.setImageResource(R.drawable.empty_image);
//kills unecessary requests for the imageview's previous occupant photo
if(personImageView.getTag() != null) {
AsyncHttpClient client = mPhotoRequestsMap.get(p.getEmployeeId());
if(client != null) {
client.cancelRequests(getActivity().getApplicationContext(), true);
Log.d(TAG, "Cancled photo request for " + String.valueOf(p.getEmployeeId()));
}
}
personImageView.setTag(p.getEmployeeId());
//first attempt to grab photo from cache
Bitmap cachedBitmap = mMemoryCache.get(p.getPhotoCacheKey());
if(cachedBitmap != null) {
personImageView.setImageBitmap(cachedBitmap);
Log.d(TAG, "bitmap for " + String.valueOf(p.getEmployeeId()) + " retrieved from memory cache");
} else {
AsyncHttpClient client = ApiWrapper.getPersonImage(180,mUserSession,
getActivity().getApplicationContext(), p.getEmployeeId(),
new MyAsyncHttpResponseHandler(this) {
@Override
public void onSuccess(String response) {
if(personImageView.getTag().equals(p.getEmployeeId())) {
// use async task to process the bitmap off the UI thread
AsyncTask<String,Integer,Bitmap> task = new AsyncTask<String,Integer,Bitmap>() {
@Override
protected Bitmap doInBackground(String... params) {
String response = params[0];
byte[] bitmapBytes = ApiWrapper.processImageResponse(response);
Bitmap bitmap = BitmapFactory.decodeByteArray(bitmapBytes, 0, bitmapBytes.length);
Bitmap bmpScaled = ThumbnailUtils.extractThumbnail(bitmap, 180, 180);
return bmpScaled;
}
protected void onPostExecute(Bitmap bitmap) {
//set on imageview if tags agree
if(personImageView.getTag().equals(p.getEmployeeId())) {
Log.d(TAG, "setting image view for " + p.getEmployeeId());
personImageView.setImageBitmap(bitmap);
mMemoryCache.put(p.getPhotoCacheKey(), bitmap);
}
else {
Log.d(TAG, "tags don't match after decode bitmap, discarding...");
}
}
};
task.execute(response);
}
else {
Log.d(TAG, "tags don't match BEFORE decode bitmap employee id: " + p.getEmployeeId() + " tag: " + personImageView.getTag());
}
}
}
);
//create entry in PhotoRequestsMap table
mPhotoRequestsMap.put(p.getEmployeeId(), client);
} // end if not in cache
}
Я попытался назвать недействительными() на ImageView после растровый установлен на нем, но, к сожалению, не решить ..
Я d очень ценю любую помощь или указатели.
Update
Метод GetView из моего адаптера:
public View getView(int position, View convertView, ViewGroup parent) {
// If we weren't given a view, inflate one
if (convertView == null) {
convertView = getActivity().getLayoutInflater().inflate(R.layout.list_item_person, null);
}
Person p = getItem(position);
TextView nameTextView = (TextView)convertView.findViewById(R.id.person_ListItemNameTextView);
nameTextView.setText(p.getFirstName() + " " + p.getLastName());
TextView idTextView = (TextView)convertView.findViewById(R.id.person_ListItemIdTextView);
idTextView.setText(String.valueOf(p.getEmployeeId()));
ImageView personImageView = (ImageView)convertView.findViewById(R.id.person_ListItemImageView);
setPersonImage(personImageView, p);
return convertView;
}
'personImageView' вызывается несколько раз, прежде чем первый AsyncTask закончит, второй перезаписывает его. Попробуйте создать массив объектов. – Shakti
Я предполагаю, что вы повторно используете одни и те же изображения для разных строк списка? Можно ли увидеть метод getView (...) 'от вашего адаптера? –
@ErnirErlingsson Я думаю, что андроид по умолчанию будет перерабатывать сами ImageView. Я кеширую растровые изображения. Я обновил вопрос с помощью метода getView(). Благодаря! – James