在android中的Listview上延迟加载图像(初学者水平)?

发布于 2024-09-03 04:41:51 字数 6424 浏览 10 评论 0原文

可能的重复:
Android - 如何进行惰性加载ListView 中加载图像

我正在使用自定义适配器处理列表视图。我想加载其上的图像和文本视图。图像是从互联网网址加载的。我只想向用户显示可见列表项的图像。我提到了 搁置来自 romainguy 的开源项目示例,但代码理解起来很复杂。对于初学者来说,我只想知道如何处理适配器和活动之间的标签。来自 公共软件 example 我可以在适配器上设置标签,但无法在列表视图的空闲状态下显示相应的图像。请帮助我提出你的想法。示例代码更容易理解。

谢谢。

编辑:

高效<的组合/a> 和慢 ApiDemos中的Adapter更有助于理解。

对高效适配器示例进行的更改如下所示:

public class List14 extends ListActivity implements ListView.OnScrollListener {
// private TextView mStatus;

private static boolean mBusy = false;
static ViewHolder holder;

public static class EfficientAdapter extends BaseAdapter {
    private LayoutInflater mInflater;
    private Bitmap mIcon1;
    private Bitmap mIcon2;

    public EfficientAdapter(Context context) {
        // Cache the LayoutInflate to avoid asking for a new one each time.
        mInflater = LayoutInflater.from(context);

        // Icons bound to the rows.
        mIcon1 = BitmapFactory.decodeResource(context.getResources(),
                R.drawable.icon48x48_1);
        mIcon2 = BitmapFactory.decodeResource(context.getResources(),
                R.drawable.icon48x48_2);
    }

    /**
     * The number of items in the list is determined by the number of
     * speeches in our array.
     * 
     * @see android.widget.ListAdapter#getCount()
     */
    public int getCount() {
        return DATA.length;
    }

    /**
     * Since the data comes from an array, just returning the index is
     * sufficent to get at the data. If we were using a more complex data
     * structure, we would return whatever object represents one row in the
     * list.
     * 
     * @see android.widget.ListAdapter#getItem(int)
     */
    public Object getItem(int position) {
        return position;
    }

    /**
     * Use the array index as a unique id.
     * 
     * @see android.widget.ListAdapter#getItemId(int)
     */
    public long getItemId(int position) {
        return position;
    }

    /**
     * Make a view to hold each row.
     * 
     * @see android.widget.ListAdapter#getView(int, android.view.View,
     *      android.view.ViewGroup)
     */
    public View getView(int position, View convertView, ViewGroup parent) {
        // A ViewHolder keeps references to children views to avoid
        // unneccessary calls
        // to findViewById() on each row.

        // When convertView is not null, we can reuse it directly, there is
        // no need
        // to reinflate it. We only inflate a new View when the convertView
        // supplied
        // by ListView is null.
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.list_item_icon_text,
                    null);

            // Creates a ViewHolder and store references to the two children
            // views
            // we want to bind data to.
            holder = new ViewHolder();
            holder.text = (TextView) convertView.findViewById(R.id.text);
            holder.icon = (ImageView) convertView.findViewById(R.id.icon);

            convertView.setTag(holder);
        } else {
            // Get the ViewHolder back to get fast access to the TextView
            // and the ImageView.
            holder = (ViewHolder) convertView.getTag();
        }
        if (!mBusy) {
            holder.icon.setImageBitmap(mIcon1);

            // Null tag means the view has the correct data
            holder.icon.setTag(null);
        } else {
            holder.icon.setImageBitmap(mIcon2);

            // Non-null tag means the view still needs to load it's data
            holder.icon.setTag(this);
        }
        holder.text.setText(DATA[position]);

        // Bind the data efficiently with the holder.
        // holder.text.setText(DATA[position]);

        return convertView;
    }

    static class ViewHolder {
        TextView text;
        ImageView icon;
    }
}

private Bitmap mIcon1;
private Bitmap mIcon2;
@Override
public void onCreate(Bundle savedInstanceState) {
    mIcon1 = BitmapFactory.decodeResource(this.getResources(),
            R.drawable.icon48x48_1);
    mIcon2 = BitmapFactory.decodeResource(this.getResources(),
            R.drawable.icon48x48_2);
    super.onCreate(savedInstanceState);
    setListAdapter(new EfficientAdapter(this));
    getListView().setOnScrollListener(this);
}

