如何使用Picasso库正确实现带图像的自定义列表视图?

如何使用Picasso库正确实现带图像的自定义列表视图?,第1张

概述我创建了一个自定义列表视图布局,其中包含从Web加载的图像,如下所示:http://i.stack.imgur.com/l8ZOc.png向下滚动时工作正常.但是,当您向下滚动时,之前的项目将从屏幕中移出然后销毁.当你再次尝试向上滚动时,它会再次被加载(从缓存,更快但不是即时),这会导致延迟并且它不应该流畅

我创建了一个自定义列表视图布局,其中包含从Web加载的图像,如下所示:

http://i.stack.imgur.com/l8ZOc.png

向下滚动时工作正常.但是,当您向下滚动时,之前的项目将从屏幕中移出然后销毁.当你再次尝试向上滚动时,它会再次被加载(从缓存,更快但不是即时),这会导致延迟并且它不应该流畅.

1.有一个如何正确做到这一点的例子吗?
2.有没有办法防止列表视图项目在屏幕外被销毁?
3.如果是这样,是否会因为保留太多物品而导致问题?

贝娄是我的代码:

MenuAdapter:

public class MenuAdapter extends BaseAdapter{    Context context;    List<MyMenuItem> menuItems;    MenuAdapter(Context context, List<MyMenuItem> menuItems) {        this.context = context;        this.menuItems = menuItems;    }    @OverrIDe    public int getCount() {        return menuItems.size();    }    @OverrIDe    public Object getItem(int position) {        return menuItems.get(position);    }    @OverrIDe    public long getItemID(int position) {        return menuItems.indexOf(getItem(position));    }    private class VIEwHolder {        ImageVIEw ivMenu;        TextVIEw tvMenuheader;    }    @OverrIDe    public VIEw getVIEw(int position, VIEw convertVIEw, VIEwGroup parent) {        VIEwHolder holder = null;        LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);        if (convertVIEw == null) {            convertVIEw = mInflater.inflate(R.layout.menu_item, null);            holder = new VIEwHolder();            holder.tvMenuheader = (TextVIEw) convertVIEw.findVIEwByID(R.ID.tvMenuheader);            holder.ivMenu = (ImageVIEw) convertVIEw.findVIEwByID(R.ID.ivMenuItem);            convertVIEw.setTag(holder);        } else {            holder = (VIEwHolder) convertVIEw.getTag();        }        MyMenuItem row_pos = menuItems.get(position);        Picasso.with(context)                .load(row_pos.getItem_image_url())                .into(holder.ivMenu);        holder.tvMenuheader.setText(row_pos.getItem_header());        Log.e("Test", "headers:" + row_pos.getItem_header());        return convertVIEw;    }}

MyMenuItem:

public class MyMenuItem {    private String item_header;    private String item_image_url;    public MyMenuItem(String item_header, String item_image_url){        this.item_header=item_header;        this.item_image_url=item_image_url;    }    public String getItem_header(){        return item_header;    }    public voID setItem_header(String item_header){        this.item_header=item_header;    }    public String getItem_image_url(){        return item_image_url;    }    public voID setItem_image_url(String item_image_url){        this.item_image_url=item_image_url;    }}

主要活动:

public class MyActivity extends Activity implements AdapterVIEw.OnItemClickListener {    List<MyMenuItem> menuItems;    ListVIEw myListVIEw;    JsONArray JsonArray;    @OverrIDe    protected voID onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentVIEw(R.layout.activity_my);        Bundle extras = getIntent().getExtras();        if(extras!=null){            try{                JsonArray = new JsONArray(extras.getString("Data"));            }catch (Exception e){                e.printstacktrace();            }        }        menuItems = new ArrayList<MyMenuItem>();        for (int i = 0; i < JsonArray.length(); i++) {            try {                MyMenuItem item = new MyMenuItem(JsonArray.getJsONObject(i).getString("Title"), JsonArray.getJsONObject(i).getString("imageURL"));                menuItems.add(item);            }catch (Exception e){                e.printstacktrace();            }        }        myListVIEw = (ListVIEw) findVIEwByID(R.ID.List);        MenuAdapter adapter = new MenuAdapter(this, menuItems);        myListVIEw.setAdapter(adapter);        myListVIEw.setonItemClickListener(this);    }}

MenuItem.xml:

