Horizo​​ntalScrollView:CustomAdapter与getView()不喜欢重复使用的ListView convertViews [英] HorizontalScrollView: CustomAdapter with getView() doesn't reuse convertViews like ListView

查看:328
本文介绍了Horizo​​ntalScrollView:CustomAdapter与getView()不喜欢重复使用的ListView convertViews的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我过去的项目之一,我实现了时间选取旋转木马。它是基于一个 Horizo​​ntalScrollView 。用户可以选择一个时间,而滚动的这一观点。时间值计算的X偏移的 Horizo​​ntalScrollView

我想分享在github上这个项目,但在清理code,我意识到一些的糟糕表现的问题。

Horizo​​ntalScrollView 填充了一个自定义的 ArrayAdapter 。在 getView()使用 convertView 。我想这可能是一个的ListView 中的适配器,所以才有了可见的项目呈现,如果他们将被销毁重用工作。相反,所有项目都呈现! (在我的情况1008!)我加入他们自己(在code例如#1),但即使我尝试删除(和回收)添加量少,逻辑旧的不工作,还是我错过了什么?

因此​​,我的基本问题是:我有什么改变,使我的适配器行为像的ListView


  1. 我发现<一个href=\"http://stackoverflow.com/questions/19020114/how-to-implement-view-recycling-mechanism-for-pager-adapter\">this所以链接,并试图重写删除的功能,但是这是从来没有所谓的(不知何故逻辑,因为我只需要添加)

  2. 有一个很好的 PagerAdapter例如就职于github上,但不知何故,我无法翻译这 ArrayAdapter&LT;串GT;

任何想法,链接,欢迎!

和请不要建议使用的ListView 来代替。我们决定使用 Horizo​​ntalScrollView ,因为回调,我们已经有一个的ListView 在布局的事实。

Horizo​​ntalScrollView

  InfiniteTimeScrubberHorizo​​ntalView延伸Horizo​​ntalScrollView {
...
公共无效setAdapter(上下文的背景下,TimeScrubberListAdapter mAdapter){
    this.mAdapter = mAdapter;
    尝试{
        fillViewWithAdapter(mAdapter);
    }赶上(ZeroChildException E){
        e.printStackTrace();
    }
}私人无效fillViewWithAdapter(TimeScrubberListAdapter mAdapter){
    // ...    的ViewGroup父=(的ViewGroup)getChildAt(0);
    parent.removeAllViews();
    的for(int i = 0; I&LT; mAdapter.getCount();我++){
        //#1:这里:ALL视图中添加
        parent.addView(mAdapter.getView(I,空,父母));
    }
}

Adpater

 公共类TimeScrubberListAdapter扩展ArrayAdapter&LT;串GT; {// ...
私人的ArrayList&LT;串GT;清单; //列表0:00,0:30 ...... 23:00,23:30
最终静态INT MAXIMUM_DAYS = 21@覆盖
公众诠释的getCount(){
    返回则为list.size()* MAXIMUM_DAYS;
}@覆盖
公共字符串的getItem(INT位置){
    返回list.get(位置%则为list.size());
}@覆盖
公共查看getView(最终诠释的立场,观点convertView,父母的ViewGroup){
    RelativeLayout的布局;    如果(convertView == NULL){
        布局=(RelativeLayout的)View.inflate(背景下,layoutId,NULL);
        持有人=新的持有人();
        holder.title =(TextView中)layout.findViewById(R.id.epg_item_text);
        layout.setTag(保持器);
    }其他{
        布局=(RelativeLayout的)convertView;
        鉴于=布局;
        支架=(座)layout.getTag();
    }    layout.setLayoutParams(MLP);    字符串TIMEVALUE =的getItem(位置);
    holder.title.setText(TIMEVALUE);    返回布局;
}
// ...
@覆盖
公共无效删除(String对象){
    //不叫......一些如何逻辑,因为我不删除的项
    super.remove(对象);
}


解决方案

我想,也许你​​混淆其中的逻辑在于用于查看和适配器之间的渲染。使用适配器不会引起视图回收行为。这是的ListView 本身,与其父一起, AbsListView ,即实现视图回收行为。该适配器是由的ListView ,以便正确地填充被显示在屏幕上根据需要查看必需的,但其访​​问量为实际选择的逻辑来显示和何时以及如何回收这些观点是不是在适配器的。

如果你看一下源$ C ​​$ C的<一个href=\"https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/widget/HorizontalScrollView.java\"><$c$c>HorizontalScrollView和<一个href=\"https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/widget/ListView.java\"><$c$c>ListView,你会看到,他们是截然不同的。他们不只是在不同的方向是一样的。

因此​​,长期和短期的是,你将无法得到你通过使用 Horizo​​ntalScrollView ,甚至一个简单的后代寻找视图回收。如果你想查看回收,你将不得不寻找或建立实现视图回收行为的自定义视图。快速谷歌的Android的水平列表视图应该给你一个很好的起点。

In one of my past projects I implemented a "Time Picker Carousel". It is based on a HorizontalScrollView. The user can pick a time while scrolling this view. The time value is calculated from the X-Offset of the HorizontalScrollView.

I wanted to share this project at github, but while cleaning up the code I realized some bad performance issue.

The HorizontalScrollView is populated with a custom ArrayAdapter. The getView() uses a Holder for the convertView. I thought it might work as an adapter within a ListView, so only the visible items are rendered and reused if they will be destroyed. Instead, all items are rendered!!! (in my case 1008!) I add them myself (#1 in Code example), but even if I try to add less, the logic from remove (and recycle) old ones doesn't work, or did I miss something?

So my basic question is: What do I have to change to make my adapter behave like ListView?

  1. I found this so link and tried overriding remove function, but this is never called (somehow logic, because i am only adding)
  2. There's a good PagerAdapter example at github, but somehow I cannot translate this to ArrayAdapter<String>

Any thoughts, links are welcome!

And please don't suggest using ListView instead. We decided to use HorizontalScrollView because of callbacks and the fact we already have a ListView in the layout.

HorizontalScrollView

InfiniteTimeScrubberHorizontalView extends HorizontalScrollView{
...
public void setAdapter(Context context, TimeScrubberListAdapter mAdapter) {
    this.mAdapter = mAdapter;
    try {
        fillViewWithAdapter(mAdapter);
    } catch (ZeroChildException e) {
        e.printStackTrace();
    }
}

private void fillViewWithAdapter(TimeScrubberListAdapter mAdapter) {
    //...

    ViewGroup parent = (ViewGroup) getChildAt(0);
    parent.removeAllViews();
    for (int i = 0; i < mAdapter.getCount(); i++) {
        //#1: Here: ALL views are added
        parent.addView(mAdapter.getView(i, null, parent));   
    }
}

Adpater

public class TimeScrubberListAdapter extends ArrayAdapter<String> {

//...
private ArrayList<String> list;  //list from 0:00,0:30...23:00,23:30
final static int MAXIMUM_DAYS = 21

@Override
public int getCount() {
    return list.size() * MAXIMUM_DAYS;
}

@Override
public String getItem(int position) {
    return list.get(position % list.size());
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    RelativeLayout layout;

    if (convertView == null) {
        layout = (RelativeLayout) View.inflate(context, layoutId, null);
        holder = new Holder();
        holder.title = (TextView) layout.findViewById(R.id.epg_item_text);
        layout.setTag(holder);
    } else {
        layout = (RelativeLayout) convertView;
        view = layout;
        holder = (Holder) layout.getTag();
    }

    layout.setLayoutParams(mLP);        

    String timeValue = getItem(position);
    holder.title.setText(timeValue);            

    return layout;
}
//...
@Override
public void remove(String object) {
    //not called...some how logic, because i do not remove an item
    super.remove(object);    
}

解决方案

I think maybe you are confusing where the logic lies for rendering between View and Adapter. Using an Adapter does not cause view recycling behavior. It is the ListView itself, along with its parent, AbsListView, that implement the view recycling behavior. The Adapter is required by the ListView in order to properly populate the Views that are shown on screen as needed, but the logic for actually choosing which Views to display and when and how to recycle those views is not in the Adapter at all.

If you look at the source code for HorizontalScrollView and for ListView, you will see that they are dramatically different. They are not just the same thing in different orientations.

So, the long and short of it is that you will not be able to get the view recycling that you are looking for by using a HorizontalScrollView or even a simple descendent. If you want view recycling, you will have to look for or build a custom View that implements the view recycling behavior. A quick google for 'android horizontal listview' should give you a good starting point.

这篇关于Horizo​​ntalScrollView:CustomAdapter与getView()不喜欢重复使用的ListView convertViews的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