public void onScroll(AbsListView view, int firstVisibleItem,
        int visibleItemCount, int totalItemCount) {
}

public void onScrollStateChanged(AbsListView view, int scrollState) {
    switch (scrollState) {
    case OnScrollListener.SCROLL_STATE_IDLE:
        mBusy = false;

        int first = view.getFirstVisiblePosition();
        int count = view.getChildCount();
        for (int i = 0; i < count; i++) {

            holder.icon = (ImageView) view.getChildAt(i).findViewById(
                    R.id.icon);
            if (holder.icon.getTag() != null) {
                holder.icon.setImageBitmap(mIcon1);
                holder.icon.setTag(null);
            } 
        }

        // mStatus.setText("Idle");
        break;
    case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
        mBusy = true;
        // mStatus.setText("Touch scroll");
        break;
    case OnScrollListener.SCROLL_STATE_FLING:
        mBusy = true;
        // mStatus.setText("Fling");
        break;
    }
}
private static final String[] DATA = { "Abbaye de Belloc",
        "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
        "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu"};
}

现在工作正常。但是当滚动状态时,它无法正确重新加载图像。某些项目间隔不显示图像2。这是图像加载的正确顺序。但并非在列表的所有项目中。实体项目间隔之间发生不匹配。 如何纠正?

Possible Duplicate:
Android - How do I do a lazy load of images in ListView

I am working on the listview with the custom adapter. I want to load the images and text view on it. The images are load from the internet urls. I just want to show the images which are visible list item to hte user. I refered the Shelves opensource project example from romainguy, but its to complicated to understand the code. For a beginner level, I just want to know how to handle the tag between the adapter and activity. From the commonsware example I can set the tag on adapter, but can't show the corresponding image at the idle state of the listview. Please help me with your ideas. Sample codes are more understandable.

Thanks.

EDIT:

The combination of Efficient and Slow Adapter in ApiDemos is more helpful to understand.

changes done on efficient adapter example like this:

public class List14 extends ListActivity implements ListView.OnScrollListener {
// private TextView mStatus;

private static boolean mBusy = false;
static ViewHolder holder;

public static class EfficientAdapter extends BaseAdapter {
    private LayoutInflater mInflater;
    private Bitmap mIcon1;
    private Bitmap mIcon2;

    public EfficientAdapter(Context context) {
        // Cache the LayoutInflate to avoid asking for a new one each time.
        mInflater = LayoutInflater.from(context);

        // Icons bound to the rows.
        mIcon1 = BitmapFactory.decodeResource(context.getResources(),
                R.drawable.icon48x48_1);
        mIcon2 = BitmapFactory.decodeResource(context.getResources(),
                R.drawable.icon48x48_2);
    }

    /**
     * The number of items in the list is determined by the number of
     * speeches in our array.
     * 
     * @see android.widget.ListAdapter#getCount()
     */
    public int getCount() {
        return DATA.length;
    }

    /**
     * Since the data comes from an array, just returning the index is
     * sufficent to get at the data. If we were using a more complex data
     * structure, we would return whatever object represents one row in the
     * list.
     * 
     * @see android.widget.ListAdapter#getItem(int)
     */
    public Object getItem(int position) {
        return position;
    }

    /**
     * Use the array index as a unique id.
     * 
     * @see android.widget.ListAdapter#getItemId(int)
     */
    public long getItemId(int position) {
        return position;
    }

    /**
     * Make a view to hold each row.
     * 
     * @see android.widget.ListAdapter#getView(int, android.view.View,
     *      android.view.ViewGroup)
     */
    public View getView(int position, View convertView, ViewGroup parent) {
        // A ViewHolder keeps references to children views to avoid
        // unneccessary calls
        // to findViewById() on each row.

        // When convertView is not null, we can reuse it directly, there is
        // no need
        // to reinflate it. We only inflate a new View when the convertView
        // supplied
        // by ListView is null.
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.list_item_icon_text,
                    null);

