2

此自定义适配器加载的图像放置在错误的位置,即正确的电影横幅未放置在正确的列表视图项中。并在一段时间内不断变化。这是我的带有 ASYNCTASK 的自定义适配器,它从 URL 加载图像

    import java.net.URL;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.List;

    import android.content.Context;
    import android.content.Intent;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.net.Uri;
    import android.os.AsyncTask;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    import android.widget.ImageView;
    import android.widget.TextView;
    import androlizer.yify.torrent.R;
    import androlizer.yify.torrents.models.UpcomingMovieListModel;

    public class UpcomingMoviesCustomAdapter extends ArrayAdapter<UpcomingMovieListModel> {


        Context context;
        public UpcomingMoviesCustomAdapter(
                Context context, int resource, List<UpcomingMovieListModel> objects) {
            super(context, resource, objects);
            this.context = context;
        }

        static class ViewHolder
        {
            TextView movieTitle_textView;
            TextView uploader_textView;
            TextView date_textView;
            ImageView movie_icon_imageView;
            ImageView imdb_url_imageView;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            final ViewHolder holder;
            // getting data
            final UpcomingMovieListModel movie = getItem(position);     

            if (convertView == null) 
            {
                convertView = View.inflate(context, R.layout.movie_upcoming_row, null);                
                holder = new ViewHolder();

                holder.movieTitle_textView = (TextView) convertView.findViewById(R.id.movie_upcoming_movie_title);
                holder.uploader_textView = (TextView) convertView.findViewById(R.id.movie_upcoming_uploader);
                holder.date_textView = (TextView) convertView.findViewById(R.id.movie_upcoming_date);
                holder.imdb_url_imageView = (ImageView)convertView.findViewById(R.id.movie_upcoming_imageView_imdblink);
                holder.movie_icon_imageView = (ImageView)convertView.findViewById(R.id.movie_upcoming_movie_image_view);
                convertView.setTag(holder);
            }
            else
            {
                holder = (ViewHolder)convertView.getTag();
            }

            if (movie != null) 
            {
                holder.movieTitle_textView.setText(movie.getM_title());
                holder.uploader_textView.setText(movie.getUploader());

                SimpleDateFormat origFormat= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                //Store it as a date object
                Date date = null;
                try {
                    date = origFormat.parse(movie.getDate_added());
                } catch (ParseException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                //Output it as a string that uses the new format
                SimpleDateFormat newFormat= new SimpleDateFormat("MMMMMMMMM dd, yyyy 'at' hh:mm a");

                String desiredDateFormat = newFormat.format(date);
                holder.date_textView.setText(desiredDateFormat);

                holder.imdb_url_imageView.setOnClickListener(new View.OnClickListener() {

                    @Override
                    public void onClick(View v) {
                        context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(movie.getImdb_url())));
                    }
                }); 
            }

            new ImageLoader().execute(convertView.g, movie.getM_cover());
            return convertView;

        }

        public class ImageLoader extends AsyncTask<Object, String, Bitmap> {

            private View view;
            private Bitmap bitmap = null;

            @Override
            protected Bitmap doInBackground(Object... parameters) {

                // Get the passed arguments here
                view = (View) parameters[0];
                String uri = (String)parameters[1];

                // Create bitmap from passed in Uri here
                // ...
                try {
                    URL req = new URL(uri);
                    bitmap = BitmapFactory.decodeStream(req.openConnection()
                            .getInputStream());
                } catch (Exception e) {
                    // TODO: handle exception
                }
                return bitmap;
            }

            @Override
            protected void onPostExecute(Bitmap bitmap) {
                if (bitmap != null && view != null) {
                    ImageView splash = (ImageView) view.findViewById(R.id.movie_upcoming_movie_image_view);
                    splash.setImageBitmap(bitmap);          
                }
            }
        }
    }
4

2 回答 2

2

我认为问题在于,当列表项被重用时,您不会停止前ImageLoader一个:当一个列表项被重用时,另一个ImageLoader被附加到它但没有删除附加到同一个列表项实例的前一个。

因此,第一个ImageLoader可能会在设置错误图像的最后一个之后完成其工作。您还需要缓存下载的图像,否则已经下载的图像将再次下载。

正确的做法(TM)应该是在holder与列表项相关的实例中设置图像位图,而不是停止加载程序,使其作用于holder.

于 2013-06-13T14:49:44.667 回答
0

What is happening here is that you are loading your images and setting them to the ImageView for your current list item, but not storing that Bitmap anywhere else. ListItems in Android are reused so that when you scroll, the device doesn't have to store many ListItems in memory. As a result, the OS will set new images to your list items as you scroll, which won't be the ones that you want.

The solution is to store your Bitmaps in the ArrayList that backs your ListView. In this case, it is List<UpcomingMovieListModel> objects that holds your data for the list view. There are several changes that need to be made here, so I'm not going to provide the full code, but I will describe the process.

  1. Extend your UpcomingMovieListModel object to have a field called movieIcon.
  2. Pass the current UpcomingMovieListModel object to your AsyncTask and have the AsyncTask set movieIcon to the downloaded image.
  3. In your getView method, set the ImageView to the value of movie.movieIcon if it is not null.
  4. In onPostExecute for your AsyncTask call this.notifyDataSetChanged() after you set movieIcon to the newly downloaded image. This tells the ListView that you have changed the underlying data, and it should refresh to show the icon for the current movie in each item on the screen.
  5. Do not call setImageBitmap directly in onPostExecute. This will be taken care of in getView when you notify that the dataset has changed.

If you change these things, you should see all the right images, because you'll be storing them correctly for the underlying data.

于 2013-06-13T15:03:07.203 回答