2014-11-19 3 views
0

동적 추가/제거 된 머리글 (섹션) 및 관련 사용자 지정 어댑터의 목록보기가 필요하기 때문에 MergeAdapter를 사용하고 있습니다. 새로운 문자열, 사진 또는 비디오 또는 데이터 콘텐츠 그룹을 한 번에 추가하면이 병합 목록에 추가되어 관련 헤더가 표시됩니다. 하지만 문제는 콘텐츠를 추가 할 때 MergeAdapter.getView가 내 사용자 지정 어댑터의 리소스에있는 RelativeLayout이 아닌 TextView를 반환하고이 사용자 지정 어댑터의 뷰에서 Null 값을 가져오고 NullPointerException을 throw합니다. BaseAdapter 코드에서 확장 "CustomContentListAdapter"라는 사용자 정의 어댑터 :MergeAdapter에서 항목을 추가하면 NullPointerException이 발생합니다.

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

    Content content = getItem(position); 

    ///* 
    if(rowView == null) 
    { 
     mCacheView = new CustomListCachedViewHolder();//a view holder 
     rowView = mLayoutInfator.inflate(mResourceId, root, false); 
     mCacheView.mToggleButton = (Button) rowView.findViewById(R.id.toggle_button); 
     mCacheView.mAudioIcon = (ImageView) rowView.findViewById(R.id.audio_icon); 
     mCacheView.mTextInput = (TextView) rowView.findViewById(R.id.content); 
     mCacheView.mThumbnail = (ImageView) rowView.findViewById(R.id.photo_thumbnail); 
     mCacheView.mCreateTimeLabel = (TextView) rowView.findViewById(R.id.created_time); 
     mCacheView.mExpandButton = (ImageView) rowView.findViewById(R.id.expand_button); 
     rowView.setTag(mCacheView); 
    } 
    else 
    { 
     mCacheView = (CustomListCachedViewHolder) rowView.getTag(); 
    } 

    if(View.GONE != mCacheView.mToggleButton.getVisibility() || 
     View.GONE != mCacheView.mAudioIcon.getVisibility()) 
    { 
     mCacheView.mToggleButton.setVisibility(View.GONE); 
     mCacheView.mAudioIcon.setVisibility(View.GONE); 
    } 

    mCacheView.mExpandButton.setOnLongClickListener(new OnLongClickListener() { 

     @Override 
     public boolean onLongClick(View v) { 

      return false; 
     } 
    }); 


    mCacheView.mThumbnail.setImageBitmap(null); 
    mCacheView.mThumbnail.setVisibility(View.GONE); 

    mCacheView.mCreateTimeLabel.setText(""); 
    mCacheView.mNoteEntry.setText(""); 


    return rowView; 
    } 

그리고 그 자원 XML은 :

