使用kotlin实现一个智能聊天机器人「图灵机器人,Android,kotlin」

简介: 推荐一部关于Ai的系列漫画,叫做代码的深渊相关代码已经上传到Github的仓库kotlinRobot先来看一下实现的效果图智能机器人效果预览~1.gif文章思路参考自刘桂林前辈的带领新手快速开发APP ,聊天界面代码参考于郭神的第一行代码第二版第三章3.7节,由衷感谢。

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

相关代码已经上传到Github的仓库kotlinRobot

先来看一下实现的效果图

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

文章思路参考自刘桂林前辈的带领新手快速开发APP ,聊天界面代码参考于郭神的第一行代码第二版第三章3.7节,由衷感谢。自己也写过一篇讲解kotlin几个基础小知识点的文章,kotlin初体验,文中不足之处,希望能得到您的指正,十分感谢。

布局文件

创建我们的项目,勾选kotlin支持,并在build.gradle下填入依赖

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

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



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




    

    

        

        




   
   

先来写一个Log工具类,方便测试,创建util包,在util下创建L类

/**
 * Created by 舍长 on 2018/4/27.
 * 在kotlin中,加了object后,L类就成为了一个单例模式的类,相当于帮我们省略掉了以前Java实现单例的代码
 * 最后我们可以直接L.d调用类中的方法
 */
object L {

    //    TAG
    public var TAG: String = "tonJies"

    fun d(test: String) {
        Log.d(TAG, test)
    }
}

我们回到Activity,在activity的导包中添加这一行,我们就不需要再写findViewByid了

import kotlinx.android.synthetic.main.activity_main.*

我们给发送按钮设置点击事件,回调监听,在点击事件里面进行输入框内容的处理,依次是:

1,获取输入框的内容

2,判断是否为空

3,点击发送按钮后清空当前输入框

//加了这一行后我们就不需要再findViewById了
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity(), View.OnClickListener {


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
//       设置控件的回调监听
        init()
        L.d("Hello")
    }

    /**
     * 设置控件的回调监听
     */
    private fun init() {
        btn_send.setOnClickListener(this)
    }


    /**
     * 重写OnClickListener接口的onClick方法
     */
    override fun onClick(v: View?) {
        when (v!!.id) {
            R.id.btn_send -> {
                /**
                 * 1,获取输入框的内容
                 * 2,判断是否为空
                 * 4,发送后清空当前的输入框
                 */
//               1,获取输入框的内容
                val text: String = et_text.text.toString()
//               2,判断是否为空
                if (!TextUtils.isEmpty(text)) {
                    L.d("不为空")
                } else {
                    L.d("为空")
                }
            }
        }
    }

}

聊天界面的书写

思路是使用recyclerView作为聊天对话列表的显示控件。让我们先在build.gradle下添加圆形化图片的框架CircleImageView,用来对头像的圆形处理

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

创建bean包,在文件夹类创建实体类Chat,用于储存后面的聊天数据

/**
 * data 数据类,默认帮我们实现了实体类的几个方法,例如toString,赋值
 * text 聊天文本数据
 * type 用来标示此对话类型是属于左边机器人发来的文本类型还是我们向机器人发送的文本类型,后面我们就根据这个属性来
 */
data class Chat(var text: String,var type: Int) {

}

这里的实体类和我们在Java中的实体类写法有些不同,data关键字在kotlin是数据类的意思,它的作用是帮我们默认生成了几个常用方法,如toString()方法,而且加了data后,括号里面的参数就可直接作为属性值使用了,不需要再像Java一样,在类中声明,然后再到构造方法中进行赋值。

然后我们开始写recyclerview的item布局,命名为chat_item,图片素材参考源代码




    

        

        
    

    

        

        
    


我们先把左右的消息都写出来,在后面Adapter加载每一个item的时候我们再根据Chat的type类型来决定要隐藏那边的布局

这里写图片描述

接下来开始写RecyclerView的适配器

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

class RecyclerViewAdapter : RecyclerView.Adapter {


    //    上下文
    private var context: Context? = null

    //   用户聊天消息列表
    private var mlist = ArrayList()

    /**
     * 空参构造方法
     */
    constructor() {

    }

