今天我们做个小项目,就是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;
@Override
protected 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>{
@Override
protected ChatMessage doInBackground(String... params) {
ChatMessage chat = HttpUtils.sendMessage(params[0]);
return chat;
}
@Override
protected 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;
}
@Override
public int getCount() {
return mDatas.size();
}
@Override
public Object getItem(int position) {
return mDatas.get(position);
}
@Override
public 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;
}
@Override
public 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";
// 申请的apiKey
public 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;
}
}
下面就是实现的效果图:
初始界面:
聊天界面: