实现一个智能聊天机器人「图灵机器人,Java,recyclerView」

简介: 实现一个智能聊天机器人(图灵机器人,Android,recyclerView)推荐一部关于Ai的系列漫画,叫做代码的深渊相关代码已经上传到Github的仓库Robot文件夹内apk体验地址:https://www.

实现一个智能聊天机器人(图灵机器人,Android,recyclerView)

推荐一部关于Ai的系列漫画,叫做代码的深渊

相关代码已经上传到Github的仓库Robot文件夹内

apk体验地址:https://www.pgyer.com/nVme

img_a46578492e1029f1b2d6ef5dc5fcf711.gif
智能机器人效果预览~1.gif

文章思路参考自刘桂林前辈的带领新手快速开发APP ,聊天界面代码参考于郭神的第一行代码第二版第三章3.7节,由衷感谢,文中不足之处,希望能得到您的指正,十分感谢

布局文件

创建项目,在build.gradle下填入依赖

implementation 'com.android.support:design:26.1.0'

然后我们进去res-values-styles下,把主题修改成没有标题的样式

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
</style>

然后在activity_main布局里面写一个recyclerView,用来显示对话聊天消息,以及一个EditText输入框,和一个发送数据的button按钮

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.administrator.robot.MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:gravity="center_vertical"
        android:orientation="horizontal">

        <EditText
            android:id="@+id/et_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:hint="输入" />

        <Button
            android:id="@+id/btn_send"
            android:layout_width="66dp"
            android:layout_height="36dp"
            android:layout_margin="5dp"
            android:background="#444444"
            android:text="发送"
            android:textColor="#FFFFFF" />
    </LinearLayout>

</LinearLayout>

回到Activity声明控件,并且给按钮设置点击事件,在按钮的点击事件里面进行输入框的处理,依次是:

1,获取输入框的内容

2,判断是否为空

3,发送后清空当前的输入框


public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    //  聊天消息列表
    private RecyclerView recyclerView;

    //  输入框
    private EditText editText;

    //  发送按钮
    private Button btn_send;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        recyclerView = findViewById(R.id.recycler);
        editText = findViewById(R.id.et_text);
        btn_send = findViewById(R.id.btn_send);
        btn_send.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_send:
                /**
                 * 1,获取输入框的内容
                 * 2,判断是否为空
                 * 3,发送后清空当前的输入框
                 */
//              1,获取输入框的内容
                String text = editText.getText().toString();
//              2,判断是否为空
                if (!TextUtils.isEmpty(text)) {
//              3,这里假装已经发送了数据,清空输入框
                    editText.setText("");
                }
                break;
        }
    }
}

后端接口的调试:

后端的接口我们使用图灵机器人,打开网站,注册好账号,创建一个机器人,我把机器人命名为阿紫,然后我们先用调试工具进行接口的调试,这里我用的调试工具是PostMan,参照图灵机器人官方文档

img_f625eca7fc97d1cce524f4eac8dc02db.png
图灵机器人页面

格式是发送Json数据的Post请求,在Json数据中带着两个参数:

{
    "reqType":0,
    "perception": {
        "inputText": {
            "text": "你叫什么"
        }
    },
    "userInfo": {
        "apiKey": "c00282de107144fb940adab994d9ff98",
        "userId": "225167"
    }
}

1,apikey(在机器人管理页),比如这里我的是:c00282de107144fb940adab994d9ff98,

2,userId(右上角用户头像右边的数字),这里我的是:225167

3,text就是表示我们想要和机器人聊天的具体文字

img_cbf29e16f33ed06def8815cda0d0a44b.png
用户id

进行调试

img_1357cf3f878c715306379a380323d1d6.png
PostMan调试

不得已截了大图,缩略图又有点模糊,点击图片就可以放大查看了

 {
    "emotion": {
        "robotEmotion": {
            "a": 0,
            "d": 0,
            "emotionId": 0,
            "p": 0
        },
        "userEmotion": {
            "a": 0,
            "d": 0,
            "emotionId": 0,
            "p": 0
        }
    },
    "intent": {
        "actionName": "",
        "code": 10004,
        "intentName": ""
    },
    "results": [{
        "groupType": 0,
        "resultType": "text",
        "values": {
            "text": "叫我阿紫就可以了"
        }
    }]
}