            // Creates a ViewHolder and store references to the two children
            // views
            // we want to bind data to.
            holder = new ViewHolder();
            holder.text = (TextView) convertView.findViewById(R.id.text);
            holder.icon = (ImageView) convertView.findViewById(R.id.icon);

            convertView.setTag(holder);
        } else {
            // Get the ViewHolder back to get fast access to the TextView
            // and the ImageView.
            holder = (ViewHolder) convertView.getTag();
        }
        if (!mBusy) {
            holder.icon.setImageBitmap(mIcon1);

            // Null tag means the view has the correct data
            holder.icon.setTag(null);
        } else {
            holder.icon.setImageBitmap(mIcon2);

            // Non-null tag means the view still needs to load it's data
            holder.icon.setTag(this);
        }
        holder.text.setText(DATA[position]);

        // Bind the data efficiently with the holder.
        // holder.text.setText(DATA[position]);

        return convertView;
    }

    static class ViewHolder {
        TextView text;
        ImageView icon;
    }
}

private Bitmap mIcon1;
private Bitmap mIcon2;
@Override
public void onCreate(Bundle savedInstanceState) {
    mIcon1 = BitmapFactory.decodeResource(this.getResources(),
            R.drawable.icon48x48_1);
    mIcon2 = BitmapFactory.decodeResource(this.getResources(),
            R.drawable.icon48x48_2);
    super.onCreate(savedInstanceState);
    setListAdapter(new EfficientAdapter(this));
    getListView().setOnScrollListener(this);
}

public void onScroll(AbsListView view, int firstVisibleItem,
        int visibleItemCount, int totalItemCount) {
}

public void onScrollStateChanged(AbsListView view, int scrollState) {
    switch (scrollState) {
    case OnScrollListener.SCROLL_STATE_IDLE:
        mBusy = false;

        int first = view.getFirstVisiblePosition();
        int count = view.getChildCount();
        for (int i = 0; i < count; i++) {

            holder.icon = (ImageView) view.getChildAt(i).findViewById(
                    R.id.icon);
            if (holder.icon.getTag() != null) {
                holder.icon.setImageBitmap(mIcon1);
                holder.icon.setTag(null);
            } 
        }

        // mStatus.setText("Idle");
        break;
    case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
        mBusy = true;
        // mStatus.setText("Touch scroll");
        break;
    case OnScrollListener.SCROLL_STATE_FLING:
        mBusy = true;
        // mStatus.setText("Fling");
        break;
    }
}
private static final String[] DATA = { "Abbaye de Belloc",
        "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
        "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu"};
}

It works fine now. But when the scrolling state its not reloading the image properly. some interval of items not shows the images2. that is the correct order of the images are loading. But not in all items of list. Mismatches happening between solid item intervals.
how to correct it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

零崎曲识 2024-09-10 04:41:51

我得到了它。这是我想要的完美代码。延迟加载适用于自定义适配器,仅显示列表项的图标。希望对初学者有帮助

public class List14 extends ListActivity implements ListView.OnScrollListener {
// private TextView mStatus;

private static boolean mBusy = false;
static ViewHolder holder;

public static class EfficientAdapter extends BaseAdapter {
    private LayoutInflater mInflater;
    private Bitmap mIcon1;
    private Bitmap mIcon2;
    private Context mContext;

    public EfficientAdapter(Context context) {
        // Cache the LayoutInflate to avoid asking for a new one each time.
        mInflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mContext = context;
        // Icons bound to the rows.
        mIcon1 = BitmapFactory.decodeResource(context.getResources(),
                R.drawable.icon48x48_1);
        mIcon2 = BitmapFactory.decodeResource(context.getResources(),
                R.drawable.icon48x48_2);
    }

    /**
     * The number of items in the list is determined by the number of
     * speeches in our array.
     * 
     * @see android.widget.ListAdapter#getCount()
     */
    public int getCount() {
        return DATA.length;
    }

    /**
     * Since the data comes from an array, just returning the index is
     * sufficent to get at the data. If we were using a more complex data
     * structure, we would return whatever object represents one row in the
     * list.
     * 
     * @see android.widget.ListAdapter#getItem(int)
     */
    public Object getItem(int position) {
        return position;
    }

