图灵机器人智能聊天—代码分析

原创代码慕课网,讲师讲的太快,不方便理解,做个代码分析,方便以后阅读!如图页面

图灵机器人智能聊天—代码分析_第1张图片
1.项目要求
要求接入图灵官网的API,做一个能机器  现类似微信的聊天页面
2.项目核心
 访问网络, JSON解析,枚举实现双视图适配器的原理
3.项目结>  基本概括:5个类,  两个getset类,一个核心类访问网络,一个Activity处理页面 还有一个测试类如图:
"MyFahui.java"  是存放访问网址后返回值的getset类           编码+Json
"Myjiexi.java"    是对Jons解析后的值后的getset类,        消息+时间+枚举
"HttpUtil.Java"   是 发送接受消息的核心类,传入发送消息,得到Json数据,被解析到MyFahui.java中,然后最后交给了Myjiexi,
(作为一个一体成型的工具类,只要传入String,就能返回出一个完整getset类)
”MyActivity.Java“ 是一个Activity,负责显示页面,双套布局的适配器,线程更新适配器等
HttpText.java"是一个测试类,主要负责测试工作,在主页面没有绘制前,对"HttpUtil.java"进行测试工作

图灵机器人智能聊天—代码分析_第2张图片

1.一旦消息传工具类,自动拼接成一个网址,并访问网址得到Json格式的数据,被解析成到一个getset类中封装好==================================================================================

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URLEncoder;
import java.util.Date;
<img src="http://img.blog.csdn.net/20151018231250086?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />



import com.google.gson.Gson;
import com.info.MyFanhui;
import com.info.Myjiexi;
import com.info.Myjiexi.Type;

public class HttpUtil {
	private static final String URL="http://www.tuling123.com/openapi/api";
	private static final String KEY="742330b59b0cdea8a537db941bfa087f";

	/*【核心】:
	 * 发送一个消息,被解析成一个getset类-----------------------------------------
	 * */
	public static Myjiexi jiexi(String stt){
				Myjiexi jiexi=new Myjiexi();     
				MyFanhui  fh=null;                    		
				String xiaoxi=doGet(stt);            //传入String,得到Json返回
			
				Gson gson=new Gson();
				try {
					fh=gson.fromJson(xiaoxi,MyFanhui.class);
					jiexi.setMsg(fh.getText());          //设置返回的内容
				} catch (Exception e) {
					jiexi.setMsg("服务器繁忙");
				}
                      
				jiexi.setDate(new Date());            //设置当前时间
				jiexi.setType(Type.WO);               //设置枚举类型
				return jiexi
						;
		
		}
	
	
/*核心方法,-------------------------------------------------
	    传入String字符串,自动拼接好地址,Url
	    传入访问网络地址,自动返回字符串,Json
	*/
	public static String doGet(String str){
		String str2=Pingjie(str);         //【此方法拼接出完整地址】
	     String str3= Fangwen(str2);   //【此方法连接网址】
		return str3; 
	}
	//【访问连接网址】
	private static String Fangwen(String str2) {
		InputStream is = null;
		ByteArrayOutputStream bs = null;
		
		String str3="";
		try {
			java.net.URL 			url= new java.net.URL(str2);                               
			HttpURLConnection conn=(HttpURLConnection) url.openConnection(); 
											conn.setReadTimeout(5*1000); 
											conn.setConnectTimeout(5*1000);
											conn.setRequestMethod("GET");								
		           is=conn.getInputStream();           //输入流
				int len=-1;
				byte[] by=new byte[128];
				 	bs=new ByteArrayOutputStream();//输出流
				while((len=is.read(by))!=-1){
					bs.write(by, 0, len);		
				}
				bs.flush();                                         //清除缓冲区
			str3=new String(bs.toByteArray());     //*输出流String
		} catch (Exception e) {
		e.printStackTrace();
			}finally{                                                   //释放资源
				try {
					if(is!=null){
						is.close();
						if(bs!=null){
							bs.close();
						}
					}
				} catch (Exception e2) {
				e2.printStackTrace();}
			}			
return str3;
	} 
	

	
	/*【拼接完整地址】*/
	public static String Pingjie(String str){
		String str2="";
		try {
		str2=URL+"?key="+KEY+"&info="+URLEncoder.encode(str, "UTF-8");	
		} catch (Exception e) {e.printStackTrace();}
		return str2;
	}
	
}

