今天做了一个小项目,就是Android自动聊天机器人的开发。主要的难点有:.图灵机器人API的解读和ListView多种item的实现

思考:
1.在ListView的每一项item中要放的数据是什么?
2.怎么把用于返回数据解析类的对象放在item的显示对象中。
3.提醒adapter有新数据了。

以下就是具体的代码实现:简单介绍一下各个函数的作用:

①MainActivity:在主线程中要实现发送按钮的监听事件,另外要创建一个异步任务实现网络数据的解析

②ChatMessageAdapter:继承于适配器BaseAdapter的类,用于向ListView中填充数据

③ChatMessage:定义ListView中要填充的内容

④Result类:因为该解析数据中没有第一级标题,所以就自定义Result类,其变量于Json解析出的变量保持一致,即是code和text

⑤HttpUtils:工具类,用于网络数据的解析

一、MainActivity

package org.mobiletrain.robot;import java.util.ArrayList;import java.util.Date;import java.util.List;import org.mobiletrain.robot.bean.ChatMessage;import org.mobiletrain.robot.bean.ChatMessage.Type;import org.mobiletrain.robot.http.HttpUtils;import android.app.Activity;import android.text.TextUtils;import android.view.View;import android.os.AsyncTask;import android.os.Bundle;import android.view.Window;import android.widget.Button;import android.widget.EditText;import android.widget.ListView;import android.widget.Toast;public class MainActivity extends Activity implements View.OnClickListener{private ListView listView;private EditText mInputText;private Button mSendButton;private ChatMessageAdapter adapter;private List<ChatMessage>mDatas;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_main);listView = (ListView)this.findViewById(R.id.id_listview_msgs);mInputText = (EditText)this.findViewById(R.id.id_input_msg);mSendButton = (Button)this.findViewById(R.id.id_send_msg);initDate();mSendButton.setOnClickListener(this);}/** * 初始化ListView的第一行 */private void initDate() {mDatas = new ArrayList<ChatMessage>();ChatMessage chat = new ChatMessage("您好,我是蛋蛋,很高兴为您服务!!",new Date(),Type.INCOMING);mDatas.add(chat);adapter = new ChatMessageAdapter(this, mDatas);listView.setAdapter(adapter);}/** * 设置按钮点击事件 *@Override */public void onClick(View v) {//1.点击之后获取edittext的值,判读一下是否为空,如果是空的,就提示用户。String msg = mInputText.getText().toString();if (TextUtils.isEmpty(msg)) {Toast.makeText(MainActivity.this, "输入数据不能为空", Toast.LENGTH_SHORT).show();}ChatMessage toMessage = new ChatMessage();toMessage.setDate(new Date());toMessage.setMessage(msg);toMessage.setType(Type.OUTCOMING);mDatas.add(toMessage);//提醒适配器更新数据adapter.notifyDataSetChanged();mInputText.setText("");new ChatMessageTask().execute(msg);}/** * 这是解析出来的数据格式 * { * code : 123 * text : 好开心呀,有吃成长快乐了。。。 * } * 定义异步任务实现数据的解析 *  */class ChatMessageTask extends AsyncTask<String, Void, ChatMessage>{@Overrideprotected ChatMessage doInBackground(String... params) {ChatMessage chat = HttpUtils.sendMessage(params[0]);return chat;}@Overrideprotected void onPostExecute(ChatMessage result) {super.onPostExecute(result);mDatas.add(result);//提醒适配器更新数据adapter.notifyDataSetChanged();}}}
二、ChatMessageAdapter适配器

package org.mobiletrain.robot;import java.text.SimpleDateFormat;import java.util.List;import org.mobiletrain.robot.bean.ChatMessage;import org.mobiletrain.robot.bean.ChatMessage.Type;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.TextView;/** * 定义ChatMessageAdapter适配器继承BaseAdapter * @author Administrator * */public class ChatMessageAdapter extends BaseAdapter{private List<ChatMessage>mDatas;private LayoutInflater mInflater;public ChatMessageAdapter(Context context,List<ChatMessage>mDatas){this.mInflater = LayoutInflater.from(context);this.mDatas = mDatas;}@Overridepublic int getCount() {return mDatas.size();}@Overridepublic Object getItem(int position) {return mDatas.get(position);}@Overridepublic long getItemId(int position) {return position;}/** * 协定listview中有几种类型的item *@Override */public int getViewTypeCount() {return 2;}/** * 判断枚举Type的类型然后确定填充数据的布局 * @Override */public int getItemViewType(int position) {ChatMessage chatMessage = mDatas.get(position);if (chatMessage.getType() == Type.OUTCOMING) {return 0;}return 1;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder vh;//如果converView为空,就去找到布局文件并填充内容if (convertView==null) {//判断Type的类型,如果为0代表用户输入,则convertView填充的数据界面为ListView的右边if (getItemViewType(position)==0) {convertView = mInflater.inflate(R.layout.item_to_msg, null);vh = new ViewHolder();vh.tv_date = (TextView)convertView.findViewById(R.id.id_to_msg_date);vh.tv_message=(TextView)convertView.findViewById(R.id.id_to_msg_info);}else {convertView = mInflater.inflate(R.layout.item_from_msg, null);vh = new ViewHolder();vh.tv_date = (TextView)convertView.findViewById(R.id.id_form_msg_date);vh.tv_message=(TextView)convertView.findViewById(R.id.id_from_msg_info);}convertView.setTag(vh);}else{vh = (ViewHolder)convertView.getTag();}//向ListView中填充数据ChatMessage data = mDatas.get(position);SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");vh.tv_date.setText(df.format(data.getDate()));vh.tv_message.setText(data.getMessage());return convertView;}/** *定义ViewHolder实现ListView的优化 * @author Administrator * */class ViewHolder{TextView tv_date;TextView tv_message;}}
三、ChatMessage类

package org.mobiletrain.robot.bean;import java.util.Date;/** * 定义获取输入的内容的类 * @author Administrator * */public class ChatMessage {private String message;private String name;private Date date;private Type type;public void setType(Type type) {this.type = type;}public Type getType() {return type;}//枚举:是一种新型的变量,他可以控制设定的内容public enum Type{OUTCOMING,INCOMING}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Date getDate() {return date;}public void setDate(Date date) {this.date = date;}public ChatMessage(String message, Date date, Type type) {super();this.message = message;this.date = date;this.type = type;}public ChatMessage() {// TODO Auto-generated constructor stub}}

四、与解析内容相匹配的自定义Result类

package org.mobiletrain.robot.bean;/** * 解析结果的格式 * @author Administrator * */public class Result {private String code;private String text;public String getCode() {return code;}public String getText() {return text;}public void setCode(String code) {this.code = code;}public void setText(String text) {this.text = text;}}

五、解析工具类:HttpUtils

package org.mobiletrain.robot.http;import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.UnsupportedEncodingException;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;import java.net.URLEncoder;import java.util.Date;import org.apache.http.HttpResponse;import org.apache.http.client.ClientProtocolException;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.DefaultHttpClient;import org.apache.http.util.EntityUtils;import org.mobiletrain.robot.bean.ChatMessage;import org.mobiletrain.robot.bean.ChatMessage.Type;import org.mobiletrain.robot.bean.Result;import com.google.gson.Gson;import com.google.gson.JsonSyntaxException;import android.R.string;/** * 联网工具类,用于连接网络,取得数据 * */public class HttpUtils {// 图灵机器人使用api的公网地址public static final String URL = "http://www.tuling123.com/openapi/api";// 申请的apiKeypublic static final String API_KEY = "be12dd3c0bac3654e78aa69e4b36a6dd";/** * 通过HttpURLConnection解析Json数据,返回结果是一个字符串 * @param url * @return */public static String getJsonContent(String url) {String result = "";URL url2;InputStream is;InputStreamReader isr;BufferedReader br;try {url2 = new URL(url);HttpURLConnection connection = (HttpURLConnection) url2.openConnection();is = connection.getInputStream();isr = new InputStreamReader(is, "utf-8");String line = "";br = new BufferedReader(isr);while ((line = br.readLine()) != null) {result += line;}try {br.close();} catch (IOException e) {e.printStackTrace();}} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return result;}/** * 通过HttpClient解析Json数据,返回结果是一个字符串 * @param url * @return */public static String getJsonContent2(String url) {String result = "";HttpClient httpClient = new DefaultHttpClient();HttpGet httpGet = new HttpGet(url);HttpResponse response = null;try {response = httpClient.execute(httpGet);if (response.getStatusLine().getStatusCode() == 200) {result = EntityUtils.toString(response.getEntity(), "utf-8");}} catch (ClientProtocolException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return result;}/** * 解析Json数据,返回结果是一个byte[]数组,一般用于解析网络图片 * @param url * @return */public static byte[] getByteContent2(String url) {byte[] data = null;HttpClient httpClient = new DefaultHttpClient();HttpGet httpGet = new HttpGet(url);HttpResponse response = null;try {response = httpClient.execute(httpGet);if (response.getStatusLine().getStatusCode() == 200) {data = EntityUtils.toByteArray(response.getEntity());}return data;} catch (ClientProtocolException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return data;}/** * 通过HttpURLConnection解析Json数据,返回结果也是一个byte[]类型的数组 * @param url * @return */public static byte[] getByteContent(String url) {try {URL url2 = new URL(url);HttpURLConnection httpConn = (HttpURLConnection) url2.openConnection();httpConn.setDoInput(true); // 允许输入内容httpConn.setDoOutput(false);httpConn.connect();ByteArrayOutputStream baos = new ByteArrayOutputStream();if (httpConn.getResponseCode() == 200) {BufferedInputStream bis = new BufferedInputStream(httpConn.getInputStream());byte[] buffer = new byte[8 * 1024];int c = 0;while ((c = bis.read(buffer)) != -1) {baos.write(buffer, 0, c);baos.flush();}byte[] data = baos.toByteArray();return data;}} catch (Exception e) {e.printStackTrace();}return null;}/** * 拼接接口,其中参数为用户输入传来的内容 */public static String setParams(String msg){String url = "";try { url = URL +"?key="+API_KEY+"&info="+URLEncoder.encode(msg, "UTF-8");} catch (UnsupportedEncodingException e) {e.printStackTrace();}return url;}/** * 解析Json数据,返回类型是一个ChatMessage对象 * @param msg * @return */public static ChatMessage sendMessage(String msg){ChatMessage chatMessage = new ChatMessage();String jsonRes = getJsonContent(setParams(msg));Gson gson = new Gson();Result result = null;try {result = gson.fromJson(jsonRes, Result.class);chatMessage.setMessage(result.getText());} catch (JsonSyntaxException e) {chatMessage.setMessage("服务器繁忙,请稍后再试");}chatMessage.setDate(new Date());chatMessage.setType(Type.INCOMING);return chatMessage;}}
下面就是实现的效果图:

初始界面:



聊天界面:




更多相关文章

  1. Android(安卓)ApiDemos示例解析(134):Views->Layouts->Baseline-
  2. Android(安卓)Okhttp断点续传面试深入解析
  3. Android(安卓)消息推送:第三方消息推送平台 详细解析
  4. Unity调用Android(安卓)jar包方法——(三、使用UnitySendMessage
  5. [置顶] 解析android 流量监测的实现原理
  6. android Adapter体系
  7. Android之EasyPermissions源码解析
  8. ArcGIS for Android(安卓)离线数据图例加载
  9. Android数据类型之间相互转换系统介绍

随机推荐

  1. Android数据库升级
  2. Android开发规范(编码+性能+UI)
  3. Android下uid与多用户释疑(一)
  4. 移动设备操作系统知识点简摘又名我的期末
  5. Android系统架构分析 和 Android应用程序
  6. 有关Android线程的学习
  7. 学习Android从0开始之背景篇-Android系统
  8. android的init实例
  9. Android存储数据的三种方式
  10. Android(安卓)原生页面同H5交互