图像和列表视图(异步)

Images and listviews (Asynchronous)

我有一个 Listview,它将为每个项目包含一个不同的图像。我按照这个 tutorial 解释了如何实现所有的东西。

在测试我的应用程序时,我发现每个项目同时显示每个图像几毫秒,并且显示很多次,这让我的应用程序崩溃了。我看不出我哪里错了。这是我的代码:

ShowItemAdapter.java

public class ShowItemsAdapter extends ArrayAdapter<Show> {

    private ArrayList<Show> shows;
    private Context context;
    private LayoutInflater inflater;

    public class ViewHolder{
        public TextView title;
        public ImageView image;
    }

    public ShowItemsAdapter(Context context, List<Show> showArray, List<Bitmap> images)
    {
        super(context, R.layout.item_shows, showArray);
        shows = (ArrayList) showArray;
        this.context = context;
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    }

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

        View rootView = convertView;
        ViewHolder holder;

        if(convertView == null)
        {
            rootView = inflater.inflate(R.layout.item_shows, parent, false);
        }

        holder = new ViewHolder();
        holder.image = (ImageView) rootView.findViewById(R.id.item_shows_image);
        holder.title = (TextView) rootView.findViewById(R.id.item_shows_title);

        holder.title.setText(shows.get(position).getTitle());

        ImageFactory imageFactory = new ImageFactory();
        imageFactory.setParameters(context, shows.get(position).getImageURL(), holder.image);
        return rootView;
    }

ImageFactory.java

public class ImageFactory {

    public static final String IMAGE = "IMAGE";

    private ReceiveImageService receiveImageService;
    private Intent intentService;
    private ImageReceivedConfirmerReceiver imageReceivedConfirmerReceiver = new ImageReceivedConfirmerReceiver();
    private Bitmap image;
    private ImageView imageView;
    private String url;
    private Context context;

    public ImageFactory(){}

    public void setParameters(Context context, String url, ImageView imageView)
    {
        this.context = context;
        this.imageView = imageView;
        context.registerReceiver(
                imageReceivedConfirmerReceiver,
                new IntentFilter(ImageFactory.IMAGE)
        );

        this.url = url;

        //Creation of the service and adding request
        intentService = new Intent(context, ReceiveImageService.class);
        intentService.putExtra("URL", url);
        context.startService(intentService);
        context.bindService(intentService, receiveImageServiceConnection, Context.BIND_AUTO_CREATE);
    }

    private void displayImage(){
        imageView.setImageBitmap(image);
    }

    private ServiceConnection receiveImageServiceConnection = new ServiceConnection(){

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            ReceiveImageService.ReceiveImageBinder binder = (ReceiveImageService.ReceiveImageBinder)service;
            //get service
            receiveImageService = binder.getService();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
    };

    private class ImageReceivedConfirmerReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            if(receiveImageService != null)
            {
                //Receive the array of data
                image = receiveImageService.getImage();
                displayImage();
            }
        }
    }
}

ReceiveImageService.java

public class ReceiveImageService extends IntentService {

    private Connection connectionToServer;
    private final IBinder receiveImageBinder = new ReceiveImageBinder();

    private final static String BASE_URL = "http://www.readyo.linux.efrei.fr/";

    private Bitmap image;

    public ReceiveImageService(){super("ReceiveImageService");}

    @Override
    protected void onHandleIntent(Intent intent) {
        String URL = BASE_URL + intent.getStringExtra("URL");
        image = reachData(URL);
        sendFinishAlert();
    }

    private Bitmap reachData(String URL) {
        HttpURLConnection urlConnection = null;
        try {
            URL url = new URL(URL);
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setUseCaches(true);
            urlConnection.addRequestProperty("Cache-Control", "max-age=0");
            // handle issues
            if (urlConnection.getResponseCode() != 200) {
                throw new Exception("Status Error CODE : " + urlConnection.getResponseCode());
            }

            InputStream in = new BufferedInputStream(urlConnection.getInputStream());
            Bitmap bitmap = BitmapFactory.decodeStream(in);
            return bitmap;
        }catch (Exception e)
        {
            if(BuildConfig.DEBUG) Log.e("DEBUG", e.getMessage());

            //On notifie l'activité qu'une erreur de connexion a eu lieu
            //sendBroadcast(new Intent(AbstractNavigationFragment.ERROR_ACTION));
        }
        finally {
            if(urlConnection != null)
            urlConnection.disconnect();
        }
        return null;
    }

    protected void sendFinishAlert() {
        Intent intent = new Intent(ImageFactory.IMAGE);
        sendBroadcast(intent);
    }

    public Bitmap getImage()
    {
        return image;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent,flags,startId);
    }

    //BINDER
    private ReceiveImageService getInstance()
    {
        return this;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return receiveImageBinder;
    }

    @Override
    public boolean onUnbind(Intent intent){
        return false;
    }

    public class ReceiveImageBinder extends Binder {
        public ReceiveImageService getService() {
            return ReceiveImageService.this;
        }
    }
}

查看 logcat - 那里描述了崩溃原因。

Post 在这里,如果你有更多问题。

最好的办法是使用库,因为内存泄漏可能会带来很多问题。

加载图像的最佳库是 Picasso and Glide

毕加索 例子:

Picasso.with(context).load("URL").into(imageView);

滑行 示例:

Glide.with(context).load("url").into(imageView);