나는 모든 데이터를 처리하기 위해 조각을 사용
<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_margin="5dp" > 
    <RelativeLayout 
    android:id="@+id/content_list_wrapper" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:padding="5dp"> 
    <RelativeLayout 
     android:id="@+id/detail_content_wrapper" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:padding="5dp">   
     <ImageView 
      android:id="@+id/audio_icon" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:contentDescription="@string/demo_img" 
      android:background="@drawable/audio_thumb" 
      android:layout_centerVertical="true" 
      android:layout_alignParentLeft="true" 
      android:visibility="gone" 
      android:layout_margin="5dp"/> 
     <Button 
      android:id="@+id/toggle_button" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:contentDescription="@string/demo_img" 
      android:layout_centerVertical="true" 
      android:text="@string/dummy_text" 
      android:layout_toRightOf="@id/audio_icon" 
      style="@style/cutomEditTextStyle" 
      android:visibility="visible" 
      android:layout_margin="5dp"/> 
     <ImageView 
      android:id="@+id/photo_thumbnail" 
      android:layout_width="100dp" 
      android:layout_height="100dp" 
      android:contentDescription="@string/demo_img"   
      android:layout_toRightOf="@id/toggle_button" 
      android:visibility="gone" 
      android:layout_margin="5dp"/> 
     <TextView 
      android:id="@+id/note_content" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:layout_toRightOf="@id/photo_thumbnail" 
      android:padding="5dp"/> 

    </RelativeLayout> 
    <LinearLayout 
     android:id="@+id/expand_delete_combo_layout" 
     android:layout_width="wrap_content" 
     android:layout_height="match_parent" 
     android:layout_alignParentRight="true" 
     android:layout_centerVertical="true" 
     android:orientation="horizontal" 
     android:padding="5dp"> 
     <ImageView 
     android:id="@+id/expand_right_button" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:contentDescription="@string/demo_img" 
     android:background="@drawable/ic_ab_forward_holo_light" 
     android:layout_gravity="center_vertical" 
     android:layout_marginRight="10dp"/> 
     <Button 
     android:id="@+id/delete_button" 
      android:layout_width="wrap_content" 
      android:layout_height="match_parent" 
      android:contentDescription="@string/demo_img" 
      android:background="@color/color_red" 
      android:visibility="gone" 
      android:layout_margin="5dp"/> 
    </LinearLayout> 
</RelativeLayout> 
<TextView 
    android:id="@+id/created_time" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_below="@id/content_list_wrapper" 
    android:layout_marginLeft="5dp" 
    android:layout_marginTop="5dp" 
    android:padding="5dp"/> 
</RelativeLayout> 

, 아래 참조하십시오

for(Content content : contents) 
    { 
     List<SubContent> subContents = mContentManager.getListCopy(content.getUUID()); 
     if(!subContents.isEmpty()) 
     { 
      TextView label = (TextView) View.inflate(mContext, 
        R.layout.titlebar_layout, null); 
      label.setText(mContext.getResources().getString(
       R.string.content, content.getSectionNum() + " " + content.getTitle())); 
      mMergeAdapter.addView(label); 
      adapter = new CustomContentListAdapter(
        mContext, R.layout.note_list_item_layout, subContents); 
      mCacheAdapterMap.put(content.getUUID(), adapter); // store existing adapter 
      mMergeAdapter.addAdapter(adapter); 
      mMergetAdapter2.setActive(adapter, true); 
     } 
    } 

    mMergedListView.setDivider(
     mContext.getResources().getDrawable(R.drawable.devider_line)); 
    mMergedListView.setDividerHeight(1); 
    mMergedListView.setAdapter(mMergeAdapter); 
    mMergedListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); 

새 콘텐츠를 추가 할 때 다음과 같이했습니다.

public void notifyNewContentAdded(SubContent subContent) 
    { 
    String id = subContent.getParentId(); 
       CustomContentListAdapter adapter = mCacheAdapterMap.get(id); 
       List<Content> subContents = mContentManager.getCurrentListCopy(id); 

       Content content = mContentManager.getInstance().getCurrentContent(id); 
       String title = ""; 
       if(null == adapter) 
       { 
        TextView label = (TextView) View.inflate(
         mContext, R.layout.titlebar_layout, null); 
        if(content != null) 
        { 
         title = content.getSectionNum() + " " + content.getTitle(); 
        } 
        label.setText(
         mContext.getResources().getString(R.string.content, title)); 
        mMergeAdapter.addView(stepLabel); 
        if(!subContents.contains(subContent)) 
        { 
         subContents.add(subContent); 
        } 
        adapter = new CustomNoteListAdapter(
         mContext, R.layout.list_item_layout, subContents); 

        mCacheAdapterMap.put(id, adapter); 
        mMergeAdapter.addAdapter(noteAdapter); 
        mMergetAdapter.setActive(noteAdapter, true); 

       } 
       else 
       { 
        if(!adapter.contains(subContent)) 
        { 
         adapter.addItem(subContent); 
        } 
        adapter.notifyAdapterChange(); 
       } 

       mMergeAdapter.notifyDataSetChanged(); 
       mMergeAdapter.notifyDataSetInvalidated(); 
} 

