Android:在 ImageView.setBitmapDrawable(..) 之后,异步加载的位图随机不会出现在 ImageView 中

标签 android android-listview android-asynctask android-imageview loopj

我有一个 ListView,它的元素是我需要从我使用 loopj 访问的远程 API 加载的照片。

loopj 下载照片数据后,我使用 AsyncTask 将数据处理成缩放位图。

这通常很好用,但是..

问题

在我的 AsyncTask 的 onPostExecute 方法中,我在 ImageView 上调用了 setImageBitmap。有时,调用 ImageView.setImageBitmap 后,位图根本不会出现在 ImageView 中。我已经通过日志和调试器验证了确实在有问题的 ImageView 上调用了 ImageView.setImageBitmap。

如果我稍微滚动列表,列表元素会重绘,图像会从内存缓存中加载并正确显示在 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 上调用 invalidate(),但遗憾的是,这并没有解决问题。

如果有任何帮助或指点,我将不胜感激。

更新

来 self 的适配器的 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;
        }

最佳答案

我认为 .setImageBitmap(Bitmap) 方法工作正常,您只是将其设置为 null

onPostExecute(Bitmap bitmap) 中检查 bitmap == null 的情况。这也符合您的观察,即当您滚动时图像会出现,因为 Android 会在那时再次为可见行调用 getView(..)

关于Android:在 ImageView.setBitmapDrawable(..) 之后,异步加载的位图随机不会出现在 ImageView 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21330345/

相关文章:

android - 如何在 ANDROID 自定义 Listview Adapter 中使用 setonitemclicklistener

android - 如何在android顶部的 ListView 中添加新项目

安卓 : AsyncTask byte[] issue

java - AsyncTask 在结束 doInBackground 之前检查 MainActivity 中的变量集

android - 如何获得印度的+91之类的移动国家代码?

android - Gridlayout 不显示,Android 工作室

android - 首选项菜单中 Android 向上/向后导航的动态父 Activity

java - MediaRecorder.GetSurface() 返回 null

android - 自定义 ListView 错误 : java. lang.unsupportedoperationexception: addview

java - Android 异步任务和 TCP/IP 套接字