2013-10-23 5 views
2

어댑터의 getView 메소드 내부에서 position 변수에 이상한 문제가 있습니다. 4 개의보기 유형 중 4 개는 내부에 버튼이 있습니다. 이 버튼은 서비스에 메시지를 보내고 (서비스에서 비동기적인 것을 유발할 수 있음),이 어댑터는 서비스에 의해 유발 된 notifyDataSetChanged()를 가져옵니다.BaseAdapter의 getView 위치가 잘못되었습니다.

메시지를 보내는 버튼을 스팸하면 문제가 발생합니다. 만약 내가 충분히 빨리 스팸, 잘못된 위치는 서비스로 전송됩니다. 문제는 스팸 중에 notifyDataSetChanged() 중에 버튼을 누르는 것입니다. 서비스에서 사용하는 메소드에 대한 호출에 주석을 달면이 불일치가 발생하지 않기 때문입니다.

이 내가 BaseAdapter를 처음 사용하고, 나는이 좋은 자습서 다음 : 다음은 내가 문제를 정확하게 지적 관련 될 수 있다고 생각 코드 부분은 Base Adapter Tutorial

합니다.

Theres는 6 개 개의 상이한 뷰 유형이 어댑터에 의해 관리되고 :

private static final int MAX_COUNT = 6; 

그리고 여기 방법 IM 재정의 :

@Override 
    public int getViewTypeCount() { 
     return MAX_COUNT; 
    } 

    @Override 
    public int getCount() { 
     return data.size(); 
    } 

    @Override 
    public ListViewDataItem getItem(int position) { 
     return data.get(position); 
    } 

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

    @Override 
    public int getItemViewType(int position) { 
     return getItem(position).getType(); 
    } 

그리고을 heres의 getView 방법 :

