今天做了一個智能聊天機器人,其實相對比較簡單,用到的知識點如下:
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;
}
}