安卓智能聊天机器人开发(二)

接上一篇文章《安卓智能聊天机器人开发(一)》,晚上继续写。

在上一篇文章中,已经实现了对网络数据的获取和处理封装,这篇文章来讲下如何嵌入到安卓应用中。

先看下效果图:

安卓智能聊天机器人开发(二)安卓智能聊天机器人开发(二)

从上面两张图我们可以发现,这个聊天布局其实就是一个ListView,只不过它和传统的ListView有些区别,因为它使用了多Item样式布局

首先,先来分析下基础布局:

这个界面是由3个布局文件组成,分别是主布局,发送消息样式布局,接收消息样式布局

先来看下主布局:

安卓智能聊天机器人开发(二)

这里是对应的主布局代码:

android:divider="@null"  --去除ListView的Item分割线

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

 2     xmlns:tools="http://schemas.android.com/tools"

 3     android:layout_width="match_parent"

 4     android:layout_height="match_parent"

 5     android:background="@drawable/chat_bg_default" >

 6 

 7     <LinearLayout

 8         android:id="@+id/title"

 9         android:layout_width="fill_parent"

10         android:layout_height="wrap_content"

11         android:layout_alignParentTop="true"

12         android:background="@drawable/title_bar"

13         android:gravity="center"

14         android:orientation="vertical" >

15 

16         <TextView

17             android:layout_width="wrap_content"

18             android:layout_height="fill_parent"

19             android:layout_gravity="center"

20             android:text="机器兔"

21             android:textColor="@android:color/white"

22             android:textSize="20sp" />

23     </LinearLayout>

24 

25     <RelativeLayout

26         android:id="@+id/bottom"

27         android:layout_width="fill_parent"

28         android:layout_height="55dp"

29         android:layout_alignParentBottom="true"

30         android:background="@drawable/bottom_bar"

31         android:padding="5dp" >

32 

33         <EditText

34             android:id="@+id/send_message"

35             android:layout_width="fill_parent"

36             android:layout_height="wrap_content"

37             android:layout_alignParentLeft="true"

38             android:layout_centerVertical="true"

39             android:layout_marginLeft="5dp"

40             android:layout_marginRight="5dp"

41             android:background="@drawable/login_edit_normal" />

42 

43         <Button

44             android:id="@+id/send_bt"

45             android:layout_width="wrap_content"

46             android:layout_height="fill_parent"

47             android:layout_alignParentRight="true"

48             android:layout_alignRight="@id/send_message"

49             android:background="@drawable/send_button_selector"

50             android:gravity="center_vertical"

51             android:text="发送" />

52     </RelativeLayout>

53 

54     <ListView

55         android:id="@+id/chatlistview"

56         android:layout_width="fill_parent"

57         android:layout_height="fill_parent"

58         android:layout_above="@id/bottom"

59         android:layout_below="@id/title"

60         android:divider="@null" >

61     </ListView>

62 

63 </RelativeLayout>

再来看下消息布局:(由于消息布局只是左右两边方向的不同,这里只给出其中一个)

安卓智能聊天机器人开发(二)

这是2个消息布局的代码:

 1 <?xml version="1.0" encoding="utf-8"?>

 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

 3     android:layout_width="match_parent"

 4     android:layout_height="match_parent"

 5     android:orientation="vertical" >

 6 

 7     <TextView

 8           android:id="@+id/sendtime"

 9         android:layout_width="wrap_content"

10         android:layout_height="wrap_content"

11         android:layout_gravity="center"

12         android:background="#999999"

13         android:text="2014-11-07 18:00"

14         android:textColor="@android:color/white" />

15 

16     <LinearLayout

17         android:layout_width="match_parent"

18         android:layout_height="wrap_content"

19         android:orientation="horizontal" >

20 

21         <LinearLayout

22             android:layout_width="wrap_content"

23             android:layout_height="wrap_content"

24             android:orientation="vertical" >

25 

26             <!-- 头像昵称部分 -->

27 

28             <ImageView

29                 android:layout_width="50dp"

30                 android:layout_height="50dp"

31                 android:src="@drawable/icon1" />

32 

33             <TextView

34                 android:layout_width="wrap_content"

35                 android:layout_height="wrap_content"

36                 android:layout_gravity="center"

37                 android:text="机器兔" />

38         </LinearLayout>

39 

40         <TextView

41             android:id="@+id/sendmsg"

42             android:layout_width="wrap_content"

43             android:layout_height="wrap_content"

44             android:background="@drawable/chatfrom_bg_normal"

45             android:text="你好,我是机器兔。" />

46     </LinearLayout>

47 

48 </LinearLayout>
 1 <?xml version="1.0" encoding="utf-8"?>

 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

 3     android:layout_width="match_parent"

 4     android:layout_height="match_parent"

 5     android:orientation="vertical" >

 6 

 7     <TextView

 8         android:id="@+id/receivetime"

 9         android:layout_width="wrap_content"

10         android:layout_height="wrap_content"

11         android:layout_gravity="center"

12         android:background="#999999"

13         android:text="2014-11-07 18:00"