@Override 
    public View getView(final int position, View convertView, ViewGroup parent) { 
//  Thread.currentThread().setContextClassLoader(MyParcelableFile.class.getClassLoader()); 
     View row = convertView; 
     StandardFolderViewHolder standardFolderViewHolder = null; 
     StandardFileViewHolder standardFileViewHolder = null; 
     MusicFileStoppedViewHolder musicFileStoppedHolder = null; 
     MusicFilePlayingViewHolder musicFilePlayingHolder = null; 
     MusicFolderStoppedViewHolder musicFolderStoppedHolder = null; 
     MusicFolderPlayingViewHolder musicFolderPlayingHolder = null; 

     switch(getItemViewType(position)) { 
     case Constants.MEDIA_FILE.TYPE.STANDARD_DIRECTORY: 
      if(row == null) { 
       standardFolderViewHolder = new StandardFolderViewHolder(); 
       row = inflater.inflate(R.layout.listview_mixed_folder_row, parent, false); 
       standardFolderViewHolder.icon = (ImageView)row.findViewById(R.id.filetype_icon); 
       standardFolderViewHolder.tempTV = (TextView)row.findViewById(R.id.listview_mixed_folder_row_test_tv); 
       row.setTag(standardFolderViewHolder); 
      } 
      else { 
       standardFolderViewHolder = (StandardFolderViewHolder)row.getTag(); 
      } 
      standardFolderViewHolder.icon.setImageDrawable(getItem(position).getDrawable()); 
      standardFolderViewHolder.tempTV.setText(getItem(position).getName()); 
      standardFolderViewHolder.tempTV.setSelected(true); 
      break; 
     case Constants.MEDIA_FILE.TYPE.MUSIC_DIRECTORY: 
      if(getItemViewState(position) == Constants.MEDIA_FILE.TYPE.STATE.PLAYING) { 
       if(row == null || (row !=null && row.getTag() instanceof MusicFolderStoppedViewHolder)) { 
        musicFolderPlayingHolder = new MusicFolderPlayingViewHolder(); 
        row = inflater.inflate(R.layout.listview_music_folder_playing_row, parent, false); 
        musicFolderPlayingHolder.icon = (ImageView)row.findViewById(R.id.filetype_icon); 
        musicFolderPlayingHolder.songName = (TextView)row.findViewById(R.id.row_title_tv); 
        musicFolderPlayingHolder.playButton = (Button)row.findViewById(R.id.row_play_button); 
        musicFolderPlayingHolder.durationTV = (TextView)row.findViewById(R.id.row_duration_tv); 
        musicFolderPlayingHolder.progressBar = (ProgressBar)row.findViewById(R.id.folder_progress_bar); 
        row.setTag(musicFolderPlayingHolder); 
       } 
       else { 
        musicFolderPlayingHolder = (MusicFolderPlayingViewHolder)row.getTag(); 
       } 
       musicFolderPlayingHolder.icon.setImageDrawable(getItem(position).getDrawable()); 
       musicFolderPlayingHolder.songName.setText(getItem(position).getName()); 
       musicFolderPlayingHolder.songName.setSelected(true); 
       musicFolderPlayingHolder.durationTV.setText(mActivity.formattedMillis(getItem(position).getDuration())); 
       musicFolderPlayingHolder.progressBar.setMax(getItem(position).getDuration()); 
       musicFolderPlayingHolder.progressBar.setProgress(getItem(position).getProgress()); 
       musicFolderPlayingHolder.playButton.setOnClickListener(new OnClickListener() { 

        @Override 
        public void onClick(View arg0) { 
         Log.e("clicked", getItem(position).getName()); 
         Bundle bun = new Bundle(); 
         bun.putString(Constants.BUNDLE_KEYS.PLAY_FILES, getItem(position).getPath()); 
         Message message = Message.obtain(null, Constants.OP_CODE.PLAY_FILES); 
         message.setData(bun); 
         try { 
          mActivity.mService.send(message); 
         } 
         catch (RemoteException re) { 
          re.printStackTrace(); 
         } 
        } 

       }); 
      } 
      else if(getItemViewState(position) == Constants.MEDIA_FILE.TYPE.STATE.STOPPED) { 
       if(row == null || (row !=null && row.getTag() instanceof MusicFolderPlayingViewHolder)) { 
        musicFolderStoppedHolder = new MusicFolderStoppedViewHolder(); 
        row = inflater.inflate(R.layout.listview_music_folder_stopped_row, parent, false); 
        musicFolderStoppedHolder.icon = (ImageView)row.findViewById(R.id.filetype_icon); 
        musicFolderStoppedHolder.songName = (TextView)row.findViewById(R.id.row_title_tv); 
        musicFolderStoppedHolder.playButton = (Button)row.findViewById(R.id.row_play_button); 
        musicFolderStoppedHolder.durationTV = (TextView)row.findViewById(R.id.row_duration_tv); 
        row.setTag(musicFolderStoppedHolder); 
       } 
       else { 
        musicFolderStoppedHolder = (MusicFolderStoppedViewHolder)row.getTag(); 
       } 
       musicFolderStoppedHolder.icon.setImageDrawable(getItem(position).getDrawable()); 
       musicFolderStoppedHolder.songName.setText(getItem(position).getName()); 
       musicFolderStoppedHolder.songName.setSelected(true); 
       musicFolderStoppedHolder.durationTV.setText(mActivity.formattedMillis(getItem(position).getDuration())); 
       musicFolderStoppedHolder.playButton.setOnClickListener(new OnClickListener() { 

        @Override 
        public void onClick(View arg0) { 
         Log.e("clicked", getItem(position).getName()); 
         Bundle bun = new Bundle(); 
         bun.putString(Constants.BUNDLE_KEYS.PLAY_FILES, getItem(position).getPath()); 
         Message message = Message.obtain(null, Constants.OP_CODE.PLAY_FILES); 
         message.setData(bun); 
         try { 
          mActivity.mService.send(message); 
         } 
         catch (RemoteException re) { 
          re.printStackTrace(); 
         } 
        } 

       }); 
      } 
      break; 
     case Constants.MEDIA_FILE.TYPE.STANDARD_FILE: 
      if(row == null) { 
       standardFileViewHolder = new StandardFileViewHolder(); 
       row = inflater.inflate(R.layout.listview_mixed_folder_row, parent, false); 
       standardFileViewHolder.icon = (ImageView)row.findViewById(R.id.filetype_icon); 
       standardFileViewHolder.tempTV = (TextView)row.findViewById(R.id.listview_mixed_folder_row_test_tv); 
       row.setTag(standardFileViewHolder); 
      } 
      else { 
       standardFileViewHolder = (StandardFileViewHolder)row.getTag(); 
      } 
      standardFileViewHolder.icon.setImageDrawable(getItem(position).getDrawable()); 
      standardFileViewHolder.tempTV.setText(getItem(position).getName()); 
      standardFileViewHolder.tempTV.setSelected(true); 
      break; 
     case Constants.MEDIA_FILE.TYPE.MUSIC_FILE: 
      if(getItemViewState(position) == Constants.MEDIA_FILE.TYPE.STATE.PLAYING) { 
       if(row == null || (row !=null && row.getTag() instanceof MusicFileStoppedViewHolder)) { 
        musicFilePlayingHolder = new MusicFilePlayingViewHolder(); 
        row = inflater.inflate(R.layout.listview_music_file_playing_row, parent, false); 
        musicFilePlayingHolder.icon = (ImageView)row.findViewById(R.id.filetype_icon); 
        musicFilePlayingHolder.songName = (TextView)row.findViewById(R.id.row_title_tv); 
        musicFilePlayingHolder.playButton = (Button)row.findViewById(R.id.row_play_button); 
        musicFilePlayingHolder.durationTV = (TextView)row.findViewById(R.id.row_duration_tv); 
        musicFilePlayingHolder.progressBar = (ProgressBar)row.findViewById(R.id.folder_progress_bar); 
        row.setTag(musicFilePlayingHolder); 
       } 
       else { 
        musicFilePlayingHolder = (MusicFilePlayingViewHolder)row.getTag(); 
       } 
       musicFilePlayingHolder.icon.setImageDrawable(getItem(position).getDrawable()); 
       musicFilePlayingHolder.songName.setText(getItem(position).getName()); 
       musicFilePlayingHolder.songName.setSelected(true); 
       musicFilePlayingHolder.durationTV.setText(mActivity.formattedMillis(getItem(position).getDuration())); 
       musicFilePlayingHolder.progressBar.setMax(getItem(position).getDuration()); 
       musicFilePlayingHolder.progressBar.setProgress(getItem(position).getProgress()); 
       musicFilePlayingHolder.playButton.setOnClickListener(new OnClickListener() { 

        @Override 
        public void onClick(View arg0) { 
         Log.e("clicked", getItem(position).getName()); 
         Bundle bun = new Bundle(); 
         bun.putString(Constants.BUNDLE_KEYS.PLAY_FILES, getItem(position).getPath()); 
         Message message = Message.obtain(null, Constants.OP_CODE.PLAY_FILES); 
         message.setData(bun); 
         try { 
          mActivity.mService.send(message); 
         } 
         catch (RemoteException re) { 
          re.printStackTrace(); 
         } 
        } 

       }); 
      } 
      else if(getItemViewState(position) == Constants.MEDIA_FILE.TYPE.STATE.STOPPED) { 
       if(row == null || (row !=null && row.getTag() instanceof MusicFilePlayingViewHolder)) { 
        musicFileStoppedHolder = new MusicFileStoppedViewHolder(); 
        row = inflater.inflate(R.layout.listview_music_file_stopped_row, parent, false); 
        musicFileStoppedHolder.icon = (ImageView)row.findViewById(R.id.filetype_icon); 
        musicFileStoppedHolder.songName = (TextView)row.findViewById(R.id.row_title_tv); 
        musicFileStoppedHolder.playButton = (Button)row.findViewById(R.id.row_play_button); 
        musicFileStoppedHolder.durationTV = (TextView)row.findViewById(R.id.row_duration_tv); 

        row.setTag(musicFileStoppedHolder); 
       } 
       else { 
        musicFileStoppedHolder = (MusicFileStoppedViewHolder)row.getTag(); 
       } 
       musicFileStoppedHolder.icon.setImageDrawable(getItem(position).getDrawable()); 
       musicFileStoppedHolder.songName.setText(getItem(position).getName()); 
       musicFileStoppedHolder.songName.setSelected(true); 
       musicFileStoppedHolder.durationTV.setText(mActivity.formattedMillis(getItem(position).getDuration())); 
       musicFileStoppedHolder.playButton.setOnClickListener(new OnClickListener() { 

        @Override 
        public void onClick(View arg0) { 
         Log.e("clicked", getItem(position).getName()); 
         Bundle bun = new Bundle(); 
         bun.putString(Constants.BUNDLE_KEYS.PLAY_FILES, getItem(position).getPath()); 
         Message message = Message.obtain(null, Constants.OP_CODE.PLAY_FILES); 
         message.setData(bun); 
         try { 
          mActivity.mService.send(message); 
         } 
         catch (RemoteException re) { 
          re.printStackTrace(); 
         } 
        } 

       }); 
      } 
      break; 
     } 

     if(!getItem(position).wasAnimatedIn()) { 
      row.startAnimation(getItem(position).getGoingIn()); 
     } 
     else if (!getItem(position).wasAnimatedOut()) { 
      Animation outAnim = getItem(position).getGoingOut(); 
      outAnim.setAnimationListener(new AnimationListener() { 

       @Override 
       public void onAnimationEnd(Animation animation) { 
        data.remove(getItem(position)); 
       } 

       @Override 
       public void onAnimationRepeat(Animation animation) {} 

       @Override 
       public void onAnimationStart(Animation animation) {} 
      }); 
      row.startAnimation(outAnim); 
     } 
     return row; 
    } 