2.下面简要看看两个getset类的基本数据类型有什么===========================================================================================================

注意:解析类中包含两个构造方法,一个有参,一个无参,方便我们以后调用

1)MyFanhui (返回类)

int类型的编码,

String类型的字符串

package com.info;
public class MyFanhui {
	private int code;
	private String text;
	public int getCode() {
		return code;
	}
	public void setCode(int code) {
		this.code = code;
	}
	public String getText() {
		return text;
	}
	public void setText(String text) {
		this.text = text;
	}


}



2)Myjiexi(解析类)------------------------------------------------------------------

字符串消息String

枚举类型Type

时间数据Data

package com.info;

import java.util.Date;
public class Myjiexi {
	private String msg;
	private Type type;
	private Date date;
	
	public Myjiexi() {
		
	}
	
	public Myjiexi( String msg, Type type, Date date) {
		this.msg = msg;
		this.type = type;
		this.date = date;
	}


	public String getMsg() {
		return msg;
	}
	public void setMsg(String msg) {
		this.msg = msg;
	}
	public Type getType() {
		return type;
	}

3.【配置环节】================================================================================================================

图灵的规定是,按要求拼接好你的地址,连接网址,得到返回数据

我们写的工具类就完全具备了这个功能了,只是没有页面,下面要进行一个代码的测试工作,

测试配置清单一览

三个重要的部分,联网权限,测试的应用库,然后就是单元测试,配置好了,就可以进入测试环境了

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.xiaomu"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />
    
<!-- 【网络权限】 -->
<uses-permission android:name="android.permission.INTERNET"/>
   	

<application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
    <!-- 【应用库】 -->
        <uses-library android:name="android.test.runner"/>
        
        <activity
            android:name="com.example.xiaomu.MyActvity"
            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.example.xiaomu"
	android:label="This is test"
    android:name="android.test.InstrumentationTestRunner"></instrumentation>
</manifest>

5.测试类是一个超类,具体自己百度去吧!===========================================================================================

  代码也是极其简单,继承就AndroidTestCase就可以了

package com.text;

import com.util.HttpUtil;

import android.test.AndroidTestCase;
/*单元测通过*/
public class Httptext extends AndroidTestCase{

	
	public void testSendInfo(){
	    String str=		HttpUtil.doGet("你好");
			System.out.println("---"+str);
		}
	
}
测试方法比较特殊,代码中点击这个类名,直接运行,

如果看到了日志中的返回中文消息就说明测试成功,我们才能继续下一步的页面编写工作了

这是返回的数据应该还是json数据,注意几个问题,测试需要开模拟器,并关闭工具类的jiexi方法,

6.主页面,如果测试完毕了那么久可以做页面了,

  首先了解下页面结构,后期贴上xml代码,

