마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

리스트뷰 재사용문제에 따른 포지션값이상현상에 대해..

0 추천
public class MyAdapter extends BaseAdapter {
		private LayoutInflater lif;
		int selectedPosition = 0;
		int editsPosition = 0;
		
		public MyAdapter() {
			lif = (LayoutInflater) getActivity().getSystemService(
					Context.LAYOUT_INFLATER_SERVICE);
			for (int i = 0; i < 50; i++) 
			{
				ListItem listItem = new ListItem();
				listItem.caption = "Caption" + i;
				myItems.add(listItem);
			}
			notifyDataSetChanged();
		}
		
		
		@Override
		public int getCount() {
			// TODO Auto-generated method stub
			return myItems.size();	
		}

		@Override
		public Object getItem(int position) {
			// TODO Auto-generated method stub
			return myItems.get(position);
		}

		@Override
		public long getItemId(int position) {
			// TODO Auto-generated method stub
			return position;
		}

		@Override
		public View getView(final int position, View convertView,ViewGroup parent) 
		{
			
			View v = convertView;
			final ViewHolder holder;
		
			if (v == null) //레이아웃 초기화 자업
			{
				v = getActivity().getLayoutInflater().inflate(R.layout.msg_listview, null);
				Log.d("","v==null");
				holder = new ViewHolder();
				holder.msg_edit = (EditText) v.findViewById(R.id.msg_edit);
				holder.msg_radio = (RadioButton) v.findViewById(R.id.msg_radio);
				holder.msg_savebtn = (Button) v.findViewById(R.id.msg_savebtn);//edit저장버튼
				v.setTag(holder);
			} 
			else // null이 아닐 때 저장된 뷰 홀더를 재사용.
			{
				Log.d("","v!=null");
				holder = (ViewHolder)v.getTag(); //v.setTag(holder)재사용
			}
		
			holder.msg_radio.setChecked(position == selectedPosition);
			holder.msg_radio.setTag(position);
			holder.msg_radio.setOnClickListener(new View.OnClickListener() 
			{
				@Override
				public void onClick(View v) {
					// TODO Auto-generated method stub

					selectedPosition = (Integer) v.getTag();
					Log.d("현재 선택 된 라디오버튼 값은?",
							Integer.toString(selectedPosition));
					String whatisedit1 = holder.msg_edit.getText().toString();
					Toast.makeText(
							getActivity(),
							"라디오버튼 :" + Integer.toString(selectedPosition)+ "/" + whatisedit, Toast.LENGTH_LONG).show();
				
					String text = pref.getString("Editmsg", "");
					holder.msg_edit.setText(text);
					//전체setText
					notifyDataSetChanged();
				}
			});
			holder.msg_savebtn.setTag(position);
			holder.msg_savebtn.setOnClickListener(new View.OnClickListener() 
			{
				
				@Override
				public void onClick(View v) 
				{
					// TODO Auto-generated method stub
					int savebtnpos = (Integer) v.getTag();
					Log.d("savebtn position",Integer.toString(savebtnpos));
					whatisedit = holder.msg_edit.getText().toString();
			//		holder.msg_edit.setText(whatisedit);
					Toast.makeText(getActivity(), "[저장]"+Integer.toString(savebtnpos)+"번 버튼 : "
					+whatisedit, 1000).show();
					//whatisedit=>해당 포지션에 입력된 string값
					//입력한 텍스트 저장하기.
					SharedPreferences.Editor ed = pref.edit();
					ed.putString("Editmsg", whatisedit);
					ed.commit();				
//					String text = pref.getString("Editmsg", "");
//					holder.msg_edit.setText(text);
				}
			});
			
			btn_send.setOnClickListener(new OnClickListener() 
			{
				
				@Override
				public void onClick(View v) {
					// TODO Auto-generated method stub
					Log.d("[전송]선택 된 라디오버튼 값은?",Integer.toString(selectedPosition));
					String whatisedit = holder.msg_edit.getText().toString();
					Log.d("[전송]선택 된 텍스트 값은?",whatisedit);
					showDialog(whatisedit);
				}
			});
			
			return v;
		} // getview
	}//Databaseadapter
	
	
	public class ViewHolder
	{
		public EditText msg_edit;
		public RadioButton msg_radio;
		public Button msg_savebtn;
	}

 

커스텀 리스트뷰를 통해 50개의 리스트를 만들었습니다.

한 줄마다 [라디오버튼] [에디트텍스트] [저장버튼] 이렇게 구성되어있습니다.

지금 몇 일째...이 getview에 의한 재사용문제로 고민 중입니다.

포지션값이 뒤죽박죽으로 바뀌는 바람에 editText에 써놓은 문자를 저장하지도 못하네요..

대략 한 화면에 5개의 줄이 보이는데, 재사용문제..아시다시피 스크롤을 하면 0번째에 써놓은 값이

밑에 있는 editText들에도 보입니다. 전혀 건드리지도 않았는데 말이죠....

convertview가 null이 아닐 때, 어떠한 조건문 처리를 해서 값이 중복되지 않게 , 포지션값이 제대로 나오게 해야하는지

모르겠습니다...

 

 

anci (19,950 포인트) 님이 2015년 1월 26일 질문

1개의 답변

0 추천
말그대로 껍데기인 뷰를 재사용하는 것이죠

convertView가 null일 때나 아닐 때나 내용은 매 번 새로 세팅해줘야 되겠죠

ListItem item = myItems.get(position);

holder.msg_edit.setText(item.caption);
alkyne (22,960 포인트) 님이 2015년 1월 26일 답변
댓글 감사합니다. 아직 제대로 이해하지 못했는데, 리스트뷰에서 스크롤을 하면서 화면을 새로 갱신할 때 무조건 getView를 호출하는데, 최초로 리스트를 띄울 때만 v==null 조건에 맞고, 그 뒤로 스크롤할 땐 v!=null 조건문만 걸리는게 아닌가요..? 아니면 두개의 조건문이 끝난 밑 부분을 말씀하시는건지요?
그렇죠 v == null 조건문 쪽은 뷰를 재사용할지 새로만들지 처리하는 부분이고 그 후에 내용넣는 부분이 들어가야겠죠
v!=null 인경우 그전에 세팅한 값을 포함한 뷰가 넘어오게 됩니다.
값을 새로 셋팅을 해주지 않는경우 라디오버튼의 경우 재사용되는 뷰가 true로 되어있던 뷰였다면 따로 셋팅한적도 없는데 true값으로 되어버리는 거죠.

포지션값에 맞는 데이터를 getview에서 항상 셋팅해주도록 하시면 됩니다.
else문의
holder = (ViewHolder)v.getTag();이 이전 뷰의 세팅값이라는것인가요..?
포지션에 맞는 값을 세팅하려면.. for문으로 50개의 값을 모두 확인해야 하는것인가요? 현재 라디오버튼은 중복이라거나 포지션문제는 없는데, editText에서 이렇게 꼬여버립니다..
editText에서 setText한 녀석을 저장버튼을 통해 저장하고싶은데요, sharedpreference를 사용하려고 하는데, 50개의 값이면 배열을 사용해야할거같은데, 다른 방법으로도 저장 할 수있을까요?
...