이 어댑터에서 서비스가 호출 할 수있는 방법 중 하나는

입니다.
public void activatePlayingState(int positionInPage) { 
     if(positionInPage < getCount()) { 
      ListViewDataItem lvDataItem = getItem(positionInPage); 
      lvDataItem.setState(Constants.MEDIA_FILE.TYPE.STATE.PLAYING); 
      notifyDataSetChanged(); 
     } 
    } 

답변

1

위치는 ID와 동일한 방식으로 안정화되지 않습니다. 예를 들어 선택 모드입니다. ID가 안정적이지 않으면 목록의 모든 변경 사항 (항목 이동/추가/제거)은 모든 항목을 저장하는 것이 실제 위치를 추적하지 못하기 때문에 체크 된 위치를 뒤집을 것입니다. 부수적으로 문제와 관련이 없지만 안정적인 ID를 갖고 항목이 20 개가 넘는 항목을 이동하면 항목의 선택 상태가 지워집니다. 코드가 작성되었을 당시에는 위치를 확인하는 ~ 20 개의 항목을 통과하는 것이 효율적인 방법으로 수행 될 수 있다고 생각했다고 가정합니다.

귀하의 경우 주변에서 물건을 움직이지 않을 수도 있지만, 내부적으로는 notifyDataSetChanged()으로 전화 할 때 항목이 움직입니다. AdapterView.AdapterDataSetObserver#onChangednotifyDataSetChanged()으로 전화하면 정확히 무슨 일이 발생하는지 보여줍니다.