14         android:textColor="@android:color/white" />

15 

16     <LinearLayout

17         android:layout_width="fill_parent"

18         android:layout_height="wrap_content"

19         android:gravity="right"

20         android:orientation="horizontal" >

21 

22         <TextView

23             android:id="@+id/receivemsg"

24             android:layout_width="wrap_content"

25             android:layout_height="wrap_content"

26             android:background="@drawable/chatto_bg_normal"

27             android:text="你好,我是机器兔。"

28             android:textColor="@android:color/black" />

29 

30         <LinearLayout

31             android:layout_width="wrap_content"

32             android:layout_height="wrap_content"

33             android:orientation="vertical" >

34 

35             <!-- 头像昵称部分 -->

36 

37             <ImageView

38                 android:layout_width="50dp"

39                 android:layout_height="50dp"

40                 android:src="@drawable/icon" />

41 

42             <TextView

43                 android:layout_width="wrap_content"

44                 android:layout_height="wrap_content"

45                 android:layout_gravity="right"

46                 android:text="我" />

47         </LinearLayout>

48     </LinearLayout>

49 

50 </LinearLayout>

 

接下来看下关于ListView的自定义适配器,和往常一样自定义适配器需要继承BaseAdapter,并实现一些必须的方法

这里有个需要注意的是,因为传统的ListView是统一一个样式的,而这里的聊天布局是左右两边收发信息多Item样式

所以需要额外的多覆写2个方法:

1、getViewTypeCount  --返回样式的种类数目

2、getItemViewType    --给定类型标示符,便于在回调函数getView时让系统知道我们需要显示的哪个样式

代码里还提到了ViewHolder,这个是优化ListView加载速度的一种方法,关于这个知识点我整理一篇笔记《安卓开发笔记——ListView加载性能优化ViewHolder

》出来,不熟悉的朋友可以看看。

  1 package com.example.androidchat;

  2 

  3 import java.text.SimpleDateFormat;

  4 import java.util.List;

  5 

  6 import com.example.pojo.Msg;

  7 import com.example.pojo.Msg.Type;

  8 

  9 import android.content.Context;

 10 import android.view.LayoutInflater;

 11 import android.view.View;

 12 import android.view.ViewGroup;

 13 import android.widget.BaseAdapter;

 14 import android.widget.TextView;

 15 /**

 16  * 

 17  * ListView适配器

 18  *

 19  */

 20 public class ChatAdapter extends BaseAdapter {

 21 

 22     private List<Msg> data;

 23     private LayoutInflater inflater;// 布局工厂,可以把res/layout的xml布局文件转换成view对象

 24 

 25     public ChatAdapter(Context context, List<Msg> data) {

 26         inflater = LayoutInflater.from(context);

 27         this.data = data;

 28     }

 29 

 30     @Override

 31     public int getCount() {

 32         return data.size();

 33     }

 34 

 35     @Override

 36     public Object getItem(int position) {

 37         return data.get(position);

 38     }

 39 

 40     @Override

 41     public long getItemId(int position) {

 42         return position;

 43     }

 44 

 45     @Override

 46     public View getView(int position, View convertView, ViewGroup parent) {

 47         Msg message = data.get(position);

 48         ViewHolder viewHolder = null;

 49         if (convertView == null) {// 未加载布局文件对象

 50             // 可以通过getItemViewType所定义的标识来设定对应的item样式

 51             if (getItemViewType(position) == 0) {// 接收信息

 52                 viewHolder = new ViewHolder();

 53                 convertView = inflater.inflate(R.layout.send_msg, null);

 54                 viewHolder.time = (TextView) convertView

 55                         .findViewById(R.id.receivetime);

 56                 viewHolder.msg = (TextView) convertView

 57                         .findViewById(R.id.receivemsg);

 58             } else {

 59                 viewHolder = new ViewHolder();

 60                 convertView = inflater.inflate(R.layout.receive_msg, null);

 61                 viewHolder.time = (TextView) convertView

 62                         .findViewById(R.id.sendtime);

 63                 viewHolder.msg = (TextView) convertView

 64                         .findViewById(R.id.sendmsg);

 65             }

 66             convertView.setTag(viewHolder);

 67         } else {// 已经存在布局文件对象

 68             viewHolder = (ViewHolder) convertView.getTag();

 69         }

 70 

 71         // 设置数据

 72         SimpleDateFormat dateFormat = new SimpleDateFormat(

 73                 "yyyy-MM-dd HH:mm:ss");

 74         viewHolder.time.setText(dateFormat.format(message.getTime()));

 75         viewHolder.msg.setText(message.getMsg());

 76         return convertView;

 77     }

 78 

 79     /**

 80      * 由于此处我们要返回2种ListView的Item样式,需要再额外多覆写2个方法 

 81      * (1)、getItemViewType(int position)给定类型标示符 

 82      * (2)、getViewTypeCount() 类型数量

 83      */

 84     @Override

 85     public int getItemViewType(int position) {

 86         Msg message = data.get(position);

 87         if (message.getType() == Type.INCOME) {

 88             return 0;// 如果消息类型为接收,则值为0

 89         }

 90         return 1;// 如果消息类型为发送,则值为1

 91     }

 92 

 93     @Override

 94     public int getViewTypeCount() {

 95         return 2;

 96     }

 97 

 98     private final class ViewHolder {

 99         TextView time;// 消息时间

100         TextView msg;// 消息内容

101     }

102 

103 }

 