    /**
     * Use the array index as a unique id.
     * 
     * @see android.widget.ListAdapter#getItemId(int)
     */
    public long getItemId(int position) {
        return position;
    }

    /**
     * Make a view to hold each row.
     * 
     * @see android.widget.ListAdapter#getView(int, android.view.View,
     *      android.view.ViewGroup)
     */
    public View getView(int position, View convertView, ViewGroup parent) {
        // A ViewHolder keeps references to children views to avoid
        // unneccessary calls
        // to findViewById() on each row.

        // When convertView is not null, we can reuse it directly, there is
        // no need
        // to reinflate it. We only inflate a new View when the convertView
        // supplied
        // by ListView is null.
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.list_item_icon_text,
                    parent, false);

            // Creates a ViewHolder and store references to the two children
            // views
            // we want to bind data to.
            holder = new ViewHolder();
            holder.text = (TextView) convertView.findViewById(R.id.text);
            holder.icon = (ImageView) convertView.findViewById(R.id.icon);

             convertView.setTag(holder);
        } else {
            // Get the ViewHolder back to get fast access to the TextView
            // and the ImageView.
             holder = (ViewHolder) convertView.getTag();
        }

        if (!mBusy) {

            holder.icon.setImageBitmap(mIcon1);

            // Null tag means the view has the correct data
            holder.icon.setTag(null);

        } else {
            holder.icon.setImageBitmap(mIcon2);

            // Non-null tag means the view still needs to load it's data
            holder.icon.setTag(this);
        }
        holder.text.setText(DATA[position]);

        // Bind the data efficiently with the holder.
        // holder.text.setText(DATA[position]);

        return convertView;
    }

    static class ViewHolder {
        TextView text;
        ImageView icon;
    }
}

private Bitmap mIcon1;
private Bitmap mIcon2;

@Override
public void onCreate(Bundle savedInstanceState) {
    mIcon1 = BitmapFactory.decodeResource(this.getResources(),
            R.drawable.icon48x48_1);
    mIcon2 = BitmapFactory.decodeResource(this.getResources(),
            R.drawable.icon48x48_2);
    super.onCreate(savedInstanceState);
    setListAdapter(new EfficientAdapter(this));
    getListView().setOnScrollListener(this);
}

public void onScroll(AbsListView view, int firstVisibleItem,
        int visibleItemCount, int totalItemCount) {
}

public void onScrollStateChanged(AbsListView view, int scrollState) {
    switch (scrollState) {
    case OnScrollListener.SCROLL_STATE_IDLE:
        mBusy = false;

        int first = view.getFirstVisiblePosition();
        int count = view.getChildCount();

        for (int i = 0; i < count; i++) {

            holder.icon = (ImageView) view.getChildAt(i).findViewById(
                    R.id.icon);
            if (holder.icon.getTag() != null) {
                holder.icon.setImageBitmap(IMAGE[first+i]);// this is the image url array.
                holder.icon.setTag(null);
            }
        }

        // mStatus.setText("Idle");
        break;
    case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
        mBusy = true;
        // mStatus.setText("Touch scroll");
        break;
    case OnScrollListener.SCROLL_STATE_FLING:
        mBusy = true;
        // mStatus.setText("Fling");
        break;
    }
}

private static final String[] DATA = { "Abbaye de Belloc",
        "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
        "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu",
        "Yarra Valley Pyramid", "Yorkshire Blue", "Zamorano",
        "Zanetti Grana Padano", "Zanetti Parmigiano Reggiano" };
  }

I got it. This is the perfect code I want. Lazy loading works to custom adapter just visible list item's icons. Hope it helps to the beginners

public class List14 extends ListActivity implements ListView.OnScrollListener {
// private TextView mStatus;

private static boolean mBusy = false;
static ViewHolder holder;

public static class EfficientAdapter extends BaseAdapter {
    private LayoutInflater mInflater;
    private Bitmap mIcon1;
    private Bitmap mIcon2;
    private Context mContext;

    public EfficientAdapter(Context context) {
        // Cache the LayoutInflate to avoid asking for a new one each time.
        mInflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mContext = context;
        // Icons bound to the rows.
        mIcon1 = BitmapFactory.decodeResource(context.getResources(),
                R.drawable.icon48x48_1);
        mIcon2 = BitmapFactory.decodeResource(context.getResources(),
                R.drawable.icon48x48_2);
    }