数据比较多,但是我们关心得的,仅仅只是Json数组result里面的test:我叫阿紫,不要被我的名字所迷倒哦而已,我们可以试试发送不同的文本,看看机器人会怎么回答,比如:

什么是Android? -- Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移...

你喜欢我吗? -- 你喜欢我,我就喜欢你。

至此,我们确定接口调试成功了

聊天界面的书写

思路是我们把消息加载到RecyclerViews的时候要去区分什么时候去显示左边的布局(机器人的对话),右边的布局(我们的对话),如果对RecyclerView还不会使用的看看这位前辈(随风飘扬的微笑)关于recyclerView的文章,或者查看第一行代码,相关图片素材已经上传到Github。

我们创建bean文件夹,然后创建聊天消息实体类chat,实体类有两个属性,用来标识是左边接受消息布局(TYPE_RECEIVED)还是右边布局的的type属性(TYPE_SENT),

/**
 * Created by 舍长 on 2018/5/10.
 * 描述: 聊天消息实体类
 */

public class Chat {
    public static final int TYPE_RECEIVED = 0;
    public static final int TYPE_SENT = 1;
    //    对话文本
    private String text;
    //    标示
    private int type;

    public Chat(String text, int type) {
        this.text = text;
        this.type = type;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    @Override
    public String toString() {
        return "ChatLiatData{" +
                "text='" + text + '\'' +
                ", type=" + type +
                '}';
    }
}

让我们先再build.gradle下添加圆形化图片的框架CircleImageView,用来对头像的处理

//CircleImageView
compile 'de.hdodenhof:circleimageview:2.1.0'

然后开始写我们的RecyclerView的item布局,命名为chat_item。我们先把左右的消息都写出来,在后面的消息加载item的时候我们再判断是要显示左边的接受消息布局还是右边的发送消息布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="10dp">

    <LinearLayout
        android:id="@+id/left_layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left">

        <de.hdodenhof.circleimageview.CircleImageView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_marginLeft="10dp"
            android:src="@drawable/robot_logo" />

        <TextView
            android:id="@+id/tv_left_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:background="@drawable/chat_bg_cloud"
            android:gravity="center_vertical"
            android:padding="20dp"
            android:text="你好,我叫阿紫"
            android:textColor="@android:color/black" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/right_layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right">

        <TextView
            android:id="@+id/tv_right_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="10dp"
            android:background="@drawable/chat_bg_user"
            android:gravity="center_vertical"
            android:padding="20sp"
            android:text="你好,你会些什么啊"
          android:textColor="@android:color/white" />

        <de.hdodenhof.circleimageview.CircleImageView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_marginRight="10dp"
            android:src="@drawable/user_logo" />
    </LinearLayout>

</LinearLayout>

接下来就开始写RecyclerView的Adapter

/**
 * Created by 舍长 on 2018/5/7.
 * 描述: 聊天布局适配器
 */

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {


    //    上下文
    private Context context;

    //    对话列表
    private List<Chat> mlist;

    public RecyclerViewAdapter() {

    }

    public RecyclerViewAdapter(Context context, List<Chat> list) {
        this.context = context;
        this.mlist = list;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_item, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Chat chat = mlist.get(position);
        if (chat.getType() == Chat.TYPE_RECEIVED) {
//           如果收的的数据是左边,就显示左边的消息布局,将右边的消息布局隐藏
            holder.leftLayout.setVisibility(View.VISIBLE);
            holder.rightLayout.setVisibility(View.GONE);
            holder.leftChat.setText(chat.getText());
//
        } else if (chat.getType() == chat.TYPE_SENT) {
//           如果发出的消息是右边,就显示右边的消息布局,将左边的消息布局隐藏
            holder.rightLayout.setVisibility(View.VISIBLE);
            holder.leftLayout.setVisibility(View.GONE);
            holder.rightChat.setText(chat.getText());
        }
    }

    @Override
    public int getItemCount() {
        return mlist.size();
    }

    /**
     * 声明控件
     */
    class ViewHolder extends RecyclerView.ViewHolder {
        LinearLayout leftLayout;
        LinearLayout rightLayout;
        TextView leftChat;
        TextView rightChat;

        public ViewHolder(View itemView) {
            super(itemView);
            leftLayout = itemView.findViewById(R.id.left_layout);
            rightLayout = itemView.findViewById(R.id.right_layout);
            leftChat = itemView.findViewById(R.id.tv_left_text);
            rightChat = itemView.findViewById(R.id.tv_right_text);
        }
    }
}

布局和平常的RecyclerView的适配器的区别在于在onBindViewHolder()方法中进行了判断。我们创建了集合mList,用来存储聊天数据

实体类Chat中有个属性type,type有两个值

public static final int TYPE_RECEIVED = 0;(接收的数据)

public static final int TYPE_SENT = 1;(发送的数据)

我们根据传入来的实体类的这个值来判断数据是左边的接收数据(TYPE_RECEIVED ),还是右边的发送数据(TYPE_SENT ),判断过后决定是要隐藏哪边的布局

Adapter写好之后我们在Activtiy进行数据的填充,RecyclerView布局管理器的代码书写

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    //  聊天消息列表
    private RecyclerView recyclerView;

    //  输入框
    private EditText editText;

    //  发送按钮
    private Button mButton;

    //    对话信息集合
    private List<Chat> list = new ArrayList<>();

    //    适配器
    private RecyclerViewAdapter recyclerViewAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
//      初始化数据
        initView();
//       加载数据
        initData();
//      设置布局管理
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(linearLayoutManager);
        recyclerViewAdapter = new RecyclerViewAdapter(this, list);
        recyclerView.setAdapter(recyclerViewAdapter);
    }

    /**
     * 加载列表布局数据
     */
    private void initData() {
        Chat c1 = new Chat("你好,我叫阿紫", Chat.TYPE_RECEIVED);
        list.add(c1);
        Chat c2 = new Chat("你好,你现在会些什么呢?", Chat.TYPE_SENT);
        list.add(c2);
        Chat c3 = new Chat("我还在成长中,很多东西还不懂,但是你可以考考我", Chat.TYPE_RECEIVED);
        list.add(c3);
        Chat c4 = new Chat("1+1等于几?", Chat.TYPE_RECEIVED);
        list.add(c4);
    }

    /**
     * 初始化控件
     */
    private void initView() {
        recyclerView = findViewById(R.id.recycler);
        editText = findViewById(R.id.et_text);
        mButton = findViewById(R.id.btn_send);
        mButton.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_send:
                /**
                 * 1,获取输入框的内容
                 * 2,判断是否为空
                 * 3,发送后清空当前的输入框
                 */
//              1,获取输入框的内容
                String text = editText.getText().toString();
//              2,判断是否为空
                if (!TextUtils.isEmpty(text)) {
//                  把要发送的数据添加到addData方法中,并把数据类型也填入,这里我们的类型是TYPE_SENT,发送数据类型
                    addData(text, Chat.TYPE_SENT);
//                  清空输入框
                    editText.setText("");
//              3,清空发送输入框
                    editText.setText("");

                }
                break;
        }
    }
        /**
     * 通过传递进来的test和type创建数据实体类,添加到聊天数据集合list中
     * @param text
     * @param type
     */
    private void addData(String text, int type) {
        Chat c = new Chat(text, type);
        list.add(c);
        //当有新消息时,刷新显示
        recyclerViewAdapter.notifyItemInserted(list.size() - 1);
        //定位的最后一行
        recyclerView.scrollToPosition(list.size() - 1);
    }

}

我们声明了一个集合list来存储我们的聊天数据,在initData()方法中加载数据,然后设置RecyclerView的布局管理器,并将集合数据填充到适配器中。我们在发送按钮的点击事件里面设置获取数据框的输入内容,设置为接受类型的数据,填充到list集合中,刷新适配器把显示的地方定位到最后一行,清空输入框。