지점으로 이동하려면 위치 대신 stableIds를 사용하여 문제를 해결할 수 있습니다. 이를 구현하려면 getItemId(int position) 메소드를 변경하여 해당 위치에있는 항목의 고유 ID를 리턴하십시오. 그런 다음 hasStableIds()을 대체하여 true를 반환합니다. hasStableIds()BaseAdapter#hasStableIds()에 대한 문서는 다음과 같습니다. 이제 이드를 당신의 서비스에 전달할 수 있습니다. 당신은 이미 번들을 서비스에 전달하고 있으므로, 이드를 그냥 넣으십시오. 또한 추적해야하는 상태의 항목에 대한 ID를 저장해야합니다. 예를 들어, ArrayList에 ID를 추가하는 것만 큼 간단합니다. 서비스가 무엇이든간에 무엇이든 할 경우, idue를 사용하여 activatePlayingState 메서드를 호출 할 수 있습니다 (int에서 long으로 해당 매개 변수를 변경해야 함). getView에서 getItemId(int position)을 사용하여 활성화 된 ID를 현재 getView 항목과 비교하고 해당 항목의보기를 예상대로 설정할 수 있습니다.

+0

안녕하세요. 제 질문을 읽어 주셔서 감사합니다. 나는 당신의 대답을 많이 읽었지만 문제가 해결되지 않는다고 생각합니다.그건 그렇고, 순간에 내가 당신의 대답을 읽고, 나는 (BaseAdapter 확장 대신) ListAdapter 구현 내 어댑터를 변경하고 문제가 지속됩니다. 내가 업데이트 된 질문에 대한 링크를 게시 할 예정입니다. 나는 또한 여기에 내 질문에 모든 사실을주지 않았어, 그래서 나는 upvoting하고 올바른 대답으로 대답을 표시합니다. – jfv

+0

편집 시간 종료 :(최하위는 getView 메소드에서 position 변수를 현재 뷰의 식별자로 사용하고 im은 각 뷰의 데이터를 보유한 arraylist를 사용하여 고유 한 인덱스로 식별합니다. 번들은 이미 원본 파일 구조에 의해 고유성이 보장 된 고유 ID 인 파일 절대 경로를 보내고 있습니다. Thx again – jfv

+0

은이 주제에 대한 업데이트 된 질문을 여기에 게시했습니다. http://stackoverflow.com/questions/19564012/listadapter-getview- 틀린 가치를위한 – jfv

관련 문제