  三段式,头部,中间,底部,

头部标题,中间listview,底部输入框

java代码的工作是,


主要是适配器的工作,默认要启动适配器,主人发送消息要激活一次适配,机器回复一次开一个适配器(线程)

至于双套视图,可以参考这个适配器中,除了默认的四个方法外,还有两个关于枚举的方法,枚举的返回值 决定了,我们要用那套视图,而且并用了ViewHoder的一个类,

实际是作为缓存类,目的是让适配器效率更加的快速,

判断是否为空,是为了保存缓存类数据,方便后面的加载,等等


其次可以看到代码集中在点击事件上,点击事件中适配器要动两次,主人发送,机器返回,

都需要适配器更新,而机器人返回数据是返回到getset中,传输整个getset类用线程启动再更新实现的效果


package com.example.xiaomu;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.info.Myjiexi;
import com.info.Myjiexi.Type;
import com.util.HttpUtil;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class MyActvity extends  Activity implements OnClickListener{
	private EditText w_edit;
	private Button   w_but;
	
	private ListView  w_listview;  //列表UI
	private   List<Myjiexi> list;    //数据集合
	private   MyAdapter adapter; //适配器
	
	//【3】子线程更新主线程,拿到消息,重启适配器
	private Handler handler=new Handler(){
		public void handleMessage(android.os.Message msg) {		
		Myjiexi	 myjiexi=(Myjiexi) msg.obj;
		list.add(myjiexi);
		adapter.notifyDataSetChanged();
		};
	};
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_main);
		
	initView();
    initData();
   
	}

	
	/*【机器人第一句话 方法】   (测试)
	 * */
	private void initData() {
		list=new ArrayList<Myjiexi>();
		list.add(new Myjiexi("你好2", Type.Ni, new Date()));
		//list.add(new Myjiexi("你好1", Type.WO, new Date()));
		adapter=new MyAdapter(this, list);
		w_listview.setAdapter(adapter);
	}



	/*【布局的初始化 方法】
	 * */
	private void initView() {
		w_edit=(EditText) findViewById(R.id.edit1);
		w_but=(Button) findViewById(R.id.but1);
		w_listview=(ListView) findViewById(R.id.listview1);
		w_but.setOnClickListener(this);		
	}





/*【双套布局适配器】----------------------
 * 目的:双套布局的使用
 * 适配器中加入了枚举的两个方法,
 * 一个是枚举数量,一个是枚举的返回值,
 * 根据返回值,设置双套布局,并设置了缓存类方便加速
 */
	class MyAdapter extends BaseAdapter{
			private Context con;
			private List<Myjiexi> list;
		public MyAdapter(Context con,List<Myjiexi> list) {
			 this.con=con;
		     this.list=list;
		}	
		public int getItemViewType(int h) {
			if(list.get(h).getType()==Type.Ni){
				return 0;	 
				}return 1;
			}
		public int getViewTypeCount() {	
			return 2;
			}	
		public int getCount() {   
			return list.size();
			}
		public Object getItem(int h) {
			return list.get(h);	
			}
		public long getItemId(int h) {
			return h;
			}
		public View getView(int h, View v, ViewGroup v2) {
			Myjiexi myjiexi=list.get(h);
			ViewHolder viewHolder=null;
			if(v==null){
				if(getItemViewType(h)==0){
					v=View.inflate(con, R.layout.litem_2, null);
					viewHolder=new ViewHolder();
					viewHolder.w_msg=(TextView) v.findViewById(R.id.Wtext);
					viewHolder.w_time=(TextView) v.findViewById(R.id.Wtime);	
				}else{
					v=View.inflate(con, R.layout.litem_1, null);
					viewHolder=new ViewHolder();
					viewHolder.w_msg=(TextView) v.findViewById(R.id.Ntext);
					viewHolder.w_time=(TextView) v.findViewById(R.id.Ntime);
				}
				v.setTag(viewHolder); 
			}else{
				viewHolder=(ViewHolder) v.getTag();
			}
			SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			viewHolder.w_time.setText(sf.format(myjiexi.getDate()));
			viewHolder.w_msg.setText(myjiexi.getMsg());	
			return v;
		}
		}	
	
	/*缓存类*/
	private final class ViewHolder{
		TextView w_time;
		TextView w_msg;
	}
	