至此,我们的聊天界面就写好了,让我们来看看目前的效果

img_f2001f2a9a7de6008d1721e7cac1038b.gif
这里写图片描述

对接网络接口:

我们采用Retrofit网络框架,还没接触过Retrofit的伙伴可以查看这篇文章

添加依赖:

//    retrofit
    compile 'com.squareup.okhttp3:okhttp:3.1.2'
    compile 'com.squareup.retrofit2:retrofit:2.0.1'
    compile 'com.squareup.retrofit2:converter-gson:2.0.1'

别忘了在AndroidManifest.xml文件中添加网络权限

<uses-permission android:name="android.permission.INTERNET"/>

现在让我们来看看发送的Json数据格式:

{

    "reqType":0,

    "perception": {

        "inputText": {

            "text": "你叫什么"

        }

    },

    "userInfo": {

        "apiKey": "c00282de107144fb940adab994d9ff98",

        "userId": "225167"

    }

}

我们在bean文件夹创建实体类Ask,使用GsonFormat工具生成请求数据实体类Ask(请求体)


/**
 * Created by 舍长 on 2018/5/10.
 * 描述: 发送数据实体类
 */

public class Ask {
    /**
     * reqType : 0
     * perception : {"inputText":{"text":"你叫什么"}}
     * userInfo : {"apiKey":"c00282de107144fb940adab994d9ff98","userId":"225167"}
     */

    private int reqType;
    private PerceptionBean perception;
    private UserInfoBean userInfo;

    public int getReqType() {
        return reqType;
    }

    public void setReqType(int reqType) {
        this.reqType = reqType;
    }

    public PerceptionBean getPerception() {
        return perception;
    }

    public void setPerception(PerceptionBean perception) {
        this.perception = perception;
    }

    public UserInfoBean getUserInfo() {
        return userInfo;
    }

    public void setUserInfo(UserInfoBean userInfo) {
        this.userInfo = userInfo;
    }

    public static class PerceptionBean {
        /**
         * inputText : {"text":"你叫什么"}
         */

        private InputTextBean inputText;

        public InputTextBean getInputText() {
            return inputText;
        }

        public void setInputText(InputTextBean inputText) {
            this.inputText = inputText;
        }

        public static class InputTextBean {
            /**
             * text : 你叫什么
             */

            private String text;

            public String getText() {
                return text;
            }

            public void setText(String text) {
                this.text = text;
            }
        }
    }

    public static class UserInfoBean {
        /**
         * apiKey : c00282de107144fb940adab994d9ff98
         * userId : 225167
         */

        private String apiKey;
        private String userId;

        public String getApiKey() {
            return apiKey;
        }

        public void setApiKey(String apiKey) {
            this.apiKey = apiKey;
        }

        public String getUserId() {
            return userId;
        }

        public void setUserId(String userId) {
            this.userId = userId;
        }
    }
}

再看看接受的Json数据

   {
    "emotion": {
        "robotEmotion": {
            "a": 0,
            "d": 0,
            "emotionId": 0,
            "p": 0
        },
        "userEmotion": {
            "a": 0,
            "d": 0,
            "emotionId": 0,
            "p": 0
        }
    },
    "intent": {
        "actionName": "",
        "code": 10004,
        "intentName": ""
    },
    "results": [{
        "groupType": 0,
        "resultType": "text",
        "values": {
            "text": "叫我阿紫就可以了"
        }
    }]
}

在bean文件夹类创建接受数据实体类Take(响应体)

/**
 * Created by 舍长 on 2018/5/10.
 * 描述: 接受的Json数据实体类
 */

public class Take {
    /**
     * emotion : {"robotEmotion":{"a":0,"d":0,"emotionId":0,"p":0},"userEmotion":{"a":0,"d":0,"emotionId":0,"p":0}}
     * intent : {"actionName":"","code":10004,"intentName":""}
     * results : [{"groupType":0,"resultType":"text","values":{"text":"叫我阿紫就可以了"}}]
     */

