AbsListView$RecycleBin.addScrapView() 中的SectionedAdapter ArrayIndexOutOfBoundsException 问题?

发布于 2024-11-08 13:59:06 字数 4990 浏览 6 评论 0原文

我正在使用一个分段适配器,但是我正在尝试修改它,以便使用 if (section.adapter.getCount() > 0) 如果它们为空,则不会出现这些部分。我有以下课程:

abstract public class SectionedAdapter extends BaseAdapter {

abstract protected View getHeaderView(String caption, int index, View convertView, ViewGroup parent);

private List<Section> sections = new ArrayList<Section>(); 
private static int TYPE_SECTION_HEADER = 0; 

public SectionedAdapter() {
    super(); 
}

public void addSection(String caption, Adapter adapter) { 
    sections.add(new Section(caption, adapter)); 
}

public void clear() {
    sections.clear();
    notifyDataSetInvalidated();
}

@Override
public Object getItem(int position) { 

    for (Section section : this.sections) {
        if (section.adapter.getCount() > 0) {

            if (position == 0) {
                return section;
            }

            int size = section.adapter.getCount() + 1;

            if (position < size) {
                return section.adapter.getItem(position - 1);
            }

            position -= size; 
        }
    } 

    return null; 
}

@Override
public int getCount() {
    int total = 0; 
    for (Section section : this.sections) {
        if (section.adapter.getCount() > 0) {
            // Add Header and Section
            total += section.adapter.getCount() + 1;
        }
    }
    return total;
} 

@Override
public int getViewTypeCount() {
    int total = 1; // Add Header
    for (Section section : this.sections) {
        if (section.adapter.getCount() > 0) {
            // Add Sections
            total += section.adapter.getViewTypeCount();
        }
    } 
    return total;
} 

@Override
public int getItemViewType(int position) { 
    int typeOffset = TYPE_SECTION_HEADER + 1;

    for (Section section : this.sections) {
        if (section.adapter.getCount() > 0) {

            if (position == 0) {
                return TYPE_SECTION_HEADER;
            }

            int size = section.adapter.getCount() + 1;

            if (position < size) {
                return (typeOffset + section.adapter.getItemViewType(position - 1));
            }

            position -= size; 
            typeOffset += section.adapter.getViewTypeCount();
        }
    } 

    return Adapter.IGNORE_ITEM_VIEW_TYPE;
}

@Override
public boolean areAllItemsEnabled() { 
    return false; 
}

@Override
public boolean isEnabled(int position) { 
    return (getItemViewType(position) != TYPE_SECTION_HEADER); 
}

@Override
public View getView(int position, View convertView, ViewGroup parent) { 
    int sectionIndex = 0;
    for (Section section : this.sections) {
        if (section.adapter.getCount() > 0) {

            if (position == 0) {
                return getHeaderView(section.caption, sectionIndex, null, parent);
            }

            int size = section.adapter.getCount() + 1;

            if (position < size) {
                return section.adapter.getView(position - 1, null, parent);
            } 

            position -= size;
            sectionIndex++;
        }
    }
    return null; 
} 

@Override
public long getItemId(int position) { 
    return position; 
}

class Section { 
    String caption; 
    Adapter adapter; 

    Section(String caption, Adapter adapter) { 
        this.caption = caption; 
        this.adapter = adapter; 
    } 
}

}

这是有效的,但有时它会因错误而崩溃 AbsListView$RecycleBin.addScrapView() 中的 ArrayIndexOutOfBoundsException

java.lang.ArrayIndexOutOfBoundsException
at android.widget.AbsListView$RecycleBin.addScrapView(AbsListView.java:4186)
at android.widget.ListView.layoutChildren(ListView.java:1572)
at android.widget.AbsListView.onLayout(AbsListView.java:1172)
at android.view.View.layout(View.java:7037)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1249)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1125)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1042)
at android.view.View.layout(View.java:7037)
at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
at android.view.View.layout(View.java:7037)
at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
at android.view.View.layout(View.java:7037)
at android.view.ViewRoot.performTraversals(ViewRoot.java:1054)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1736)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:143)
at android.app.ActivityThread.main(ActivityThread.java:4701)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)

我知道这个错误很可能与 getViewTypeCount() 或 getItemViewType(intposition) 有关,但我无法找出哪里出错了(由于其他 StackOverflow 搜索)。该异常不会可靠地发生,因此我不知道为什么会发生这种情况。我在这里错过了什么吗?