    /**
     * context 上下文
     * list  对话列表聊天数据
     */
    constructor(context: Context, list: ArrayList) {
        this.context = context
        this.mlist = list
    }

    /**
     * 加载item布局
     */
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.chat_item, parent, false)
        return ViewHolder(view)
    }


    /**
     *  在onBindViewHolder()方法中判断是要显示对应position位置的item布局要隐藏哪边的布局
     *  我们用0来表示机器人的文本类型,用1来表示用户的文本类型。
     */
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val chat = mlist[position]
//
        if (chat.type == 0) {
            //   如果数据是机器人的文本类型,就显示左边的布局,隐藏右边的布局
            holder.leftLayout.visibility = View.VISIBLE
            holder.rightLayout.visibility = View.GONE
            //    把文本设置到机器人对话框内
            holder.leftChat.text = chat.text
            //
        } else if (chat.type == 1) {
            //   如果数据是用户的文本类型,就隐藏左边布局,显示右边的布局
            holder.rightLayout.visibility = View.VISIBLE
            holder.leftLayout.visibility = View.GONE
            //            把文本设置到用户对话框内
            holder.rightChat.text = chat.text
        }
    }

    override fun getItemCount(): Int {
        return mlist.size
    }

    /**
     * 声明控件
     *
     */
    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        //      左边的机器人布局
        var leftLayout: LinearLayout

        //      右边的用户布局
        var rightLayout: LinearLayout

        //      左边的机器人文本
        var leftChat: TextView

        //      右边的用户发送文本
        var rightChat: TextView

        /**
         *
         */
        init {
            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)
        }
    }
}

我们声明一个mlist集合来进行数据的传递,在onBindViewHolder方法中使用0作为机器人文本的标识,使用1作为用户文本的标识,根据标识的不同来决定显示item哪边的布局,再把Chat类对象的text属性传入要显示布局的TextView上

Adapter写好后我们在Activity中进行数据的填充,并设置RecyclerView的布局管理器,以及适配器

//加了这一行后我们就不需要再findViewById了
import kotlinx.android.synthetic.main.activity_main.*

/**
 * 继承于AppCompatActivity()
 * 继承于View.OnClickListener接口,复写onClick点击事件
 */
class MainActivity : AppCompatActivity(), View.OnClickListener {
    //    对话列表集合
    private var list = ArrayList()

    //    recyclerView适配器
    private var recyclerViewAdapter = RecyclerViewAdapter(this, list)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
//       设置控件的回调监听
        init()
//       加载数据
        initData();
        //       设置recyclerView布局管理
        val linearLayoutManager = LinearLayoutManager(this)
//       把布局管理器添加到recyclerView中
        recycler.setLayoutManager(linearLayoutManager)
//       把适配器添加到recyclerView中
        recycler.setAdapter(recyclerViewAdapter)
    }

    /**
     * 设置控件的回调监听
     */
    private fun init() {
        btn_send.setOnClickListener(this)
    }

    /**
     * 重写OnClickListener接口的onClick方法
     */
    override fun onClick(p0: View?) {
        when (p0!!.id) {
            R.id.btn_send -> {
                /**
                 * 1,获取输入框的内容
                 * 2,判断是否为空
                 * 4,发送后清空当前的输入框
                 */
//               1,获取输入框的内容
                val text: String = et_text.text.toString()
//               2,判断是否为空
                if (!TextUtils.isEmpty(text)) {
                    L.d(text + "")
                    addData(text, 1)
                } else {
                    L.d("你的输入为空")
                }
            }
        }
    }

    /**
     * 通过传递进来的test和type创建数据实体类,添加到聊天数据集合list中
     * @param text 文本信息
     * @param type 标示类型
     */
    private fun addData(mtext: String, mtype: Int) {
        L.d(mtext + "" + mtype)
        var c = Chat(mtext, mtype)
        list.add(c)

//      更新适配器,插入新数据
        recyclerViewAdapter.notifyItemInserted(list.size - 1)
//      把显示的位置定位到最后一行
        recycler.scrollToPosition(list.size - 1)
    }

    /**
     * 模拟加载数据
     */
    private fun initData() {
//      传入0到c1的type属性来表示该数据是接受到的数据,然后把实体类c1添加到对话列表集合中
        var c1: Chat = Chat("你好,我叫阿紫", 0)
        list.add(c1)
//      使用1到c2的type属性来表示该数据是输入框的发送数据,然后把实体类c2添加到对话列表集合中
        var c2: Chat = Chat("你好,你现在会些什么呢?", 1)
        list.add(c2)
//      接受数据
        var c3: Chat = Chat("我还在成长中,很多东西还不懂,但是你可以考考我\"", 0)
        list.add(c3)
//      发送数据
        var c4: Chat = Chat("1+1等于几?\"", 1)
        list.add(c4)
    }


}

