如何使用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条)

保存