I have a Sectioned Adapter that I am using, however I am trying to modify it so that the sections won't appear if they are empty using if (section.adapter.getCount() > 0). I have the following class:

abstract public class SectionedAdapter extends BaseAdapter {

abstract protected View getHeaderView(String caption, int index, View convertView, ViewGroup parent);

private List<Section> sections = new ArrayList<Section>(); 
private static int TYPE_SECTION_HEADER = 0; 

public SectionedAdapter() {
    super(); 
}

public void addSection(String caption, Adapter adapter) { 
    sections.add(new Section(caption, adapter)); 
}

public void clear() {
    sections.clear();
    notifyDataSetInvalidated();
}

@Override
public Object getItem(int position) { 

    for (Section section : this.sections) {
        if (section.adapter.getCount() > 0) {

            if (position == 0) {
                return section;
            }

            int size = section.adapter.getCount() + 1;

            if (position < size) {
                return section.adapter.getItem(position - 1);
            }

            position -= size; 
        }
    } 

    return null; 
}

@Override
public int getCount() {
    int total = 0; 
    for (Section section : this.sections) {
        if (section.adapter.getCount() > 0) {
            // Add Header and Section
            total += section.adapter.getCount() + 1;
        }
    }
    return total;
} 

@Override
public int getViewTypeCount() {
    int total = 1; // Add Header
    for (Section section : this.sections) {
        if (section.adapter.getCount() > 0) {
            // Add Sections
            total += section.adapter.getViewTypeCount();
        }
    } 
    return total;
} 

@Override
public int getItemViewType(int position) { 
    int typeOffset = TYPE_SECTION_HEADER + 1;

    for (Section section : this.sections) {
        if (section.adapter.getCount() > 0) {

            if (position == 0) {
                return TYPE_SECTION_HEADER;
            }

            int size = section.adapter.getCount() + 1;

            if (position < size) {
                return (typeOffset + section.adapter.getItemViewType(position - 1));
            }

            position -= size; 
            typeOffset += section.adapter.getViewTypeCount();
        }
    } 

    return Adapter.IGNORE_ITEM_VIEW_TYPE;
}

@Override
public boolean areAllItemsEnabled() { 
    return false; 
}

@Override
public boolean isEnabled(int position) { 
    return (getItemViewType(position) != TYPE_SECTION_HEADER); 
}

@Override
public View getView(int position, View convertView, ViewGroup parent) { 
    int sectionIndex = 0;
    for (Section section : this.sections) {
        if (section.adapter.getCount() > 0) {

            if (position == 0) {
                return getHeaderView(section.caption, sectionIndex, null, parent);
            }

            int size = section.adapter.getCount() + 1;

            if (position < size) {
                return section.adapter.getView(position - 1, null, parent);
            } 

            position -= size;
            sectionIndex++;
        }
    }
    return null; 
} 

@Override
public long getItemId(int position) { 
    return position; 
}

class Section { 
    String caption; 
    Adapter adapter; 

    Section(String caption, Adapter adapter) { 
        this.caption = caption; 
        this.adapter = adapter; 
    } 
}

}

This is working however sometimes it will crash with the error
ArrayIndexOutOfBoundsException in AbsListView$RecycleBin.addScrapView()

java.lang.ArrayIndexOutOfBoundsException
at android.widget.AbsListView$RecycleBin.addScrapView(AbsListView.java:4186)
at android.widget.ListView.layoutChildren(ListView.java:1572)
at android.widget.AbsListView.onLayout(AbsListView.java:1172)
at android.view.View.layout(View.java:7037)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1249)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1125)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1042)
at android.view.View.layout(View.java:7037)
at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
at android.view.View.layout(View.java:7037)
at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
at android.view.View.layout(View.java:7037)
at android.view.ViewRoot.performTraversals(ViewRoot.java:1054)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1736)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:143)
at android.app.ActivityThread.main(ActivityThread.java:4701)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)

I know that this error is most likely related to getViewTypeCount() or getItemViewType(int position) but I can't work out where I am going wrong (due to other StackOverflow searches). The exception doesn't occur reliably so I am at a loss to why this would be occurring. Am I missing something here?

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

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

发布评论

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