MergeAdapter.getView()의 convertView가 내 사용자 지정 어댑터에 위치 할 때 TextView가되는 이유를 모르겠습니다. 그리고 if (rowView == null)를 if (rowView == null || rowView instanceof TextView)로 변경하면 NullPointerException이 사라집니다. 그러나 병합 된 목록보기를 스크롤 할 때 다른 차단기가 튀어 나오게됩니다. ArrayIndexOutOfBoundException를 던집니다. 아래 로그인 정보 : 그것은 확실히 매우 건설적인 조언 감사합니다 것

11-18 13:26:24.687: E/ApplicationErrorHandler(10971): Entered uncaughtException 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): java.lang.ArrayIndexOutOfBoundsException: length=8; index=9 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.widget.AbsListView$RecycleBin.addScrapView(AbsListView.java:8269) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.widget.AbsListView.trackMotionScroll(AbsListView.java:6629) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.widget.AbsListView.scrollIfNeeded(AbsListView.java:3910) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.widget.AbsListView.onTouchMove(AbsListView.java:4762) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.widget.AbsListView.onTouchEvent(AbsListView.java:4590) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.view.View.dispatchTouchEvent(View.java:8135) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2416) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2140) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2422) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2155) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2422) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2155) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2422) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2155) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2422) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2155) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2422) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2155) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2422) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2155) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2422) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2155) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2422) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2155) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2422) 
11-18 13:26:24.687: E/ApplicationErrorHandler(10971): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2155) 

.

+0

MergeAdaper.getView()에서 왜 convertView가 섹션 헤더가 아닌 가장 복잡한 것 인 실제 데이터 행이 아닌 TextView가 될 수 있는지 알 수 없습니다. 실제 행보기는 사용자 정의 리소스 xml에서 팽창되어 부모 ViewGroup, RelativeLayout, LinearLayout 또는 기타를 참조해야합니다. – user3830579

+0

그래서 convertView가 TextView이므로 NullPointerException이 발생합니다. getItemViewType() 및 getViewTypeCount()를 재정의하고 convertView가 TextView 일 때와 View 2 래퍼 인 그룹 래퍼를 구별합니다. 따라서 NullPointerException이 전혀 없습니다. 그러나 새 항목을 추가 할 때 ArrayIndexOutOfBound도 있습니다. – user3830579

답변

0

MergeAdapter.getView()가 내 사용자 정의 어댑터에서 TextView로 convertView를 재활용했는지 확인하지 않았으므로 행 뷰가 null이 아니고 ImageViews, Buttons 및 TextViews가있는 캐시 된 뷰 홀더가 될 수 없습니다. 이 점에서 적절하게 표현된다. getItemViewType() 및 getViewTypeCount()가 있어야한다는 것을 알고 있습니다. 필자는 이것을 수행하여 RelativeLayout과 같은 헤더 텍스트 뷰 또는 외부 래퍼 유형인지 확인하기 위해 몇 가지 조건을 추가했습니다. 처음에는 괜찮아 보이지만 때로는 새 섹션에서 새 내용이 생성되면 MergeAdapter에 새 어댑터가 추가된다는 의미이며 다시 한번 ArrayIndexOutOfBoundException이 될 수 있습니다. 위의 리소스 파일에서 알 수 있듯이 중요한 문제는 listview의 한 행에있는 약간 복잡한 항목의 조합으로 인해 발생해야합니다. 이 시나리오에서는 getViewTypeCount() 및 getItemViewType()을 재정의 할 수 있는지 잘 모르겠습니다. 이 사건에 대한 어떤 생각? 감사.

+0

자식 어댑터에서 새 항목을 추가 한 후 또는 스크롤하는 경우 실제 상황은 어댑터가 ArrayIndexOutOfBoundException을 발생시킵니다. – user3830579

관련 문제