    /**
     * The number of items in the list is determined by the number of
     * speeches in our array.
     * 
     * @see android.widget.ListAdapter#getCount()
     */
    public int getCount() {
        return DATA.length;
    }

    /**
     * Since the data comes from an array, just returning the index is
     * sufficent to get at the data. If we were using a more complex data
     * structure, we would return whatever object represents one row in the
     * list.
     * 
     * @see android.widget.ListAdapter#getItem(int)
     */
    public Object getItem(int position) {
        return position;
    }

    /**
     * Use the array index as a unique id.
     * 
     * @see android.widget.ListAdapter#getItemId(int)
     */
    public long getItemId(int position) {
        return position;
    }

    /**
     * Make a view to hold each row.
     * 
     * @see android.widget.ListAdapter#getView(int, android.view.View,
     *      android.view.ViewGroup)
     */
    public View getView(int position, View convertView, ViewGroup parent) {
        // A ViewHolder keeps references to children views to avoid
        // unneccessary calls
        // to findViewById() on each row.

        // When convertView is not null, we can reuse it directly, there is
        // no need
        // to reinflate it. We only inflate a new View when the convertView
        // supplied
        // by ListView is null.
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.list_item_icon_text,
                    parent, false);

            // Creates a ViewHolder and store references to the two children
            // views
            // we want to bind data to.
            holder = new ViewHolder();
            holder.text = (TextView) convertView.findViewById(R.id.text);
            holder.icon = (ImageView) convertView.findViewById(R.id.icon);

             convertView.setTag(holder);
        } else {
            // Get the ViewHolder back to get fast access to the TextView
            // and the ImageView.
             holder = (ViewHolder) convertView.getTag();
        }

        if (!mBusy) {

            holder.icon.setImageBitmap(mIcon1);

            // Null tag means the view has the correct data
            holder.icon.setTag(null);

        } else {
            holder.icon.setImageBitmap(mIcon2);

            // Non-null tag means the view still needs to load it's data
            holder.icon.setTag(this);
        }
        holder.text.setText(DATA[position]);

        // Bind the data efficiently with the holder.
        // holder.text.setText(DATA[position]);

        return convertView;
    }

    static class ViewHolder {
        TextView text;
        ImageView icon;
    }
}

private Bitmap mIcon1;
private Bitmap mIcon2;

@Override
public void onCreate(Bundle savedInstanceState) {
    mIcon1 = BitmapFactory.decodeResource(this.getResources(),
            R.drawable.icon48x48_1);
    mIcon2 = BitmapFactory.decodeResource(this.getResources(),
            R.drawable.icon48x48_2);
    super.onCreate(savedInstanceState);
    setListAdapter(new EfficientAdapter(this));
    getListView().setOnScrollListener(this);
}

public void onScroll(AbsListView view, int firstVisibleItem,
        int visibleItemCount, int totalItemCount) {
}

public void onScrollStateChanged(AbsListView view, int scrollState) {
    switch (scrollState) {
    case OnScrollListener.SCROLL_STATE_IDLE:
        mBusy = false;

        int first = view.getFirstVisiblePosition();
        int count = view.getChildCount();

        for (int i = 0; i < count; i++) {

            holder.icon = (ImageView) view.getChildAt(i).findViewById(
                    R.id.icon);
            if (holder.icon.getTag() != null) {
                holder.icon.setImageBitmap(IMAGE[first+i]);// this is the image url array.
                holder.icon.setTag(null);
            }
        }

        // mStatus.setText("Idle");
        break;
    case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
        mBusy = true;
        // mStatus.setText("Touch scroll");
        break;
    case OnScrollListener.SCROLL_STATE_FLING:
        mBusy = true;
        // mStatus.setText("Fling");
        break;
    }
}

private static final String[] DATA = { "Abbaye de Belloc",
        "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
        "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu",
        "Yarra Valley Pyramid", "Yorkshire Blue", "Zamorano",
        "Zanetti Grana Padano", "Zanetti Parmigiano Reggiano" };
  }
伴梦长久 2024-09-10 04:41:51

Praveen -