    private EmotionBean emotion;
    private IntentBean intent;
    private List<ResultsBean> results;

    public EmotionBean getEmotion() {
        return emotion;
    }

    public void setEmotion(EmotionBean emotion) {
        this.emotion = emotion;
    }

    public IntentBean getIntent() {
        return intent;
    }

    public void setIntent(IntentBean intent) {
        this.intent = intent;
    }

    public List<ResultsBean> getResults() {
        return results;
    }

    public void setResults(List<ResultsBean> results) {
        this.results = results;
    }

    public static class EmotionBean {
        /**
         * robotEmotion : {"a":0,"d":0,"emotionId":0,"p":0}
         * userEmotion : {"a":0,"d":0,"emotionId":0,"p":0}
         */

        private RobotEmotionBean robotEmotion;
        private UserEmotionBean userEmotion;

        public RobotEmotionBean getRobotEmotion() {
            return robotEmotion;
        }

        public void setRobotEmotion(RobotEmotionBean robotEmotion) {
            this.robotEmotion = robotEmotion;
        }

        public UserEmotionBean getUserEmotion() {
            return userEmotion;
        }

        public void setUserEmotion(UserEmotionBean userEmotion) {
            this.userEmotion = userEmotion;
        }

        public static class RobotEmotionBean {
            /**
             * a : 0
             * d : 0
             * emotionId : 0
             * p : 0
             */

            private int a;
            private int d;
            private int emotionId;
            private int p;

            public int getA() {
                return a;
            }

            public void setA(int a) {
                this.a = a;
            }

            public int getD() {
                return d;
            }

            public void setD(int d) {
                this.d = d;
            }

            public int getEmotionId() {
                return emotionId;
            }

            public void setEmotionId(int emotionId) {
                this.emotionId = emotionId;
            }

            public int getP() {
                return p;
            }

            public void setP(int p) {
                this.p = p;
            }
        }

        public static class UserEmotionBean {
            /**
             * a : 0
             * d : 0
             * emotionId : 0
             * p : 0
             */

            private int a;
            private int d;
            private int emotionId;
            private int p;

            public int getA() {
                return a;
            }

            public void setA(int a) {
                this.a = a;
            }

            public int getD() {
                return d;
            }

            public void setD(int d) {
                this.d = d;
            }

            public int getEmotionId() {
                return emotionId;
            }

            public void setEmotionId(int emotionId) {
                this.emotionId = emotionId;
            }

            public int getP() {
                return p;
            }

            public void setP(int p) {
                this.p = p;
            }
        }
    }

    public static class IntentBean {
        /**
         * actionName :
         * code : 10004
         * intentName :
         */

        private String actionName;
        private int code;
        private String intentName;

        public String getActionName() {
            return actionName;
        }

        public void setActionName(String actionName) {
            this.actionName = actionName;
        }

        public int getCode() {
            return code;
        }

        public void setCode(int code) {
            this.code = code;
        }

        public String getIntentName() {
            return intentName;
        }

        public void setIntentName(String intentName) {
            this.intentName = intentName;
        }
    }

    public static class ResultsBean {
        /**
         * groupType : 0
         * resultType : text
         * values : {"text":"叫我阿紫就可以了"}
         */

        private int groupType;
        private String resultType;
        private ValuesBean values;

        public int getGroupType() {
            return groupType;
        }

        public void setGroupType(int groupType) {
            this.groupType = groupType;
        }

        public String getResultType() {
            return resultType;
        }

        public void setResultType(String resultType) {
            this.resultType = resultType;
        }

        public ValuesBean getValues() {
            return values;
        }

        public void setValues(ValuesBean values) {
            this.values = values;
        }

        public static class ValuesBean {
            /**
             * text : 叫我阿紫就可以了
             */

            private String text;

            public String getText() {
                return text;
            }

            public void setText(String text) {
                this.text = text;
            }
        }
    }
}