评论(1

云仙小弟 2024-11-15 13:59:06

如果我没记错的话,您的目标不是在该部分为空时不显示该部分。我认为您在这里应用的条件不会给您带来您想要的结果。

因此,请删除您在SectionedAdapter 中放入的条件。 getHeaderView 这里是抽象方法。但是实现是在其他一些类中编写的,您必须像我一样进行修改。

SectionedAdapter adapter = new SectionedAdapter() {
        protected View getHeaderView(String caption, int index, View convertView, ViewGroup parent) {
            TextView result = (TextView)convertView;

            if (convertView == null) {
                result=(TextView)getLayoutInflater().inflate(R.layout.header, null);
            }
            if(caption != null) {
                result.setText(caption);
            } else {
                result.setVisibility(View.GONE);
            }

            return(result);
        }
    };

如果您不想插入任何部分,则在 addSelection() 方法中传递 null 而不是部分名称。

请看一下我修改后的代码。尝试运行SectionedDemo类

// SectionedDemo class
//----------------------
import android.app.ListActivity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class SectionedDemo extends ListActivity {
    private static String[] items={ "lorem", "ipsum", "dolor", "sit", "amet", "consectetuer", "adipiscing", 
                                    "elit", "morbi", "vel", "ligula", "vitae", "arcu", "aliquet", "mollis", 
                                    "etiam", "vel", "erat", "placerat", "ante", "porttitor", "sodales", 
                                    "pellentesque", "augue", "purus"};

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.main1);

        adapter.addSection(null, new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, items));

        List<String> list = Arrays.asList(items);
        Collections.shuffle(list);
        adapter.addSection(null, new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list));

        list = Arrays.asList(items);
        Collections.shuffle(list);
        adapter.addSection(null, new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list));

        setListAdapter(adapter);
    }

    SectionedAdapter adapter = new SectionedAdapter() {
        protected View getHeaderView(String caption, int index, View convertView, ViewGroup parent) {
            TextView result=(TextView)convertView;

            if (convertView==null) { 
                result=(TextView)getLayoutInflater() .inflate(R.layout.header, null);
            }
            if(caption != null) {
                result.setText(caption);
            } else {
                result.setVisibility(View.GONE);
            }

            return(result);
        }
    };
}

,以下是SectionedAdapter类

//SectionedAdapter class
//-------------------------
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.BaseAdapter;
import java.util.ArrayList;
import java.util.List;

abstract public class SectionedAdapter extends BaseAdapter {
    abstract protected View getHeaderView(String caption, int index, View convertView, ViewGroup parent);

    private List<Section> sections=new ArrayList<Section>();
    private static int TYPE_SECTION_HEADER=0;

    public SectionedAdapter() {
        super();
    }

    public void addSection(String caption, Adapter adapter) {
        sections.add(new Section(caption, adapter));
    }

    public Object getItem(int position) {
        for (Section section : this.sections) {
            if (position==0) {
                return(section);
            }

            int size=section.adapter.getCount()+1;

            if (position<size) {
                return(section.adapter.getItem(position-1));
            }

            position-=size;
        }

        return(null);
    }

    public int getCount() {
        int total = 0;

        for (Section section : this.sections) {
            total += section.adapter.getCount()+1; // add one for header
        }

        return(total);
    }

    public int getViewTypeCount() {
        int total = 1;  // one for the header, plus those from sections

        for (Section section : this.sections) {
            total += section.adapter.getViewTypeCount();
        }

        return(total);
    }

    public int getItemViewType(int position) {
        int typeOffset=TYPE_SECTION_HEADER+1;   // start counting from here

        for (Section section : this.sections) {
            if (position==0) {
                return(TYPE_SECTION_HEADER);
            }

            int size=section.adapter.getCount()+1;

            if (position<size) {
                return(typeOffset+section.adapter.getItemViewType(position-1));
            }

            position-=size;
            typeOffset+=section.adapter.getViewTypeCount();
        }

        return(-1);
    }

    public boolean areAllItemsSelectable() {
        return(false);
    }

    public boolean isEnabled(int position) {
        return(getItemViewType(position)!=TYPE_SECTION_HEADER);
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        int sectionIndex=0;

        for (Section section : this.sections) {

            if (position==0) {
                return(getHeaderView(section.caption, sectionIndex, convertView, parent));
            }

            int size=section.adapter.getCount()+1;

            if (position<size) {
                return(section.adapter.getView(position-1, convertView, parent));
            }

            position-=size;
            sectionIndex++;
        }

        return(null);
    }

    public long getItemId(int position) {
        return(position);
    }

    class Section {
        String caption;
        Adapter adapter;

        Section(String caption, Adapter adapter) {
            this.caption=caption;
            this.adapter=adapter;
        }
    }
}