由于您已经找到了我关于此的博客文章,我只是想将其推回 Stackoverflow,以便其他人可以使用它。

这是基本讨论:
http://ballardhack。 wordpress.com/2010/04/05/loading-remote-images-in-a-listview-on-android/

我稍后记录了一个类,它使用线程和回调来加载图像:

< a href="http://ballardhack.wordpress.com/2010/04/10/loading-images-over-http-on-a-separate-thread-on-android/" rel="noreferrer">http:// /ballardhack.wordpress.com/2010/04/10/loading-images-over-http-on-a-separate-thread-on-android/

更新: 解决您的特定问题例外,我认为从 getChildAt 列表中返回的视图不是 ImageView - 它是您用来保存图像和文本的任何布局视图。

更新以包含相关代码:(根据 @george-stocker 的建议)

这是我使用的适配器:

public class MediaItemAdapter extends ArrayAdapter<MediaItem> {
  private final static String TAG = "MediaItemAdapter";
  private int resourceId = 0;
  private LayoutInflater inflater;
  private Context context;

  private ImageThreadLoader imageLoader = new ImageThreadLoader();

  public MediaItemAdapter(Context context, int resourceId, List<MediaItem> mediaItems) {
    super(context, 0, mediaItems);
    this.resourceId = resourceId;
    inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    this.context = context;
  }

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

    View view;
    TextView textTitle;
    TextView textTimer;
    final ImageView image;

    view = inflater.inflate(resourceId, parent, false);

    try {
      textTitle = (TextView)view.findViewById(R.id.text);
      image = (ImageView)view.findViewById(R.id.icon);
    } catch( ClassCastException e ) {
      Log.e(TAG, "Your layout must provide an image and a text view with ID's icon and text.", e);
      throw e;
    }

    MediaItem item = getItem(position);
    Bitmap cachedImage = null;
    try {
      cachedImage = imageLoader.loadImage(item.thumbnail, new ImageLoadedListener() {
      public void imageLoaded(Bitmap imageBitmap) {
      image.setImageBitmap(imageBitmap);
      notifyDataSetChanged();                }
      });
    } catch (MalformedURLException e) {
      Log.e(TAG, "Bad remote image URL: " + item.thumbnail, e);
    }

    textTitle.setText(item.name);

    if( cachedImage != null ) {
      image.setImageBitmap(cachedImage);
    }

    return view;
  }
}

Praveen -

As you already found my blog post on this, I just wanted to push it back to Stackoverflow so that others can use it.

Here's the basic discussion:
http://ballardhack.wordpress.com/2010/04/05/loading-remote-images-in-a-listview-on-android/

And there's a class I documented later that uses a thread and a callback to load the images:

http://ballardhack.wordpress.com/2010/04/10/loading-images-over-http-on-a-separate-thread-on-android/

Update: To address your specific exception, I think that view returned in the list from getChildAt is not an ImageView -- it's whatever layout view you are using to hold the image and text.

Update to include relevant code: (Per @george-stocker's recommendation)

Here is the adapter I was using:

public class MediaItemAdapter extends ArrayAdapter<MediaItem> {
  private final static String TAG = "MediaItemAdapter";
  private int resourceId = 0;
  private LayoutInflater inflater;
  private Context context;

  private ImageThreadLoader imageLoader = new ImageThreadLoader();

  public MediaItemAdapter(Context context, int resourceId, List<MediaItem> mediaItems) {
    super(context, 0, mediaItems);
    this.resourceId = resourceId;
    inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    this.context = context;
  }

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

    View view;
    TextView textTitle;
    TextView textTimer;
    final ImageView image;

    view = inflater.inflate(resourceId, parent, false);

    try {
      textTitle = (TextView)view.findViewById(R.id.text);
      image = (ImageView)view.findViewById(R.id.icon);
    } catch( ClassCastException e ) {
      Log.e(TAG, "Your layout must provide an image and a text view with ID's icon and text.", e);
      throw e;
    }

    MediaItem item = getItem(position);
    Bitmap cachedImage = null;
    try {
      cachedImage = imageLoader.loadImage(item.thumbnail, new ImageLoadedListener() {
      public void imageLoaded(Bitmap imageBitmap) {
      image.setImageBitmap(imageBitmap);
      notifyDataSetChanged();                }
      });
    } catch (MalformedURLException e) {
      Log.e(TAG, "Bad remote image URL: " + item.thumbnail, e);
    }

    textTitle.setText(item.name);

    if( cachedImage != null ) {
      image.setImageBitmap(cachedImage);
    }

    return view;
  }
}
温柔戏命师 2024-09-10 04:41:51