两个实体类看起来有点复杂,但其实我们这个小例子只是需要其中的一个文本数据而已。然后我们创建net文件夹,在net文件夹类创建Api接口来写Retrofit的实现接口

/**
 * Created by 舍长 on 2018/5/10.
 * 描述: Retrofit接口
 */

public interface Api {
    //发送json数据形式的post请求,把网络请求接口的后半部分openapi/api/v写在里面
    //Ask是请求数据实体类,Take接受数据实体类
    @POST("openapi/api/v2")
    Call<Ask> saveUser(@Body Take take);
}

然后写我们的数据请求方法

/**
     * 请求数据
     *
     * @param text 输入框的发送数据
     */
    private void request(String text) {
//      把输入的文本数据存储在请求实体类中
        Ask ask = new Ask();
        Ask.UserInfoBean info = new Ask.UserInfoBean();
        info.setApiKey("c00282de107144fb940adab994d9ff98");//将机器人的key值填入
        info.setUserId("225167");//将用户id填入
        ask.setUserInfo(info);
        Ask.PerceptionBean.InputTextBean pre = new Ask.PerceptionBean.InputTextBean(text);//将要发送给机器人书文本天趣
        ask.setPerception(new Ask.PerceptionBean(pre));

//       创建Retrofit对象
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://openapi.tuling123.com/")//设置网络请求url,后面一段写在网络请求接口里面
                .addConverterFactory(GsonConverterFactory.create())//Gson解析
                .build();
//       创建网络请求接口的实例
        Api api = retrofit.create(Api.class);
//      Take为响应实体类,用来接受机器人返回的回复数据
        Call<Take> call = api.request(ask);
//
        call.enqueue(new Callback<Take>() {
//          请求成功
            @Override
            public void onResponse(Call<Take> call, Response<Take> response) {
//              接受到的机器人回复的数据
                String mText= response.body().getResults().get(0).getValues().getText();
//              把接受到的数据传入addData方法中,类型是TYPE_RECEIVED接受数据
                addData(mText, Chat.TYPE_RECEIVED);
                L.d("接受到的机器人回复的数据: "+mText);
            }
//            请求失败
            @Override
            public void onFailure(Call<Take> call, Throwable t) {
                L.d("请求失败: "+t.toString());
            }
        });
    }

代码有点多,但逻辑比不复杂,首先我们创建一个请求实体类,并把我们的机器人key,userId以及要发送的文本数据传入,最后使用Retrofit进行网络请求,接受到返回的数据,把返回的数据和数据类型传入到我们的addData方法中,显示到RecyclerView界面上,当然,这个方法是要在按钮的点击事件中调用的,接下来看看Activity的完整代码

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    //  聊天消息列表
    private RecyclerView recyclerView;

    //  输入框
    private EditText editText;

    //  发送按钮
    private Button mButton;

    //    对话信息集合
    private List<Chat> list = new ArrayList<>();

    //    适配器
    private RecyclerViewAdapter recyclerViewAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
//      初始化数据
        initView();
//       加载数据
        initData();
