제가 리스트뷰나 어댑터의 개념이 딸려서 그런지 몰라도 구글링을 해보거나 여러곳을 찾아봐도
도대체 모르겠습니다.
지금 구현된 형태는 액티비티에 리스트뷰를 하나 만들어놨고
다른 클래스에 BaseAdapter를 받아서 어댑터를 구현해 놨습니다.
로우에는 체크박스 , 텍스트뷰, 버튼 이렇게 세개가 있고
버튼을 눌렀을 때 이 로우가 삭제되고
화면에 바로 갱신이 되게 하고 싶습니다.
어댑터에서 버튼에 리스너 달고 자료를 지워도 화면에 반영이 되질 않습니다.
알아본바로는 어댑터 안에서는
notifyDataSetChanged() 가 안먹인 다고 알고 있는데
리스트가 있는 액티비티에서 또 버튼리스너를 달으려니 또 안 달아 집니다. 영문을 모르겠습니다.
액티비티에서 삭제버튼을 누르면 발생하는 리스너를 구현해야 한다면 어떻게 리스너를 달아야 되고
아니면 어댑터내에서 해결을 하려면 어떻게 해야 되는지 제발 방법좀 알려주세요.
부탁드려요.
일단 액티비티의 코드입니다.!!!!
public class vms extends Activity{ //implements BookMarkAdapterListner{
HashMap<String,String> hm;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.l_vms);
hm = new TryAccData(vms.this).accVmsDataList(hello.vmsListUrl,null,null);
if(!(hm.get("nothing[0]")==null)&&hm.get("nothing[0]").equals("nothing"))return;
final vmsListAdapter vmsListAdapter = new vmsListAdapter(this,vms.this,R.layout.vms_row_main, hm);
ListView vmsListMain = (ListView) findViewById(R.id.vmsListMain);
vmsListMain.setAdapter(vmsListAdapter);//어댑터로 리스튜뷰에 리스트 집어넣음
/*Button launch = (Button)findViewById(R.id.vmsDelBtn);
launch.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
}
});*/
vmsListMain.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?>parent,View view , int position, long id)
{
vmsListAdapter.notifyDataSetChanged();
}
});
}이것 저것 다 해봐서 소스가 좀 지저분하네요.
그리고 이것은 어댑터의 getview소스입니다.
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
if(convertView == null){
convertView = inflater.inflate(mListLayout, parent,false);
}
CheckBox cb = (CheckBox)convertView.findViewById(R.id.isRead);
cb.setFocusable(false);//체크박스가 포커스를 가지고 있음녀 리스트뷰의 리스너가 안먹는다 그래서 이 것을 false로 설정
cb.setClickable(false);//체크박스가 안에서 클릭이 안되게 설정
final int positionInt = position;
//TryAccData set =new TryAccData();
TextView subject = (TextView) convertView.findViewById(R.id.play_vms);
subject.setText((position+1)+". " + hm.get("regdate["+position+"]"));
//Log.i("체크",hm.get("rwflag["+position+"]"));
String rwflag=hm.get("rwflag["+position+"]");
if(rwflag.equals("true"))
cb.setChecked(true);
else
cb.setChecked(false);
Button vmsDelBtn = (Button) convertView.findViewById(R.id.vmsDelBtn);
try{
vmsDelBtn.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v){
del(positionInt);
}
});
subject.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v){
set(positionInt);
}
});
} catch (Exception e){
Log.e("vmsbuttonlistener",e.getMessage());
}
notifyDataSetChanged();
return convertView;
}마지막으로 로우의 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">
<TextView android:text="제목"
android:layout_toRightOf="@+id/isRead"
android:maxLines="4"
android:lines="4"
android:ellipsize="end"
android:layout_width="230px"
android:layout_height="wrap_content"
android:id="@+id/play_vms"
></TextView>
<CheckBox
android:layout_width="wrap_content"
android:id="@+id/isRead"
android:layout_height="wrap_content"
android:text =""
android:layout_alignParentLeft="true"
android:focusableInTouchMode="false"
android:focusable="false"
android:clickable="false"
/>
<TextView android:id="@+id/textview"
android:layout_width="wrap_content"
android:text=""
android:textSize="8px"
android:layout_height="wrap_content"
android:layout_below="@+id/isRead"
android:layout_alignLeft="@+id/isRead"
android:focusableInTouchMode="false"
></TextView>
<Button
android:id="@+id/vmsDelBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="삭제"
android:layout_alignParentRight="true"
android:layout_toRightOf="@+id/play_vms"
/>
</RelativeLayout>
제가 리스트뷰에 설정할 데이터로 해쉬맵데이터로 쓰고 있는데요.. 충분히 찾아보지 않고 올렸다고 하셔도 할말없지만
이 문제때문에 찾아보면서도 삼일째 해결을 못하고 있습니다. 도와 주세요
똑같은 레이아웃의 activity를 써서 속임수를 쓰면 어떨까요?
버튼을 누르면 리스트뷰 삭제 작업을 한 뒤에 똑같은 액티비티를 한번더 불러내면서 + 기존의 액티비티는 finish, 그리고 새로만든 액티비티의 flag를 지정하면 감쪽같이 될거 같아요^^
notifyDataSetChanged() 가 안먹인 다고 알고 있는데 <--- 먹히지 않나요 ㅡㅡ?
notifyDataSetChanged() 는 DATA가 변동이 있을때 적용이 되니까 실제로DATA값을 삭제하면 정상적으로 작동할거 같은데요..
ㅡㅡa 저번에 한거 같아는데 쩝 가물가물
이코드의 문제점 몇가지를 지적하자면 우선 리스트뷰의 OnItemClickListener가 하는일이 Adapter의 notifyDataSetChanged() 뿐이라면 달아줄 필요 없습니다. 이러면 개별 리스트뷰 아이템이 하는일은 하나도 없는데 클릭만 되고 클릭하면 쓸때없는 새로고침만 계속 될뿐이죠 그리고 getView의 마지막 부분에서 notifyDataSetChanged()를 호출하고 계신데 이렇게 하면 리스트뷰를 스크롤 할때마다 새로고치기 때문에 문제가 발생합니다.
Adapter에 Map을 넣으셨는데 저렇게 position을 바탕으로 데이터를 세팅해주실거면 Map을 Adapter에 쓰는건 굉장히 비효율적입니다.
하시고 싶으신게 삭제버튼을 누르면 삭제하고 새로 고치는거니 del() 메서드에서 삭제하시고 notifyDataSetChanged()를 호출해주시면 되겠습니다.
답변 정말 감사드려요. 염치없지만 다시 한번 여쭤 볼게요..
map으로 쓴 이유는 바로 웹서버에서 내려받은 xml을 파싱해서 map으로 저장했기 때문인데요.
xml로 내려올때 만약
<DATA>
<FLAG>F</FLAG>
<SUBJECT>A</SUBJECT>
</DATA>
<DATA>
<FLAG>T</FLAG>
<SUBJECT>B</SUBJECT>
</DATA>
<DATA>
<FLAG>F</FLAG>
<SUBJECT>C</SUBJECT>
</DATA>
이런식으로 내려온다면 MAP에는 파싱을 해서
FLAG[0]=F
SUBJECT[0]=A
FLAG[1]=T
SUBJECT[1]=B
FLAG[2]=F
SUBJECT[2]=C
이렇게 저장을 해서 사용하고 있습니다.
리스트에 넣어주는 것은 맵에 있는 0인덱스대로 리스트에 넣어주고 있는데요.
기본적으로 del()매서드에도 당연히 notifyDataSetChanged()가 있습니다.
리스트뷰의 리스너도 결국 원하는 결과가 나오지 않아서 notifyDataSetChanged()를 추가해 봤고요.
getview에도 notifyDataSetChanged()를 넣어본건데 동작하지 않는 것을 봐서는
결국 notifyDataSetChanged()가 문제가 없다면 아이템을 지우는 방법을 제가 모르는 것 같네요.
그럼 map안에 있는 자료를 지워주면 리스트에서도 지워 지는 것인가요?
부탁드립니다.ㅜ
저런식으로 Map을 써서 Adapter에 넣어주기 보다는 ValueObject 클래스를 만들어 쓰시는게 좋습니다.
예를들면
class Data {
private String flag;
private String subject;
public void setFlag(String flag) {
this.flag = flag
}
public String getFlag() {
return flag;
}
}
이런식으로 C에서 구조체 쓰듯 멤버변수 넣어주신뒤에 세터와 게터 메서드 만들어 주시고 List<Data> 타입으로
Adapter에 넣어주신뒤에 포지션에 맞게 쓰고 지울때는 remove로 list에서 날려주시면 됩니다.
Map은 key로 검색해야 될때 좋은 자료구조이지 이렇게 리스트형식으로 나타낼때는 별로 좋지 못합니다.




비슷한걸 구현한 적이 있는데 리스트뷰 뿌리는 부분을 따로 분리해서 놓고 onResume에다 호출하게 한 다음 삭제버튼을 눌렀을 때 다이얼로그를 띄워서 "삭제하시겠습니까?" 물어보게 하고 예를 눌리면 삭제. 그러면 알아서 onResume이 불려지면서 리스트뷰가 다시 뿌려짐.
이런 식으로 만들었던 거 같네요. 눌리면 바로 삭제하게 하는 것도 리스트뷰를 다시 뿌리면 되지 않을까 하는데요.