据我了解,您需要在滚动完成后更新列表。这很容易。这是适合您的固定代码:

EfficientAdapter adapter;

@Override
public void onCreate(Bundle savedInstanceState) {
    mIcon1 = BitmapFactory.decodeResource(this.getResources(),
            R.drawable.icon48x48_1);
    mIcon2 = BitmapFactory.decodeResource(this.getResources(),
            R.drawable.icon48x48_2);
    super.onCreate(savedInstanceState);
    adapter=new EfficientAdapter(this);
    setListAdapter(adapter);
    getListView().setOnScrollListener(this);
}

public void onScroll(AbsListView view, int firstVisibleItem,
    int visibleItemCount, int totalItemCount) {
}

public void onScrollStateChanged(AbsListView view, int scrollState) {
    switch (scrollState) {
    case OnScrollListener.SCROLL_STATE_IDLE:
        mBusy = false;
        adapter.notifyDataSetChanged() 
        break;
    case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
        mBusy = true;
        // mStatus.setText("Touch scroll");
        break;
    case OnScrollListener.SCROLL_STATE_FLING:
        mBusy = true;
        // mStatus.setText("Fling");
        break;
    }
}

notifyDataSetChanged 将告诉适配器重新显示所有可见项目,因此它们将与 image2 一起显示。

As far as I understand you need to update your list after scrolling is finished. That's easy. Here's the fixed code for you:

EfficientAdapter adapter;

@Override
public void onCreate(Bundle savedInstanceState) {
    mIcon1 = BitmapFactory.decodeResource(this.getResources(),
            R.drawable.icon48x48_1);
    mIcon2 = BitmapFactory.decodeResource(this.getResources(),
            R.drawable.icon48x48_2);
    super.onCreate(savedInstanceState);
    adapter=new EfficientAdapter(this);
    setListAdapter(adapter);
    getListView().setOnScrollListener(this);
}

public void onScroll(AbsListView view, int firstVisibleItem,
    int visibleItemCount, int totalItemCount) {
}

public void onScrollStateChanged(AbsListView view, int scrollState) {
    switch (scrollState) {
    case OnScrollListener.SCROLL_STATE_IDLE:
        mBusy = false;
        adapter.notifyDataSetChanged() 
        break;
    case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
        mBusy = true;
        // mStatus.setText("Touch scroll");
        break;
    case OnScrollListener.SCROLL_STATE_FLING:
        mBusy = true;
        // mStatus.setText("Fling");
        break;
    }
}

notifyDataSetChanged will tell the adapter to re-display all visible items, so they'll be displayed with image2.

兲鉂ぱ嘚淚 2024-09-10 04:41:51

据我所知,静态 ViewHolder 没有任何帮助。尝试将整个 onScrollStateChanged 函数放在 /**/ 之间,删除 static ViewHolder 行,然后更改 < code>holder = new ViewHolder(); 到 ViewHolderholder = new ViewHolder();

As far as I can see, the static ViewHolder isn't helping anything. Try putting the entire onScrollStateChanged function between /* and */, removing the static ViewHolder line, and changing holder = new ViewHolder(); to ViewHolder holder = new ViewHolder();.

好多鱼好多余 2024-09-10 04:41:51

啊,检查你的 logcat 以确保你的应用程序没有被终止并重新启动。大多数手机将应用程序总大小限制为 16mb 或 24mb。很容易加载一堆图像,跑过去,被杀死,重新启动,并且让你的 onPause 不加载屏幕外的大数据。这是穷人的垃圾收藏。

Ah, check your logcat to make sure your app isn't being killed and restarted. Most handsets limit your total application size to 16mb or 24mb. It's easy to load up a bunch of images, run over, get killed, restart, and have your onPause not load big data off screen. It's poor man's garabage collection.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文