今天做了一个智能聊天机器人,其实相对比较简单,用到的知识点如下:
1.listView的熟练使用
2.第三方API的调用,发送数据请求和返回数据解析
3.网络请求时使用的异步任务和Handler
不过学会了之前没有接触的东西,在IDE里测试工具类,写完工具类测试是一个好习惯
public class HttpUtil { private static final String URL = "http://www.tuling123.com/openapi/api"; private static final String API_KEY = ""; private static final String CHARSET = "UTF-8"; /* * 发送一个消息,得到ChatMessage类型返回值 */ public static ChatMessage sendChatmessage(String msg){ ChatMessage chatMessage = new ChatMessage(); String JsonResult = getMsg(msg); Gson gson = new Gson(); Result result = null; try { result = gson.fromJson(JsonResult, Result.class); chatMessage.setMsg(result.getText()); } catch (JsonSyntaxException e) { chatMessage.setMsg("服务器异常"); e.printStackTrace(); } chatMessage.setDate(new Date()); chatMessage.setType(Type.INCOMING); return chatMessage; } /* * 发送请求,得到返回这为json数组 */ public static String getMsg(String msg){ StringBuffer result = new StringBuffer(); StringBuffer outBuf = new StringBuffer(); try { outBuf.append("key=").append(API_KEY).append("&info=").append(URLEncoder.encode(msg, CHARSET)); } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); } HttpURLConnection conn; try { //POST方式向服务器端发送信息 conn = (HttpURLConnection) new URL(URL).openConnection(); conn.setRequestMethod("POST"); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); conn.setDoOutput(true); //一行行读取和字节读取哪个更好? BufferedWriter out = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream(), CHARSET)); out.write(outBuf.toString()); out.flush(); BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), CHARSET)); String line = ""; while((line = in.readLine()) != null){ result.append(line); } } catch (ProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return result.toString(); } }
在这里首先使用POST方式发送消息给服务器(也可以采用GET方式),解析返回值时,返回值是JSON数组,用BufferReader的readline()一行行读取(也可以用字节流读取,相对来说应该更加可靠,但是效率比较慢,因此我使用字符流)。返回的JSON字符串在sendChatMessage()中使用GSON来把JSON字符串解析为对应了Bean,这里我把JSON字符串转化为了Result。工具类写好了,接下来开始测试:
<application android:allowBackup="true" android:icon="@drawable/xiaomeng" android:label="@string/app_name" android:theme="@style/AppTheme" > <uses-library android:name="android.test.runner"></uses-library> <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <instrumentation android:targetPackage="com.liu.androidxiaofeng"//指定测试程序的包名 android:label="This is a test"//可以随便写 android:name="android.test.InstrumentationTestRunner"> </instrumentation>
在apalication里写了uses-library,接着编写instrucmentaction,这就是配置测试的必要步骤
接着编写测试类
public class TestHttpUtil extends AndroidTestCase { private static final String TAG = "TestHttpUtil"; public void testUtil(){ String res = HttpUtil.getMsg("你好"); Log.d(TAG, res); res = HttpUtil.getMsg("给我讲个笑话"); Log.d(TAG, res); res = HttpUtil.getMsg("我帅不帅"); Log.d(TAG, res); } }
创建一个类继承AndroidTestCase,在里面编写测试逻辑,然后对逻辑测试方法右键 run-as-Android-JUtil-Test
说明测试成功!!
还有一点需要注意,由于listView是对话模式,因此要有两个子项布局,在编写Adapter时,要实现另外两个方法getItemViewType(int position) 和 getViewTypeCount()
public class MsgAdapter extends BaseAdapter { private List<ChatMessage> data; private LayoutInflater inflater; public MsgAdapter(Context context, List<ChatMessage> data){ this.data = data; inflater = LayoutInflater.from(context); } @Override public int getCount() { return data.size(); } @Override public Object getItem(int position) { return data.get(position); } @Override public long getItemId(int position) { return position; } @Override public int getItemViewType(int position) { ChatMessage chatMessage = data.get(position); if(chatMessage.getType() == Type.INCOMING){//如果是接受消息,返回0 return 0; }else{ return 1;//如果是发送消息,返回1 } } @Override public int getViewTypeCount() { return 2;//有发送消息和接受消息两种view } @Override public View getView(int position, View convertView, ViewGroup parent) { ChatMessage chatMessage = data.get(position); ViewHolder viewHolder = null; if(convertView == null){ if(getItemViewType(position) == 0){//说明是接受布局 convertView = inflater.inflate(R.layout.item_from_msg, parent, false); viewHolder = new ViewHolder(); viewHolder.date = (TextView) convertView.findViewById(R.id.tv_from_msg_date); viewHolder.msg = (TextView) convertView.findViewById(R.id.tv_from_msg); }else{//说明是发送布局 convertView = inflater.inflate(R.layout.item_to_msg, parent, false); viewHolder = new ViewHolder(); viewHolder.date = (TextView) convertView.findViewById(R.id.tv_to_msg_date); viewHolder.msg = (TextView) convertView.findViewById(R.id.tv_to_msg); } convertView.setTag(viewHolder); }else{ viewHolder = (ViewHolder) convertView.getTag(); } //设置数据 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); viewHolder.date.setText(dateFormat.format(new Date())); viewHolder.msg.setText(chatMessage.getMsg()); return convertView; } private final class ViewHolder{ TextView date; TextView msg; } }