<relativeLayout xmlns:androID="http://schemas.androID.com/apk/res/androID"    androID:layout_wIDth="match_parent"    androID:layout_height="match_parent">    <ImageVIEw        androID:ID="@+ID/ivMenuItem"        androID:layout_wIDth="match_parent"        androID:layout_height="wrap_content"        androID:scaleType="center"        androID:src="@drawable/em" />    <TextVIEw        androID:ID="@+ID/tvMenuheader"        androID:layout_wIDth="match_parent"        androID:layout_height="wrap_content"        androID:background="#55000000"        androID:paddingBottom="15dp"        androID:paddingleft="10dp"        androID:paddingRight="10dp"        androID:paddingtop="15dp"        androID:textcolor="@androID:color/white"        androID:layout_gravity="left|top"        androID:layout_alignBottom="@+ID/ivMenuItem"        androID:layout_alignParentleft="true"        androID:layout_alignParentStart="true"        androID:layout_alignParentRight="true"        androID:layout_alignParentEnd="true" /></relativeLayout>

解决方法:

1.有没有一个如何正确做到这一点的例子?

您的代码看起来非常接近完美. Adapter的getVIEw方法通常是优化的关键途径.比较毕加索自己的例子SampleListDetailAdapter.java.重要的一点(以及你的代码)

>检查&重新使用已经膨胀的观点,通货膨胀是昂贵的.
>使用VIEwHolder,这样您就不必每次都调用findVIEwByID.在简单的视图上并不是非常昂贵.也缓存了afaik.
> Picasso.with(context).load(url)…每次需要显示图像时.这应该立即完成,但仍然使用缓存和其他魔法.

您可以添加一些小的优化,但我怀疑有明显的甚至可衡量的变化:

纯样式更改:使用BaseAdapter#getItem(position).这种方法
   只为你而存在.框架不使用它.

   @OverrIDe   public MyMenuItem getItem(int position) { // << subclasses can use subtypes in overrIDden methods!       return menuItems.get(position);   }   @OverrIDe   public VIEw getVIEw(int position, VIEw convertVIEw, VIEwGroup parent) {       ...       MyMenuItem row_pos = getItem(position);

使用理智的ID方法

@OverrIDepublic long getItemID(int position) {    return menuItems.indexOf(getItem(position));}

相当于

@OverrIDepublic long getItemID(int position) {    return position;}

但现在无限快. indexOf(Object)与对象数量的关系非常严重.

缓存不更改的对象:

MenuAdapter(Context context, List<MyMenuItem> menuItems) {    this.mLayoutInflater = LayoutInflater.from(content);    this.mPicasso = Picasso.with(context);}..@OverrIDepublic VIEw getVIEw(int position, VIEw convertVIEw, VIEwGroup parent) {    if (convertVIEw == null) {        convertVIEw = mInflater.inflate(R.layout.menu_item, null);    ...    mPicasso            .load(row_pos.getItem_image_url())            .into(holder.ivMenu);

2.有没有办法阻止列表视图项目在屏幕外被销毁?

没有(*).

..(*)你可以基本上缓存getVIEw的结果,例如在LruCache(位置,视图)或LruCache(MyMenuItem,VIEw)中,然后不要触摸convertVIEw – 它们需要保持未转换状态,否则您将在缓存中终止这些视图.也

@OverrIDepublic int getItemVIEwType(int position) {    return Adapter.IGnorE_ITEM_VIEW_TYPE;}

似乎是必需的,因为使用代码的标准适配器假定它从可见性中删除的视图消失了.他们不是和他们搞乱你的缓存混乱,并为我造成了奇怪的显示问题.

3.如果是这样,是否会因为保留太多物品而导致问题?

是.此行为不是意图/预期.你或多或少都没有获得.您可以保存对holder.tvMenuheader.setText()的调用.同样是毕加索的一个,但他们两个都应该立即完成.毕加索应该已经缓存了你的图像.通过缓存所有视图,您实际上添加了另一个包含所有图像的缓存.我宁愿检查毕加索缓存是否按预期工作并保存大部分项目.您可能希望使用视图缓存执行此操作的唯一原因是需要复杂设置视图的情况,因此值得缓存完全构造的视图而不仅仅是某些内容部分.

轮廓

分析实际上可以告诉您可以/需要/应该改进的地方.第一个看IMO的是tracevIEw.您将看到代码是否阻止主线程导致乱序列表滚动.如果您正在执行复杂的视图,并且您发现绘制方法大多数时间都在执行,那么也要对它们进行概要分析.

> http://www.curious-creature.org/docs/android-performance-case-study-1.html
> http://blog.venmo.com/hf2t3h4x98p5e13z82pl8j66ngcmry/performance-tuning-on-android
> http://www.vogella.com/tutorials/AndroidTools/article.html

总结

以上是内存溢出为你收集整理的如何使用Picasso库正确实现带图像的自定义列表视图?全部内容,希望文章能够帮你解决如何使用Picasso库正确实现带图像的自定义列表视图?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:http://outofmemory.cn/web/1115659.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-29
下一篇2022-05-29

发表评论

登录后才能评论

评论列表(0条)

    保存