我们声明了一个集合list来存储我们的聊天数据,在initData()方法中加载数据,然后设置RecyclerView的布局管理器,并将集合数据填充到适配器中。

在按钮点击事件里获取数据框的输入内容,设置标识为1,填充到list集合中,刷新适配器并把显示的地方定位到最后一行,清空输入框。

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

这里写图片描述

后端接口的调试

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

这里写图片描述
  • Post请求
  • 接口地址:

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

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

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

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

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

这里写图片描述

进行调试

这里写图片描述

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

 {
    "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的自由及开放源代码的操作系统,主要使用于移...

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

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

对接网络接口:

我们采用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文件中添加网络权限


让我们来看看要作为body发送给服务端是Json数据

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

我们在bean包创建实体类Ask,作为发送请求的请求体。

使用Java代码时,生成JavaBean实体类一般使用JsonFormat插件进行生成,但是JsonFormat在Kotlin中是使用不了的,所以我们要使用kotlin的生成JavaBean插件,JSON To Kotlin

打开File-Setting-Plugins-Browse respositories 搜索 JSON To Kotlin Class 安装,然后使用它生成Ask请求体实体类

这里写图片描述

打开Setting-Other-勾选Enable Inner Class Model 的作用是使得生成的数据都以内部类的形式出现,不勾选的话会默认把所有的类都生成在包内

/**
 * 请求数据请求体实体类
 * reqType 传0就行
 */
data class Ask(val reqType: Int,
        val perception: Perception,
        val userInfo: UserInfo
) {
    data class Perception(
            val inputText: InputText
    ) {
//      要发送的文本消息
        data class InputText(
                val text: String
        )
    }

    data class UserInfo(
//          机器人apiKey
            val apiKey: String,
//          用户id
            val userId: String
    )
}

上面提到加了data关键字,会帮我们默认生成几个方法,比如toString(),格式是例如"User(name=John, age=42)";但是要注意的一点是加了data,类就不能有无参构造方法了,如果我们输入这样的代码,var ask=Ask(),那就会报错了。

再看看响应体的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(响应体)


/**
 * 返回数据响应体实体类
 */
data class Take(
        val emotion: Emotion,
        val intent: Intent,
        val results: List
) {
    data class Emotion(
            val robotEmotion: RobotEmotion,
            val userEmotion: UserEmotion
    ) {
        data class UserEmotion(
                val a: Int,
                val d: Int,
                val emotionId: Int,
                val p: Int
        )

        data class RobotEmotion(
                val a: Int,
                val d: Int,
                val emotionId: Int,
                val p: Int
        )
    }

    data class Result(
            val groupType: Int,
            val resultType: String,
            val values: Values
    ) {
        //      返回文本 "叫我阿紫就可以了"
        data class Values(
                val text: String
        )
    }

    data class Intent(
            val actionName: String,
            val code: Int,
            val intentName: String
    )
}

响应体实体类中,我们关注的只有text返回的文本数据

接下来我们创建net包,在net包内写一个Retrofit的实现接口


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

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

之后就直接在MainActivity写我们的数据请求方法了


//加了这一行后我们就不需要再findViewById了
import kotlinx.android.synthetic.main.activity_main.*
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

/**
 * 继承于AppCompatActivity()
 * 继承于View.OnClickListener接口,复写onClick点击事件
 */
class MainActivity : AppCompatActivity(), View.OnClickListener {
    //    对话列表集合
    private var list = ArrayList()

    //    recyclerView适配器
    private var recyclerViewAdapter = RecyclerViewAdapter(this, list)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
//       设置控件的回调监听
        init()
//       加载数据
        initData()
        //       设置recyclerView布局管理
        val linearLayoutManager = LinearLayoutManager(this)
//       把布局管理器添加到recyclerView中
        recycler.setLayoutManager(linearLayoutManager)
//       把适配器添加到recyclerView中
        recycler.setAdapter(recyclerViewAdapter)


    }

    /**
     * 设置控件的回调监听
     */
    private fun init() {
        btn_send.setOnClickListener(this)
    }

    /**
     * 重写OnClickListener接口的onClick方法
     */
    override fun onClick(p0: View?) {
        when (p0!!.id) {
            R.id.btn_send -> {
                /**
                 * 1,获取输入框的内容
                 * 2,判断是否为空
                 * 4,发送后清空当前的输入框
                 */
//               1,获取输入框的内容
                val text: String = et_text.text.toString()
//               2,判断是否为空
                if (!TextUtils.isEmpty(text)) {
                    addData(text, 1)
                    request(text)
                } else {
                    L.d("你的输入为空")
                }
            }
        }
    }

    /**
     * 通过传递进来的test和type创建数据实体类,添加到聊天数据集合list中
     * @param text 文本信息
     * @param type 标示类型
     */
    private fun addData(mtext: String, mtype: Int) {
        L.d("addData  mtext:" + mtext + "  mtype" + mtype)
        var c = Chat(mtext, mtype)
        list.add(c)
//      更新适配器,插入新数据
        recyclerViewAdapter.notifyItemInserted(list.size - 1)
//      把显示的位置定位到最后一行
        recycler.scrollToPosition(list.size - 1)
    }

    /**
     * 模拟加载数据
     */
    private fun initData() {
//      传入0到c1的type属性来表示该数据是接受到的数据,然后把实体类c1添加到对话列表集合中
        var c1: Chat = Chat("你好,我叫阿紫", 0)
        list.add(c1)
//      使用1到c2的type属性来表示该数据是输入框的发送数据,然后把实体类c2添加到对话列表集合中
        var c2: Chat = Chat("你好,你现在会些什么呢?", 1)
        list.add(c2)
//      接受数据
        var c3: Chat = Chat("我还在成长中,很多东西还不懂,但是你可以考考我\"", 0)
        list.add(c3)
//      发送数据
        var c4: Chat = Chat("1+1等于几?\"", 1)
        list.add(c4)
        //      接受数据
        var c5: Chat = Chat("1+1=2", 0)
        list.add(c5)
    }


    /**
     * 请求数据
     *
     */
    private fun request(mText: String) {
//      存储要发送的的文本
        var perceotion = Ask.Perception(Ask.Perception.InputText(mText))
//      设置用户id和ApidKey
        val userInfo = Ask.UserInfo("c00282de107144fb940adab994d9ff98", "225167")
//      填充到请求体Ask中
        var ask = Ask(0, perceotion, userInfo)

//      使用retiofit进行请求
        var retrofit = Retrofit.Builder()
                .baseUrl("http://openapi.tuling123.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .build()
//      创建网络请求接口的实例
        val api = retrofit.create(Api::class.java)
//
        val call = api.request(ask)

//
        call.enqueue(object : retrofit2.Callback {
            //          请求成功
            override fun onResponse(call: retrofit2.Call, response: Response) {
                //              接受到的机器人回复的数据
                L.d("返回的全部信息:" + response.body().toString())
                var text = response.body().results.get(0).values.text
                //在这里进行处理,防止接口没有返回数据时抛出异常
                if (text == null) {
                    text = "我还小,不知道这句话的意思"
                    //把接受到的数据传入addData方法中,类型是TYPE_RECEIVED接受数据
                    addData(text, 0)
                } else {
                    //把接受到的数据传入addData方法中,类型是TYPE_RECEIVED接受数据
                    addData(text, 0)
                }
                L.d("接受到的机器人回复的数据: " + text)
            }

            //            请求失败
            override fun onFailure(call: retrofit2.Call, t: Throwable) {
                L.d("请求失败: " + t.toString())
            }
        })
    }
}

在方法中我们创建了一个Ask请求体对象,把机器人key,userId和要发送的文本传入,注意reqType我们传入0就可以了。使用Retrofit进行网络请求,在回调里接收返回的文本,把返回的文本传入addData中,标识为0,机器人文本。

当然request方法是在点击按钮时调用的,Activty完整代码

//加了这一行后我们就不需要再findViewById了
import kotlinx.android.synthetic.main.activity_main.*
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

/**
 * 继承于AppCompatActivity()
 * 继承于View.OnClickListener接口,复写onClick点击事件
 */
class MainActivity : AppCompatActivity(), View.OnClickListener {
    //    对话列表集合
    private var list = ArrayList()

    //    recyclerView适配器
    private var recyclerViewAdapter = RecyclerViewAdapter(this, list)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
//       设置控件的回调监听
        init()
//       加载数据
        initData()
        //       设置recyclerView布局管理
        val linearLayoutManager = LinearLayoutManager(this)
//       把布局管理器添加到recyclerView中
        recycler.setLayoutManager(linearLayoutManager)
//       把适配器添加到recyclerView中
        recycler.setAdapter(recyclerViewAdapter)


    }

    /**
     * 设置控件的回调监听
     */
    private fun init() {
        btn_send.setOnClickListener(this)
    }

    /**
     * 重写OnClickListener接口的onClick方法
     */
    override fun onClick(p0: View?) {
        when (p0!!.id) {
            R.id.btn_send -> {
                /**
                 * 1,获取输入框的内容
                 * 2,判断是否为空
                 * 4,发送后清空当前的输入框
                 */
//               1,获取输入框的内容
                val text: String = et_text.text.toString()
//               2,判断是否为空
                if (!TextUtils.isEmpty(text)) {
                    addData(text, 1)
                    request(text)
                } else {
                    L.d("你的输入为空")
                }
            }
        }
    }

    /**
     * 通过传递进来的test和type创建数据实体类,添加到聊天数据集合list中
     * @param text 文本信息
     * @param type 标示类型
     */
    private fun addData(mtext: String, mtype: Int) {
        L.d("addData  mtext:" + mtext + "  mtype" + mtype)
        var c = Chat(mtext, mtype)
        list.add(c)
//      更新适配器,插入新数据
        recyclerViewAdapter.notifyItemInserted(list.size - 1)
//      把显示的位置定位到最后一行
        recycler.scrollToPosition(list.size - 1)
    }

    /**
     * 模拟加载数据
     */
    private fun initData() {
//      传入0到c1的type属性来表示该数据是接受到的数据,然后把实体类c1添加到对话列表集合中
        var c1: Chat = Chat("你好,我叫阿紫", 0)
        list.add(c1)
//      使用1到c2的type属性来表示该数据是输入框的发送数据,然后把实体类c2添加到对话列表集合中
        var c2: Chat = Chat("你好,你现在会些什么呢?", 1)
        list.add(c2)
//      接受数据
        var c3: Chat = Chat("我还在成长中,很多东西还不懂,但是你可以考考我\"", 0)
        list.add(c3)
//      发送数据
        var c4: Chat = Chat("1+1等于几?\"", 1)
        list.add(c4)
        //      接受数据
        var c5: Chat = Chat("1+1=2", 0)
        list.add(c5)
    }


    /**
     * 请求数据
     *
     */
    private fun request(mText: String) {
//      存储要发送的的文本
        var perceotion = Ask.Perception(Ask.Perception.InputText(mText))
//      设置用户id和ApidKey
        val userInfo = Ask.UserInfo("c00282de107144fb940adab994d9ff98", "225167")
//      填充到请求体Ask中
        var ask = Ask(0, perceotion, userInfo)

//      使用retiofit进行请求
        var retrofit = Retrofit.Builder()
                .baseUrl("http://openapi.tuling123.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .build()
//      创建网络请求接口的实例
        val api = retrofit.create(Api::class.java)
//
        val call = api.request(ask)

//
        call.enqueue(object : retrofit2.Callback {
            //          请求成功
            override fun onResponse(call: retrofit2.Call, response: Response) {
                //              接受到的机器人回复的数据
                L.d("返回的全部信息:" + response.body().toString())
                var text = response.body().results.get(0).values.text
                //在这里进行处理,防止接口没有返回数据时抛出异常
                if (text == null) {
                    text = "我还小,不知道这句话的意思"
                    //把接受到的数据传入addData方法中,类型是TYPE_RECEIVED接受数据
                    addData(text, 0)
                } else {
                    //把接受到的数据传入addData方法中,类型是TYPE_RECEIVED接受数据
                    addData(text, 0)
                }
                L.d("接受到的机器人回复的数据: " + text)
            }

            //            请求失败
            override fun onFailure(call: retrofit2.Call, t: Throwable) {
                L.d("请求失败: " + t.toString())
            }
        })
    }
}

这一小节就到这里啦,谢谢您的观看,文中不足之处,希望能得到您的指正,期待您的留言

目录
相关文章
|
3月前
|
Android开发 Kotlin
Android经典面试题之Kotlin的==和===有什么区别?
本文介绍了 Kotlin 中 `==` 和 `===` 操作符的区别:`==` 用于比较值是否相等,而 `===` 用于检查对象身份。对于基本类型,两者行为相似;对于对象引用,`==` 比较值相等性,`===` 检查引用是否指向同一实例。此外,还列举了其他常用比较操作符及其应用场景。
193 93
|
8天前
|
自然语言处理 算法 机器人
智能电话销售机器人源码搭建部署系统电话机器人源码
智能电话销售机器人源码搭建部署系统电话机器人源码
19 4
|
19天前
|
机器学习/深度学习 传感器 算法
智能机器人在工业自动化中的应用与前景###
本文探讨了智能机器人在工业自动化领域的最新应用,包括其在制造业中的集成、操作灵活性和成本效益等方面的优势。通过分析当前技术趋势和案例研究,预测了智能机器人未来的发展方向及其对工业生产模式的潜在影响。 ###
73 9
|
20天前
|
安全 IDE Java
Kotlin教程笔记(3) - 空类型和智能类型转换
Kotlin教程笔记(3) - 空类型和智能类型转换
|
27天前
|
安全 IDE Java
Kotlin教程笔记(3)- 空类型和智能类型转换
本教程详细讲解了Kotlin中的空类型、非空与可空类型、可空类型操作符、安全调用操作符、Elvis运算符、非空断言运算符以及智能类型转换等内容,帮助开发者更好地理解和使用Kotlin的空安全机制。适合希望深入了解Kotlin语法的开发者。快速入门请参考“简洁”系列教程。
28 3
|
11天前
|
机器学习/深度学习 人工智能 运维
电话机器人源码-智能ai系统-freeswitch-smartivr呼叫中心-crm
电话机器人源码-智能ai系统-freeswitch-smartivr呼叫中心-crm
31 0
|
2月前
|
存储 前端开发 测试技术
Android kotlin MVVM 架构简单示例入门
Android kotlin MVVM 架构简单示例入门
31 1
|
15天前
|
机器人 人机交互 语音技术
智能电销机器人源码部署安装好后怎么运行
销售打电销,其中90%电销都是无效的,都是不接,不要等被浪费了这些的精力,都属于忙于筛选意向客户,大量的人工时间都耗费在此了。那么,有这种新型的科技产品,能为你替代这些基本的工作,能为你提升10倍的电销效果。人们都在关心智能语音客服机器人如何高效率工作的问题,今天就为大家简单的介绍下:1、智能筛选系统:电销机器人目前已经达到一个真人式的专家级的销售沟通水平,可以跟客户沟通,筛选意向,记录语音和文字通话记录,快速帮助电销企业筛选意向客户,大大的节约了筛选时间成本和人工成本。2、高速运转:在工作效率上,人工电销员,肯定跟不上智能语音机器人,机器人自动拨出电话,跟客户交谈。电话机
92 0
|
2月前
|
安全 IDE Java
Kotlin 学习笔记- 空类型和智能类型转换
Kotlin 学习笔记聚焦于空类型和智能类型转换,深入解析非空与可空类型、安全调用操作符、Elvis 运算符、非空断言运算符及智能类型转换等内容,助你高效掌握 Kotlin 语言特性,避免 NullPointException 异常,提升代码质量。
29 2
|
2月前
|
调度 Android开发 开发者
构建高效Android应用:探究Kotlin多线程优化策略
【10月更文挑战第11天】本文探讨了如何在Kotlin中实现高效的多线程方案,特别是在Android应用开发中。通过介绍Kotlin协程的基础知识、异步数据加载的实际案例,以及合理使用不同调度器的方法,帮助开发者提升应用性能和用户体验。
53 4