然后就是主程序代码了:

这里就没什么好说的了,网络数据获取工具类包括ListView的适配器类在之前已经提过,这里就只剩下调用了。

注意点有3:

1、那就是在UI主线程里不能直接取获取网络数据,这里我们需要另开一个子线程去获取,然后在通过Handler去更新UI界面。

2、当数据源发生更新的时候,需要在UI主线程去操作,而不是子线程,还有就是不应该去重新设置Adapter,只需要去调用Adapter的notifyDataSetChanged()就行。

3、记得设置下ListView的setSelection选项,便于焦点自动往下拉。

不在UI主线程里做耗时操作,会使得UI现成阻塞。不在子线程里去更新UI界面,会导致应用程序无响应。

 1 package com.example.androidchat;

 2 

 3 import java.util.ArrayList;

 4 import java.util.Date;

 5 import java.util.List;

 6 

 7 import android.app.Activity;

 8 import android.os.Bundle;

 9 import android.os.Handler;

10 import android.os.Message;

11 import android.view.View;

12 import android.view.View.OnClickListener;

13 import android.widget.Button;

14 import android.widget.EditText;

15 import android.widget.ListView;

16 

17 import com.example.pojo.Msg;

18 import com.example.pojo.Msg.Type;

19 import com.example.utils.GetDataUtils;

20 

21 public class MainActivity extends Activity {

22 

23     

24     private ListView listview;

25     private EditText sendmsg;

26     private Button sendbt;

27     private ChatAdapter adapter;//ListView自定义适配器

28     private List<Msg> data;//数据源

29 

30     

31     private Handler handler=new Handler(){

32         public void handleMessage(Message msg) {

33                 Msg receiveMsg=(Msg) msg.obj;

34                 data.add(receiveMsg);

35                 adapter.notifyDataSetChanged();

36                 listview.setSelection(data.size()-1);//定位位置,自动下拉

37             

38         };

39     };

40     @Override

41     protected void onCreate(Bundle savedInstanceState) {

42         super.onCreate(savedInstanceState);

43         setContentView(R.layout.activity_main);

44         

45         initView();//初始化控件

46         initData();//初始化数据

47         initAction();//初始化事件

48     }

49 

50     private void initAction() {

51         this.sendbt.setOnClickListener(new OnClickListener() {

52             

53             @Override

54             public void onClick(View v) {

55                 /**

56                  * 点击发送按钮执行步骤

57                  * 1、获取用户输入的内容并显示到ListView(判断是否为空)

58                  * 2、发送用户输入的内容到服务端获取服务端返回内容并显示到ListView(注意线程处理)

59                  * 3、清空输入框

60                  */

61                 final String sendInfo=sendmsg.getText().toString();//获取用户输入数据(用于发送)

62                 data.add(new Msg("",sendInfo,new Date(),Type.INCOME));

63                 adapter.notifyDataSetChanged();//更新数据源

64                 listview.setSelection(data.size()-1);//定位位置,自动下拉

65                 sendmsg.setText("");

66                 

67                 

68                 //向服务端发送信息并接收返回信息,由于UI主线程不能执行网络获取操作,这里需要开一个子线程

69                 new Thread(){

70 

71                     @Override

72                     public void run() {

73                         //执行网络操作

74                         GetDataUtils dataUtils=new GetDataUtils();

75                         Msg msg=dataUtils.getInfo(sendInfo);//获取到一个Msg对象,但由于子线程不能够更新UI,所以需要用到一个Handler

76                         Message message=Message.obtain();

77                         message.obj=msg;//封装信息

78                         handler.sendMessage(message);

79                     }

80                     

81                 }.start();

82             }

83         });

84     }

85 

86 private void initData() {

87         data=new ArrayList<Msg>();

88         adapter=new ChatAdapter(MainActivity.this,data);//获取ListView适配器实例

89         listview.setAdapter(adapter);

90     }

91 

92     private void initView() {

93         this.listview=(ListView) MainActivity.this.findViewById(R.id.chatlistview);

94         this.sendmsg=(EditText) findViewById(R.id.send_message);

95         this.sendbt=(Button) findViewById(R.id.send_bt);

96     }

97 

98 

99 }

好了,到此"安卓智能聊天机器人”就已经完成了,虽说这个机器人有点二,不过在无聊之余还是可以打发打发时间的哈~

 

作者:Balla_兔子
出处:http://www.cnblogs.com/lichenwei/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
正在看本人博客的这位童鞋,我看你气度不凡,谈吐间隐隐有王者之气,日后必有一番作为!旁边有“推荐”二字,你就顺手把它点了吧,相得准,我分文不收;相不准,你也好回来找我!

 

你可能感兴趣的:(安卓)