/*【点击事件】---------------------------------------------------------------------------------
 * 目的: 发送消息,更新页面
 * 消息判断,清空输入框,线程访问网络,返回值交给主线程更新页面
 * */
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.but1:
		final String str=w_edit.getText().toString();
		if(TextUtils.isEmpty(str)){
			Toast.makeText(this, "消息不能为空", 1).show();
		}
		//【1】更新发送
		Myjiexi myjiexi=new Myjiexi();
					myjiexi.setDate(new Date());
					myjiexi.setMsg(str);
					myjiexi.setType(Type.Ni);
		list.add(myjiexi);
		adapter.notifyDataSetChanged();
		w_edit.setText("");
	  // 【2】处理回收
		new Thread(){
			public void run() {
				Myjiexi myjiexi=HttpUtil.jiexi(str);
				Message m=Message.obtain();
				               m.obj=myjiexi;
				               handler.sendMessage(m);
				               }}.start();
			break;
		}
	}

}










后面就是页面了

1)主页面

图灵机器人智能聊天—代码分析_第3张图片

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
   >

   <!-- 【头部布局】 --> 
    <RelativeLayout
        android:id="@+id/toubu"
        android:layout_width="fill_parent"
        android:layout_height="45dp"
        android:layout_alignParentTop="true"
        android:background="@drawable/title_bar" >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="小欣"
            android:textColor="#ffffff"
            android:textSize="22sp" />
    </RelativeLayout>

<!-- 【底部布局】 -->
    <RelativeLayout
        android:id="@+id/dibu"
        android:layout_width="fill_parent"
        android:layout_height="55dp"
        android:layout_alignParentBottom="true"
        android:background="@drawable/bottom_bar" >
        <Button
            android:id="@+id/but1"
            android:layout_width="60dp"
            android:layout_height="40dp"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:background="@drawable/but_by"
            android:text="发送" />

        <EditText
            android:id="@+id/edit1"
            android:layout_width="fill_parent"
            android:layout_height="40dp"
            android:layout_centerVertical="true"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:layout_toLeftOf="@id/but1"
            android:background="@drawable/login_edit_normal"
            android:textSize="18sp" />
    </RelativeLayout>
<!-- 聊天列表 -->
    <ListView
        android:id="@+id/listview1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_above="@id/dibu"
        android:layout_below="@id/toubu"
        android:divider="@null"
        android:dividerHeight="5dp" >
    </ListView>

</RelativeLayout>


2)发送

图灵机器人智能聊天—代码分析_第4张图片


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
  	android:orientation="vertical" >
    <TextView
        android:id="@+id/Wtime"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="显示时间" 
        android:textSize="12sp"
        android:background="#bebebe"
        android:textColor="#f5f5f5"
       android:layout_gravity="center"/>
    
    <!-- 线性布局(横向) 包含:
     消息+  线性布局(头像+昵称)
    -->
<LinearLayout 
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:gravity="right">
    <TextView 
        android:id="@+id/Wtext"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="你好"
        android:layout_gravity="center_vertical"
        android:background="@drawable/chatto_bg_focused"
        />
    
    <LinearLayout 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">
    	
    	<TextView 
      	  	android:layout_width="wrap_content"
        	android:layout_height="wrap_content"
        	android:text=" 主人"/>
    </LinearLayout>
    
</LinearLayout>



</LinearLayout>


3)接受

图灵机器人智能聊天—代码分析_第5张图片

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
  	android:orientation="vertical" >
    <TextView
        android:id="@+id/Wtime"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="显示时间" 
        android:textSize="12sp"
        android:background="#bebebe"
        android:textColor="#f5f5f5"
       android:layout_gravity="center"/>
    
    <!-- 线性布局(横向) 包含:
     消息+  线性布局(头像+昵称)
    -->
<LinearLayout 
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:gravity="right">
    <TextView 
        android:id="@+id/Wtext"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="你好"
        android:layout_gravity="center_vertical"
        android:background="@drawable/chatto_bg_focused"
        />
    
    <LinearLayout 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">
    	
    	<TextView 
      	  	android:layout_width="wrap_content"
        	android:layout_height="wrap_content"
        	android:text=" 主人"/>
    </LinearLayout>
    
</LinearLayout>



</LinearLayout>


你可能感兴趣的:(图灵机器人智能聊天—代码分析)