안드로이드 개발 질문/답변
(글 수 45,052)
안녕하세요, 카카오톡과 비슷한 기능의 채팅기능을 구현중인데요!
실제 필드에서 쓰는 방식이 있으심 알려주시고요. 저는 일단 이렇게 구현 했는데 도와주세요. 간절...~~~
채팅 구현방식으로는 커스톰 리스트뷰 아답터를 이용하여
리스트뷰에 제가쓴글과 타인이쓴글을 구분하여, 각기 다른 xml을 리스트뷰에 넣어주는 식으로 구현하고있습니다.
누구든지 글을 쓸 경우는 써드파티 웹서버를 통해 채팅방 안에있는 모든 친구들의
GCM 키값을 가져와 해당 친구들에게 푸쉬를
보내고, 푸쉬를 받은 사람들은 특정 로직에따라
방에 참여하고있을경우 위에서 말했던 것처럼
리스트뷰에 값이 넣어지게 됩니다.
서론이 길었는데요, 몇가지 문제가 발생하였습니다.
리스트뷰에 어느정도 채팅값이
쌓이고나서
스크롤을 하면(getview()함수가 호출되면)
스크롤을 빠르게 할시 겟뷰가 빠르게 호출되면서
1-리스트뷰에 null이 발생하거나/ 2-첨부한
fatal exception이 발생하며 종료되거나 / 3- 혹은 리스트뷰의 뷰순서가 꼬입니다.
그래서 구글링과 검색을통해 해결책으로
viewholder을 이용해보기도하고, 자기가쓴글과 타인이쓴글을 2개의 xml row를 이용하지않고 프레임레이아웃으로
visibility를 켜고 끄는식으로도 해보고, 이미 구성되어있던 레이아웃들을 relative로 바꾸어 가볍게 해보기도 했는데
해결이
안됩니다. 특히 3번문제의경우 사양이 좋은 폰에서는 문제가 안되는것으로 보아, viewholder을 이용하면 문제가
해결될줄 알았으나 결국 제자리 걸음이네요. 심지어 3번문제는 글을 올리는도중에도 저사양 폰에서는 뷰순서가 꼬이게 됩니다.
logcat과 함께 아답터의 코드, 리시버에서 데이터를받고 아답터에 넣는 코드를 첨부합니다.
작은 조언이나 키워드라도 감사하게 받겠습니다!
(참고로 로그캣의 첫번째 에러나는 부분은 소스코드중 viewHolder.PersonName.setText(data.getName());
여기입니다.)
[code]
public View getView(int position, View convertView, ViewGroup
parent)
{
Log.d("겟뷰호출", "겟뷰호출");
ViewHolder
viewHolder;
// View view = null;
//int type = getItemViewType(position);
ChatDatas
data= m_data_list.get(position);
if(convertView == null) {
// 타입에 따라 각기 다른 XML 리소스로 뷰를 생성한다.
viewHolder = new ViewHolder();
convertView=inflater.inflate(R.layout.chat_list,null);
viewHolder.leftChat=(RelativeLayout)convertView.findViewById(R.id.left_chat);
viewHolder.rightChat=(LinearLayout)convertView.findViewById(R.id.right_chat);
if(data.getType()==0){
//convertView=inflater.inflate(R.layout.chat_left_list,null);
viewHolder.leftChat.setVisibility(View.VISIBLE);
viewHolder.rightChat.setVisibility(View.GONE);
viewHolder.PersonImg
=(ImageView)convertView.findViewById(R.id.left_person_img);
viewHolder.PersonName=(TextView)convertView.findViewById(R.id.left_person_name);
viewHolder.PersonSay=(TextView)convertView.findViewById(R.id.left_person_say);
viewHolder.PersonTime=(TextView)convertView.findViewById(R.id.left_person_time);
}
else{
//convertView=inflater.inflate(R.layout.chat_right_list,null);
viewHolder.rightChat.setVisibility(View.VISIBLE);
viewHolder.leftChat.setVisibility(View.GONE);
viewHolder.PersonSay=(TextView)convertView.findViewById(R.id.right_person_say);
viewHolder.PersonTime=(TextView)convertView.findViewById(R.id.right_person_time);
//view =
m_inflater.inflate(R.layout.chat_right_list, null);
}
convertView.setTag(viewHolder);
} else {
//view = convertView;
viewHolder=(ViewHolder)convertView.getTag();
}
// 요청하는 항목에 해당하는 데이터 객체를 얻는다.
if(data != null) {
if(data.getType()==0) {
//viewHolder.PersonImg.setImageResource(R.drawable.test_thumbnail);
//viewHolder.PersonImg.setImageResource(0);
viewHolder.PersonName.setText(data.getName());
viewHolder.PersonSay.setText(data.getSay());
viewHolder.PersonTime.setText(data.getTime());
}else
if(data.getType()==1) {
viewHolder.PersonSay.setText(data.getSay());
viewHolder.PersonTime.setText(data.getTime());
}
}
return convertView;
}
public class ViewHolder
{
public ImageView PersonImg;
public TextView PersonName;
public TextView PersonSay;
public TextView PersonTime;
public RelativeLayout leftChat;
public LinearLayout rightChat;
}
//////////////////////리시버에서 아답터로 넣는코드
receiver = new BroadcastReceiver(){
public void
onReceive(Context context, Intent intent) {
if(intent.getAction().equals("msg"))
{
String
room_name = intent.getExtras().getString("roomName").toString();
if(room_name.equals(currentRoom))
{
String talker_name
="";
talker_name=intent.getExtras().getString("talkerName").toString();
if(talker_name.equals("")){
}else{
talker_say =
intent.getExtras().getString("talkerSay").toString();
talker_time =
intent.getExtras().getString("talkerTime").toString();
//int type=0;
int type=1;
if(!talker_name.equals(app.getName()))
type=0;
dt = new
ChatDatas(0,talker_name,talker_say,talker_time,type);
adapter.add(dt);
chatListView.smoothScrollToPosition(adapter.getCount()-1);
}
}
else{
Log.d("다른방",
"다른방");
}
}
}//onreceive
끝
};
[/code]
data.getName() 값이 null이 들어가서 그렇습니다.
null 확인해보십시요.