1

ListView で AsyncTask を使用して画像を読み込む際に、この奇妙な問題があります。ListView では、すべての行に ImageView と TextView が含まれています。このリンクをたどった:

http://android-developers.blogspot.in/2010/07/multithreading-for-performance.html

画像は URL から正常にダウンロードされており、関連する行に取り込まれています。しかし、ListView をスクロールするか、任意のリスト項目をクリックすると、画像が行を交換するだけです。TextViews のテキストは同じ行に残りますが。なぜそれが起こっているのかわかりません。私はそれについて多くのことをグーグルで調べましたが、完全な理由を見つけることができません. 助けてください。

これが私のアダプタークラスです:

     private class ListAdapter extends BaseAdapter{

    private ArrayList<HashMap<String, Object>> allFriends; 
    private LayoutInflater mInflater;

    public ListAdapter(ArrayList<HashMap<String, Object>> allFriends, Context context){
        this.allFriends = allFriends;
        mInflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount() {
        return allFriends.size();
    }

    @Override
    public Object getItem(int position) {
        return allFriends.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        FriendsViewHolder holder;

        if (convertView == null||!(convertView instanceof TextView)||!(convertView instanceof ImageView)) {
             convertView = mInflater.inflate(R.layout.friend_list_view, null);

             holder = new FriendsViewHolder();
             holder.friendName = (TextView) convertView.findViewById(R.id.friendName);
             holder.friendImage = (ImageView) convertView.findViewById(R.id.friendImage);                

             convertView.setTag(holder);
         }else {
             holder = (FriendsViewHolder) convertView.getTag(); 
         }

        holder.friendName.setText((String) allFriends.get(position).get(FriendsActivity.FRIENDS_NAME_KEY));

        String otherId=(String) allFriends.get(position).get(FriendsActivity.IDKEY);
        String isImage=(String) allFriends.get(position).get(FriendsActivity.IS_IMAGE_KEY);

            if(isImage.equalsIgnoreCase("true")){
                download(otherId, holder.friendImage);
            }

        return convertView;
    }
}//End of list adapter

ダウンロード方法は次のとおりです。

   public void download(String otherId, ImageView imageView) {
     BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);
     task.execute(otherId);
 }

ここで BitmapDownloaderTask は、画像をダウンロードするための非同期タスクです。

    class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
        private String otherId;
        private final WeakReference<ImageView> imageViewReference;

        public BitmapDownloaderTask(ImageView imageView) {
            imageViewReference = new WeakReference<ImageView>(imageView);
        }

        @Override
        // Actual download method, run in the task thread
        protected Bitmap doInBackground(String... params) {
             // params comes from the execute() call: params[0] is the url.

             return getOtherUserImage(params[0]);
        }

        @Override
        // Once the image is downloaded, associates it to the imageView
        protected void onPostExecute(Bitmap bitmap) {
            if (isCancelled()) {
                bitmap = null;
            }

            if(bitmap!=null){
                if (imageViewReference != null) {
                    ImageView imageView = imageViewReference.get(); 
                    if(imageView != null ){
                        imageView.setImageBitmap(bitmap);
                    } 
                }
            }
        }
    }

getOtherUserImage メソッドは次のとおりです。

    public Bitmap getOtherUserImage(String otherUserId){

    // code to download the image goes here. It returns bitmap "bmImg".

    if(bmImg==null){
        return null;
    }else {
        bmImg = Bitmap.createScaledBitmap(bmImg,imageWidth, imageHeight, true);

        /*availableFriends.get(position).put(BITMAP_KEY, bmImg);
        runOnUiThread(new Runnable() {
            public void run() {
                adapter.notifyDataSetChanged();
            }
        });*/
        return bmImg;
    }
}
4

2 に答える 2

1

このAndroid 開発者のブログ投稿では、画像を ListView に非同期的に正しく読み込む方法について説明し、ニーズに合わせてすばやく簡単に変更できる (私が行った) 優れたサンプル アプリを提供しています。

実際、メモリ効率の理由から、ListViewユーザーがスクロールしたときに表示されるビューをリサイクルします。リストを飛ばすと、特定のImageViewオブジェクトが何度も使用されます。が正しく表示されるたびにImageView、イメージ ダウンロード タスクがトリガーされ、最終的にイメージが変更されます。では、どこに問題があるのでしょうか。ほとんどの並列アプリケーションと同様に、重要な問題は順序にあります。この場合、ダウンロード タスクが開始された順序で完了するという保証はありません。その結果、リストに最終的に表示される画像は、たまたまダウンロードに時間がかかった以前のアイテムからのものである可能性があります。ダウンロードした画像が指定された ImageViews.

于 2012-07-28T19:56:16.110 に答える
0

画像をダウンロードするという方法を「同期」させるべきだと思います。多くのスレッドが同時に実行されているため、画像が間違った場所に表示される可能性があります。

于 2012-10-25T13:09:51.660 に答える