我在使用自己的Adapter类创建带分隔符的ListView时遇到了一些麻烦。我是Android开发的初学者,所以我真的不能单独修复它。
我想用same layout as seen on this web site创建一个列表视图,我也希望我的项目按字母顺序排列。
所以我创建了两个Adapter,一个用于添加分隔符,另一个用于处理每个项目的特定布局。
类ListeMusicContainer
是按名称按字母顺序排序的ArrayList。
每个人分别完美地工作,但是当我尝试两者时,我得到一个运行时错误。
当应用程序启动时,只有当我尝试滚动时才会出现错误(所以我猜我几乎不错)。
我真的不知道滚动时出现此错误的原因。怎么解决这个问题?
这是我用来创建带分隔符的ListView的适配器
abstract public class MusicAdapter 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 MusicAdapter() {
super();
}
public void addSection(String caption, ItemAdapter 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;
}
return total;
}
public int getItemViewType(int position){
int typeOffset = TYPE_SECTION_HEADER + 1;
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);
}
@Override
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;
}
@Override
public long getItemId(int position){
return position;
}
class Section {
String caption;
ItemAdapter adapter;
Section(String caption, ItemAdapter adapter) {
this.caption = caption;
this.adapter = adapter;
}
}
}
这是我用于每个项目的那个:
public class ItemAdapter extends BaseAdapter{
private ListeMusicContainer<Music> mList;
private LayoutInflater mInflater;
public ItemAdapter(Context context, ListeMusicContainer<Music> musics){
mInflater = LayoutInflater.from(context);
mList = musics;
}
@Override
public int getCount() {
return mList.size();
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null){
convertView = mInflater.inflate(R.layout.list_item, null);
holder = new ViewHolder();
holder.nom = (TextView) convertView.findViewById(R.id.nomAlbum);
holder.genre = (TextView) convertView.findViewById(R.id.genreAlbum);
convertView.setTag(holder);
}
else{
holder = (ViewHolder) convertView.getTag();
}
holder.nom.setText(mList.getItem(position).getNom());
holder.genre.setText(mList.getItem(position).getGenre());
return convertView;
}
static class ViewHolder{
TextView nom;
TextView genre;
}
}
以下是我初始化布局的方法:
public class TestView extends ListActivity {
/** Called when the activity is first created. */
private ListView mListView;
private static String[] items;
private XmlDataParser mParser;
private ListeMusicContainer<Music> mList;
private MusicAdapter mAdapter = new MusicAdapter() {
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);
}
result.setText(caption);
return (result);
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mParser = new XmlDataParser();
mList = mParser.parseXml(this);
ListeMusicContainer<Music> groupe = new ListeMusicContainer<Music>();
String currLetter = null;
for (int i = 0; i < mList.size(); i++){
if (!mList.getItem(i).getLabel().equalsIgnoreCase(currLetter) && currLetter != null){
mAdapter.addSection(mList.getItem(i).getLabel().toUpperCase(), new ItemAdapter(this, groupe));
groupe = new ListeMusicContainer<Music>();
currLetter = mList.getItem(i).getLabel();
}
if (currLetter == null){
currLetter = mList.getItem(i).getLabel();
}
groupe.addData(mList.getItem(i));
}
setListAdapter(mAdapter);
}
}
编辑:在logcat中,这是我在运行应用程序时在logcat中得到的:
I/ActivityManager( 42): Displayed activity com.view/.TestView: 1480 ms (total
1480 ms)
D/dalvikvm( 975): GC_EXTERNAL_ALLOC freed 1214 objects / 78504 bytes in 96ms
D/AndroidRuntime( 975): Shutting down VM
W/dalvikvm( 975): threadid=1: thread exiting with uncaught exception (group=0x4
001d800)
E/AndroidRuntime( 975): FATAL EXCEPTION: main
E/AndroidRuntime( 975): java.lang.NullPointerException
E/AndroidRuntime( 975): at com.view.ItemAdapter.getView(ItemAdapter.java
:51)
E/AndroidRuntime( 975): at com.view.MusicAdapter.getView(Music
Adapter.java:91)
E/AndroidRuntime( 975): at android.widget.AbsListView.obtainView(AbsList
View.java:1294)
E/AndroidRuntime( 975): at android.widget.ListView.makeAndAddView(ListVi
ew.java:1727)
E/AndroidRuntime( 975): at android.widget.ListView.fillDown(ListView.jav
a:652)
E/AndroidRuntime( 975): at android.widget.ListView.fillGap(ListView.java
:623)
E/AndroidRuntime( 975): at android.widget.AbsListView.trackMotionScroll(
AbsListView.java:2944)
E/AndroidRuntime( 975): at android.widget.AbsListView.onTouchEvent(AbsLi
stView.java:2065)
E/AndroidRuntime( 975): at android.widget.ListView.onTouchEvent(ListView
.java:3315)
E/AndroidRuntime( 975): at android.view.View.dispatchTouchEvent(View.jav
a:3766)
E/AndroidRuntime( 975): at android.view.ViewGroup.dispatchTouchEvent(Vie
wGroup.java:897)
E/AndroidRuntime( 975): at android.view.ViewGroup.dispatchTouchEvent(Vie
wGroup.java:936)
E/AndroidRuntime( 975): at android.view.ViewGroup.dispatchTouchEvent(Vie
wGroup.java:936)
E/AndroidRuntime( 975): at android.view.ViewGroup.dispatchTouchEvent(Vie
wGroup.java:936)
E/AndroidRuntime( 975): at com.android.internal.policy.impl.PhoneWindow$
DecorView.superDispatchTouchEvent(PhoneWindow.java:1671)
E/AndroidRuntime( 975): at com.android.internal.policy.impl.PhoneWindow.
superDispatchTouchEvent(PhoneWindow.java:1107)
E/AndroidRuntime( 975): at android.app.Activity.dispatchTouchEvent(Activ
ity.java:2086)
E/AndroidRuntime( 975): at com.android.internal.policy.impl.PhoneWindow$
DecorView.dispatchTouchEvent(PhoneWindow.java:1655)
E/AndroidRuntime( 975): at android.view.ViewRoot.handleMessage(ViewRoot.
java:1785)
E/AndroidRuntime( 975): at android.os.Handler.dispatchMessage(Handler.ja
va:99)
E/AndroidRuntime( 975): at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime( 975): at android.app.ActivityThread.main(ActivityThrea
d.java:4627)
E/AndroidRuntime( 975): at java.lang.reflect.Method.invokeNative(Native
Method)
E/AndroidRuntime( 975): at java.lang.reflect.Method.invoke(Method.java:5
21)
E/AndroidRuntime( 975): at com.android.internal.os.ZygoteInit$MethodAndA
rgsCaller.run(ZygoteInit.java:868)
E/AndroidRuntime( 975): at com.android.internal.os.ZygoteInit.main(Zygot
eInit.java:626)
E/AndroidRuntime( 975): at dalvik.system.NativeStart.main(Native Method)
W/ActivityManager( 42): Force finishing activity com.view/.TestView