前言:今天休假回来的第一天,突然不知道该写点什么了,打开微信也找不到人聊天。。。无聊只好翻阅聊天记录,突然有了想法:今天写一下聊天记录的实现。
我们的聊天记录是保存在本地的,利用安卓自带的轻量化数据库SQlite实现。设计思路是这样的,对于会话列表我们只保存与某一好友聊天的最后一条记录,而进入会话界面后再查询所有记录,也就是会话列表与聊天记录实际上是两个表,在这里我们一起来了解一下会话记录的实现。
Step1,设计界面
整个会话记录界面其实就是一个首部与一个列表组成,首部即朋友圈消息,列表则是展现会话记录,每一条会话记录由对方头像、昵称、最后一条消息以及时间构成,界面整体布局代码如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.administrator.parentproject.activity.AllWorkActivity"> <RelativeLayout android:layout_width="match_parent" android:layout_height="@dimen/dp_72" android:background="@drawable/text_bg"> <TextView android:id="@+id/title_tv" android:layout_width="wrap_content" android:layout_height="@dimen/dp_72" android:layout_centerHorizontal="true" android:gravity="center" android:paddingTop="27dp" android:text="消息" android:textColor="@color/white" android:textSize="@dimen/text_14_sp" /> <ImageView android:layout_width="@dimen/dp_20" android:layout_height="@dimen/dp_20" android:layout_alignParentRight="true" android:layout_marginRight="@dimen/dp_10" android:layout_marginTop="37dp" android:id="@+id/iv_friend" android:src="@drawable/friend"/> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="@dimen/dp_5"> <ImageView android:layout_width="40dp" android:layout_height="40dp" android:layout_marginLeft="@dimen/dp_20" android:id="@+id/iv_friend_circle" android:src="@drawable/friendcircle"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/iv_friend_circle" android:layout_marginLeft="@dimen/dp_30" android:layout_marginTop="@dimen/dp_2" android:id="@+id/tv_friend_circle" android:textColor="#00DB00" android:text="班级圈"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/iv_friend_circle" android:layout_below="@id/tv_friend_circle" android:layout_marginLeft="@dimen/dp_30" android:layout_marginTop="@dimen/dp_2" android:text="语文老师 发表了一个动态"/> </RelativeLayout> <TextView android:layout_width="match_parent" android:layout_height="@dimen/dp_1" android:layout_marginTop="@dimen/dp_5" android:background="@color/lineColor" /> <TextView android:layout_width="match_parent" android:layout_height="@dimen/dp_1" android:layout_marginTop="@dimen/dp_10" android:background="@color/lineColor" /> <ListView android:id="@+id/ddjl_lv" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="@dimen/dp_5" android:layout_marginRight="@dimen/dp_5" android:layout_marginTop="@dimen/dp_5" android:divider="@color/lineColor" android:dividerHeight="@dimen/dp_1" android:scrollbars="none" /> </LinearLayout>
Step2,数据库设计
在这里只分析会话记录表结构,我们假定会话表具备这几个字段
private static final String ID = "id";//唯一标识 private static final String SENDERID = "sender_id";//发送者id private static final String ACCEPTERID = "accetter_id";//接受者id private static final String GROUPID = "group_id";//群id(临时无用) private static final String MSG = "msg";//消息 private static final String CREATETIME = "create_time";//时间 private static final String USERNAME = "user_name";//昵称 private static final String ICONURL = "icon_url";//头像地址
创建数据表sql语句如下:
public static final String SQL_CREATE_TABLE = "create table " + TABLE_NAME + "(" + ID + " integer primary key," + SENDERID + " integer," + ACCEPTERID + " integer," + GROUPID + " varchar(50)," + MSG + " varchar(50)," + CREATETIME + " varchar(50)," + USERNAME + " varchar(50)," + ICONURL + " varchar(50)" + ")";
由于我们设计的会话记录只保存最后一条,因此每次有新消息的时候需要删除之前的并写入新记录,并且考虑到实际情况,应该支持用户删除所有的会话记录,因此实现其删除、增加与查询方法,代码如下:
//保存 public void saveSession(int uid1,int uid2,ChatRecord cr){ clearById(uid1,uid2); insert(cr); }
public void clearById(int uid1,int uid2) { SQLiteDatabase db = dbHelper.getWritableDatabase(); String sql = "delete from " + TABLE_NAME + " where ( sender_id = " + uid1+" and accetter_id = "+uid2+" ) or (sender_id = " + uid2+" and accetter_id = "+uid1+")"; try { db.execSQL(sql); } catch (Exception e) { e.printStackTrace(); } finally { db.close(); } }
public void insert(ChatRecord cr) { SQLiteDatabase db = dbHelper.getWritableDatabase(); ContentValues cv = new ContentValues(); cv.put(SENDERID, cr.getSenderid()); cv.put(ACCEPTERID, cr.getAccepterid()); cv.put(GROUPID, cr.getGroupid()); cv.put(MSG, cr.getMsg()); cv.put(CREATETIME, cr.getCreatetime()); cv.put(ICONURL, cr.getIconurl()); cv.put(USERNAME, cr.getUsername()); db.insert(TABLE_NAME, null, cv); db.close(); }
/*获取会话列表*/ public List<ChatRecord> queryAll(String userid) { SQLiteDatabase db = dbHelper.getReadableDatabase(); List<ChatRecord> list = new ArrayList<>(); Cursor cursor = db.rawQuery("select * from " + TABLE_NAME +" where (sender_id = "+userid+" or accetter_id = "+userid+") order by create_time desc",null); for (cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()) { ChatRecord history=new ChatRecord(cursor.getInt(cursor.getColumnIndex(SENDERID)),cursor.getInt(cursor.getColumnIndex(ACCEPTERID)),cursor.getString(cursor.getColumnIndex(MSG)),cursor.getString(cursor.getColumnIndex(CREATETIME)),cursor.getString(cursor.getColumnIndex(GROUPID)),cursor.getString(cursor.getColumnIndex(ICONURL)),cursor.getString(cursor.getColumnIndex(USERNAME))); list.add(history); } if (cursor != null) { cursor.close(); } if (db != null) { db.close(); } return list; }
需要注意的是,为防止删除后添加失败的情况,可以利用事务进行处理
Step3,获取会话列表
在第二步中,我们已经定义了获取会话列表的方法,为什么要传递一个Userid参数呢,之所以这么做是考虑到一台终端可能支持多个用户登录,如果不做处理会导致会话记录混乱,我们定义一个适配器,并利用这个适配器将数据渲染到界面(listView)中。
userList = DBSessionDao.getInstance().queryAll(userId); if(userList.size()==0){ Toast.makeText(MyApplication.getContextObject(),"暂无数据",Toast.LENGTH_SHORT).show(); } myListViewAdapter = new MyListViewAdapter(MyApplication.getContextObject(), userList, "session","session"); ltLv.setAdapter(myListViewAdapter); ltLv.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { Log.e("icon111",userList.get(i).getIconurl()); Intent intent = new Intent(MyApplication.getContextObject(), com.example.administrator.parentproject.chat.MainActivity.class); if((userList.get(i).getSenderid()+"").equals(userId)){ intent.putExtra("toid", userList.get(i).getAccepterid()+""); }else{ intent.putExtra("toid", userList.get(i).getSenderid()+""); } intent.putExtra("nickName", userList.get(i).getUsername()); intent.putExtra("chatType", "1"); intent.putExtra("avatar", userList.get(i).getIconurl()); startActivity(intent); } });