//      设置布局管理
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(linearLayoutManager);
        recyclerViewAdapter = new RecyclerViewAdapter(this, list);
        recyclerView.setAdapter(recyclerViewAdapter);
    }

    /**
     * 加载列表布局数据
     */
    private void initData() {
        Chat c1 = new Chat("你好,我叫阿紫", Chat.TYPE_RECEIVED);
        list.add(c1);
        Chat c2 = new Chat("你好,你现在会些什么呢?", Chat.TYPE_SENT);
        list.add(c2);
        Chat c3 = new Chat("我还在成长中,很多东西还不懂,但是你可以考考我", Chat.TYPE_RECEIVED);
        list.add(c3);
        Chat c4 = new Chat("1+1等于几?", Chat.TYPE_RECEIVED);
        list.add(c4);
    }

    /**
     * 初始化控件
     */
    private void initView() {
        recyclerView = findViewById(R.id.recycler);
        editText = findViewById(R.id.et_text);
        mButton = findViewById(R.id.btn_send);
        mButton.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_send:
                /**
                 * 1,获取输入框的内容
                 * 2,判断是否为空
                 * 3,发送后清空当前的输入框
                 */
//              1,获取输入框的内容
                String text = editText.getText().toString();
//              2,判断是否为空
                if (!TextUtils.isEmpty(text)) {
//                  把要发送的数据添加到addData方法中,并把数据类型也填入,这里我们的类型是TYPE_SENT,发送数据类型
                    addData(text, Chat.TYPE_SENT);
//                  清空输入框
                    editText.setText("");
//                  把发送的文本数据传递到request方法中,请求数据
                    request(text);
                }
                break;
        }
    }

    /**
     * 通过传递进来的test和type创建数据实体类,添加到聊天数据集合list中
     * @param text
     * @param type
     */
    private void addData(String text, int type) {
        Chat c = new Chat(text, type);
        list.add(c);
        //当有新消息时,刷新显示
        recyclerViewAdapter.notifyItemInserted(list.size() - 1);
        //定位的最后一行
        recyclerView.scrollToPosition(list.size() - 1);
    }

    /**
     * 请求数据
     *
     * @param text 输入框的发送数据
     */
    private void request(String text) {
//      把输入的文本数据存储在请求实体类中
        Ask ask = new Ask();
        Ask.UserInfoBean info = new Ask.UserInfoBean();
        info.setApiKey("c00282de107144fb940adab994d9ff98");//将机器人的key值填入
        info.setUserId("225167");//将用户id填入
        ask.setUserInfo(info);
        Ask.PerceptionBean.InputTextBean pre = new Ask.PerceptionBean.InputTextBean(text);//将要发送给机器人书文本天趣
        ask.setPerception(new Ask.PerceptionBean(pre));

//       创建Retrofit对象
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://openapi.tuling123.com/")//设置网络请求url,后面一段写在网络请求接口里面
                .addConverterFactory(GsonConverterFactory.create())//Gson解析
                .build();
//       创建网络请求接口的实例
        Api api = retrofit.create(Api.class);
//      Take为响应实体类,用来接受机器人返回的回复数据
        Call<Take> call = api.request(ask);
//
        call.enqueue(new Callback<Take>() {
//          请求成功
            @Override
            public void onResponse(Call<Take> call, Response<Take> response) {
//              接受到的机器人回复的数据
                String mText= response.body().getResults().get(0).getValues().getText();
//              把接受到的数据传入addData方法中,类型是TYPE_RECEIVED接受数据
                addData(mText, Chat.TYPE_RECEIVED);
                L.d("接受到的机器人回复的数据: "+mText);
            }
//            请求失败
            @Override
            public void onFailure(Call<Take> call, Throwable t) {
                L.d("请求失败: "+t.toString());
            }
        });
    }
}
目录
相关文章
|
9天前
|
SQL 监控 Java
Java连接池技术的最新发展,包括高性能与低延迟、智能化管理与监控、扩展性与兼容性等方面
本文探讨了Java连接池技术的最新发展,包括高性能与低延迟、智能化管理与监控、扩展性与兼容性等方面。同时,结合最佳实践,介绍了如何选择合适的连接池库、合理配置参数、使用监控工具及优化数据库操作,以实现高效稳定的数据库访问。示例代码展示了如何使用HikariCP连接池。
7 2
|
28天前
|
人工智能 搜索推荐 机器人
挑战未来职场:亲手打造你的AI面试官——基于Agents的模拟面试机器人究竟有多智能?
【10月更文挑战第7天】基于Agent技术,本项目构建了一个AI模拟面试机器人,旨在帮助求职者提升面试表现。通过Python、LangChain和Hugging Face的transformers库,实现了自动提问、即时反馈等功能,提供灵活、个性化的模拟面试体验。相比传统方法,AI模拟面试机器人不受时间和地点限制,能够实时提供反馈,帮助求职者更好地准备面试。
35 2
|
1月前
|
人工智能 缓存 Java
深入解析Spring AI框架:在Java应用中实现智能化交互的关键
【10月更文挑战第12天】Spring AI 是 Spring 框架家族的新成员,旨在满足 Java 应用程序对人工智能集成的需求。它支持自然语言处理、图像识别等多种 AI 技术,并提供与云服务(如 OpenAI、Azure Cognitive Services)及本地模型的无缝集成。通过简单的配置和编码,开发者可轻松实现 AI 功能,同时应对模型切换、数据安全及性能优化等挑战。
|
3月前
|
人工智能 算法 机器人
机器人版的斯坦福小镇来了,专为具身智能研究打造
【8月更文挑战第12天】《GRUtopia:城市级具身智能仿真平台》新论文发布,介绍了一款由上海AI实验室主导的大规模3D城市模拟环境——GRUtopia。此平台包含十万级互动场景与大型语言模型驱动的NPC系统,旨在解决具身智能研究中的数据稀缺问题并提供全面的评估工具,为机器人技术的进步搭建重要桥梁。https://arxiv.org/pdf/2407.10943
207 60
|
2月前
|
机器学习/深度学习 数据采集 JavaScript
ADR智能监测系统源码,系统采用Java开发,基于SpringBoot框架,前端使用Vue,可自动预警药品不良反应
ADR药品不良反应监测系统是一款智能化工具,用于监测和分析药品不良反应。该系统通过收集和分析病历、处方及实验室数据,快速识别潜在不良反应,提升用药安全性。系统采用Java开发,基于SpringBoot框架,前端使用Vue,具备数据采集、清洗、分析等功能模块,并能生成监测报告辅助医务人员决策。通过集成多种数据源并运用机器学习算法,系统可自动预警药品不良反应,有效减少药害事故,保障公众健康。
ADR智能监测系统源码,系统采用Java开发,基于SpringBoot框架,前端使用Vue,可自动预警药品不良反应
|
3月前
|
机器人 C# 人工智能
智能升级:WPF与人工智能的跨界合作——手把手教你集成聊天机器人,打造互动新体验与个性化服务
【8月更文挑战第31天】聊天机器人已成为现代应用的重要组成部分,提供即时响应、个性化服务及全天候支持。随着AI技术的发展,聊天机器人的功能日益强大,不仅能进行简单问答,还能实现复杂对话管理和情感分析。本文通过具体案例分析,展示了如何在WPF应用中集成聊天机器人,并通过示例代码详细说明其实现过程。使用Microsoft的Bot Framework可以轻松创建并配置聊天机器人,增强应用互动性和用户体验。首先,需在Bot Framework门户中创建机器人项目并编写逻辑。然后,在WPF应用中添加聊天界面,实现与机器人的交互。
90 0
|
3月前
|
机器人 TensorFlow 算法框架/工具
智能聊天机器人
【8月更文挑战第1天】智能聊天机器人。
101 2
|
3月前
|
人工智能 自然语言处理 安全
盘点国内:AI写作助手_ai智能问答机器人
AI写作助手是利用人工智能技术,特别是自然语言处理(NLP)技术,来辅助用户进行写作的工具。这类助手通过分析大量文本数据,能够理解语言的结构和含义,从而生成、编辑或优化文本内容。AI写作助手通常具有自动纠错、语法检查、内容生成和风格调整等功能,帮助用户提高写作效率和质量。
|
4月前
|
人工智能 移动开发 Java
Java智能之Spring AI:5分钟打造智能聊天模型的利器
尽管Python最近成为了编程语言的首选,但是Java在人工智能领域的地位同样不可撼动,得益于强大的Spring框架。随着人工智能技术的快速发展,我们正处于一个创新不断涌现的时代。从智能语音助手到复杂的自然语言处理系统,人工智能已经成为了现代生活和工作中不可或缺的一部分。在这样的背景下,Spring AI 项目迎来了发展的机遇。尽管该项目汲取了Python项目如LangChain和LlamaIndex的灵感,但Spring AI并不是简单的移植。该项目的初衷在于推进生成式人工智能应用程序的发展,使其不再局限于Python开发者。
145 2