If I am not wrong, your aim is not to show section if the section is empty. I don't think the condition you have applied here will give you your desire result.

So remove the conditions that you have put in SectionedAdapter. getHeaderView is abstract method here. But implementation is written in some other class there you have to modify as i did.

SectionedAdapter adapter = new SectionedAdapter() {
        protected View getHeaderView(String caption, int index, View convertView, ViewGroup parent) {
            TextView result = (TextView)convertView;

            if (convertView == null) {
                result=(TextView)getLayoutInflater().inflate(R.layout.header, null);
            }
            if(caption != null) {
                result.setText(caption);
            } else {
                result.setVisibility(View.GONE);
            }

            return(result);
        }
    };

If you don't want to insert any section then in addSelection() method pass null instead of section name.

Please have a look on my modified code. try to run SectionedDemo class

// SectionedDemo class
//----------------------
import android.app.ListActivity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class SectionedDemo extends ListActivity {
    private static String[] items={ "lorem", "ipsum", "dolor", "sit", "amet", "consectetuer", "adipiscing", 
                                    "elit", "morbi", "vel", "ligula", "vitae", "arcu", "aliquet", "mollis", 
                                    "etiam", "vel", "erat", "placerat", "ante", "porttitor", "sodales", 
                                    "pellentesque", "augue", "purus"};

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.main1);

        adapter.addSection(null, new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, items));

        List<String> list = Arrays.asList(items);
        Collections.shuffle(list);
        adapter.addSection(null, new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list));

        list = Arrays.asList(items);
        Collections.shuffle(list);
        adapter.addSection(null, new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list));

        setListAdapter(adapter);
    }

    SectionedAdapter adapter = new SectionedAdapter() {
        protected View getHeaderView(String caption, int index, View convertView, ViewGroup parent) {
            TextView result=(TextView)convertView;

            if (convertView==null) { 
                result=(TextView)getLayoutInflater() .inflate(R.layout.header, null);
            }
            if(caption != null) {
                result.setText(caption);
            } else {
                result.setVisibility(View.GONE);
            }

            return(result);
        }
    };
}

And the following is SectionedAdapter class

//SectionedAdapter class
//-------------------------
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.BaseAdapter;
import java.util.ArrayList;
import java.util.List;

abstract public class SectionedAdapter extends BaseAdapter {
    abstract protected View getHeaderView(String caption, int index, View convertView, ViewGroup parent);

    private List<Section> sections=new ArrayList<Section>();
    private static int TYPE_SECTION_HEADER=0;

    public SectionedAdapter() {
        super();
    }

    public void addSection(String caption, Adapter adapter) {
        sections.add(new Section(caption, adapter));
    }

    public Object getItem(int position) {
        for (Section section : this.sections) {
            if (position==0) {
                return(section);
            }

            int size=section.adapter.getCount()+1;

            if (position<size) {
                return(section.adapter.getItem(position-1));
            }

            position-=size;
        }

        return(null);
    }

    public int getCount() {
        int total = 0;

        for (Section section : this.sections) {
            total += section.adapter.getCount()+1; // add one for header
        }

        return(total);
    }

    public int getViewTypeCount() {
        int total = 1;  // one for the header, plus those from sections

        for (Section section : this.sections) {
            total += section.adapter.getViewTypeCount();
        }

        return(total);
    }

    public int getItemViewType(int position) {
        int typeOffset=TYPE_SECTION_HEADER+1;   // start counting from here

        for (Section section : this.sections) {
            if (position==0) {
                return(TYPE_SECTION_HEADER);
            }

            int size=section.adapter.getCount()+1;

            if (position<size) {
                return(typeOffset+section.adapter.getItemViewType(position-1));
            }

            position-=size;
            typeOffset+=section.adapter.getViewTypeCount();
        }

        return(-1);
    }

    public boolean areAllItemsSelectable() {
        return(false);
    }

    public boolean isEnabled(int position) {
        return(getItemViewType(position)!=TYPE_SECTION_HEADER);
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        int sectionIndex=0;

        for (Section section : this.sections) {

            if (position==0) {
                return(getHeaderView(section.caption, sectionIndex, convertView, parent));
            }

            int size=section.adapter.getCount()+1;

            if (position<size) {
                return(section.adapter.getView(position-1, convertView, parent));
            }

            position-=size;
            sectionIndex++;
        }

        return(null);
    }

    public long getItemId(int position) {
        return(position);
    }

    class Section {
        String caption;
        Adapter adapter;

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