前几天在慕课网上看到这个机器人视频感觉挺有意思的 索性就也跟着做了一个
慕课网上用的http请求 我使用的OkHttp和Retrofit请求接口,为什么使用这个
请求在前面博客中我也讲到了。
1.做这个能学到什么?
1.第三方API图灵机器人的使用
2.更加熟练请求接口(OkHttp和Retrofit)你也可以用 volley和http
3.Listview多种Item布局的处理实现聊天对话界面
2.效果图
3.代码展示
3.1添加依赖和和网络权限
<uses-permission android:name="android.permission.INTERNET/>
compile 'com.squareup.retrofit2:retrofit:2.2.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile "com.squareup.retrofit2:adapter-rxjava2:2.2.0"
3.2先请求成功
3.2.1 接口
package com.example.bx.robot;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;
/**
* Created by BX on 2017/8/24.
*/
public interface IUserBiz {
@GET("openapi/api")
Call<Result> getResult(@Query("key") String APIkey,@Query("info") String info);
}
3.2.2 OkHttp和Retrofit请求
package com.example.bx.robot;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
/**
* Created by BX on 2017/8/24.
*/
public class Retrofit_r {
public static final String URL="http://www.tuling123.com/";
private static final int TIME_OUT = 8;
private static Retrofit_r mInstance;
public IUserBiz mService;
public static Retrofit_r getInstance() {
if (mInstance == null) {
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(TIME_OUT, TimeUnit.SECONDS)
.build();
mInstance = new Retrofit_r(client);
}
return mInstance;
}
private Retrofit_r(OkHttpClient client) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
mService = retrofit.create(IUserBiz.class);
}
}
3.2.3 封装一个类储存数据
package com.example.bx.robot;
/**
* Created by BX on 2017/8/24.
*/
public class Result {
private String code;
private String text;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
3.2.4在主线程中调用
//APIkey是请求用的key,mag是你你输入的内容
Call<Result> call= Retrofit_r.getInstance().mService.getResult(APIkey,mag);
call.enqueue(new Callback<Result>() {
//请求成功调用的方法
@Override
public void onResponse(Call<Result> call, Response<Result> response) {
//根据你输入内容返回的结果用log打印出来
Log.d(TAG, "onResponse: "+response.body().getText());
}
请求失败调用的方法
@Override
public void onFailure(Call<Result> call, Throwable t) {
Toast.makeText(MainActivity.this, "请求失败", Toast.LENGTH_SHORT).show();
}
});
4.请求成功后 写聊天界面的布局
4.1需要两个布局 就像聊天界面一样左右两个 我只给一个右边 布局两个布局差不多
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/shijian1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_gravity="center"
android:background="#bebebe"
android:text="2012-12-12 12:12:12"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:gravity="right"
android:layout_height="wrap_content">
<TextView
android:layout_marginLeft="100dp"
android:id="@+id/tv_message1"
android:layout_marginTop="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="1dp"
android:background="@drawable/chatto_bg_pressed"
android:text="你好!就看"
android:textSize="20dp"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="60dp"
android:layout_marginLeft="10dp"
android:layout_height="70dp">
<ImageView
android:layout_gravity="center"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/mee"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="男神"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
4.2,主页面的布局
需要一个title 和聊天对应的发送和输入框 不懂我说的 可以看微信聊天界面
界面中间就是listview 显示聊天的记录
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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.bx.robot.MainActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar1"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:weightSum="1">
<TextView
android:id="@+id/toolbarTv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="20dp" />
</android.support.v7.widget.Toolbar>
<RelativeLayout
android:id="@+id/relativeLayout"
android:layout_width="match_parent"
android:layout_height="55dp"
android:background="@drawable/bottom_bar"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true">
<EditText
android:id="@+id/et_shuru"
android:layout_margin="5dp"
android:layout_width="270dp"
android:layout_height="45dp"
android:textSize="20dp"
android:background="@drawable/login_edit_normal"/>
<Button
android:id="@+id/but_fasong"
android:layout_width="70dp"
android:layout_height="50dp"
android:text="发送"
android:layout_alignParentTop="true"
android:layout_toRightOf="@+id/et_shuru"
android:layout_toEndOf="@+id/et_shuru" />
</RelativeLayout>
<ListView
android:id="@+id/listview"
android:divider="@null"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/relativeLayout"
android:transcriptMode="alwaysScroll"
android:layout_below="@id/toolbar1"></ListView>
</RelativeLayout>
5实现聊天界面
5.1封装一个类保存添加到listview中的数据
封装的时候注意Type的
//枚举:是一种新型的变量,他可以控制设定的内容
package com.example.bx.robot;
import java.lang.reflect.Type;
import java.util.Date;
/**
* Created by BX on 2017/8/24.
*/
public class ChatMessage {
private String message;
private String name;
private Date date;
private Type type;
public ChatMessage(){
// TODO Auto-generated constructor stub
}
public ChatMessage(String message, Date date, Type type) {
super();
this.message = message;
this.date = date;
this.type = type;
}
{
}
//枚举:是一种新型的变量,他可以控制设定的内容
public enum Type{
OUTCOMING,INCOMING
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
}
5.2 Listview 的适配器
添加两个方法getViewTypeCount和getItemViewType
package com.example.bx.robot;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.security.KeyRep;
import java.text.SimpleDateFormat;
import java.util.List;
/**
* Created by BX on 2017/8/24.
*/
public class MyAdapter extends BaseAdapter {
private LayoutInflater inflater;
private List<ChatMessage> mDates;
public MyAdapter(Context context, List<ChatMessage> lists){
this.inflater=LayoutInflater.from(context);
this.mDates=lists;
}
@Override
public int getCount() {
return mDates.size();
}
@Override
public Object getItem(int i) {
return mDates.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
/**
* 协定listview中有几种类型的item
*@Override
*/
@Override
public int getViewTypeCount() {
return 2;
}
/**
* 判断枚举Type的类型然后确定填充数据的布局
* @Override
*/
@Override
public int getItemViewType(int position) {
ChatMessage chatMessage=mDates.get(position);
if(chatMessage.getType()== ChatMessage.Type.OUTCOMING) {
return 0;
}
return 1;
}
@Override
public View getView(int i, View convertView, ViewGroup viewGroup) {
ViewHolder viewHolder;
//如果converView为空,就去找到布局文件并填充内容
if(convertView==null){
//判断Type的类型,如果为0代表用户输入,则convertView填充的数据界面为ListView的右边
if (getItemViewType(i)==0){
convertView=inflater.inflate(R.layout.list1_item,null);
viewHolder=new ViewHolder();
viewHolder.tv_date=(TextView)convertView.findViewById(R.id.shijian1);
viewHolder.tv_message=(TextView)convertView.findViewById(R.id.tv_message1);
}else {
convertView=inflater.inflate(R.layout.list_item,null);
viewHolder=new ViewHolder();
viewHolder.tv_date=(TextView)convertView.findViewById(R.id.shijian);
viewHolder.tv_message=(TextView)convertView.findViewById(R.id.tv_message);
}
convertView.setTag(viewHolder);
}else {
viewHolder=(ViewHolder)convertView.getTag();
}
//向ListView中填充数据
ChatMessage date=mDates.get(i);
SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
viewHolder.tv_date.setText(df.format(date.getDate()));
viewHolder.tv_message.setText(date.getMessage());
return convertView;
}
class ViewHolder {
TextView tv_date;
TextView tv_message;
}
}
mainActivity中的代码
package com.example.bx.robot;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
public static final String APIkey="aaebb21ed18948598e0721a599826db2";
private IUserBiz iUserBiz;
private Toolbar toolbar;
private TextView toolbarTv;
String mag;
private ListView mlistview;
private MyAdapter madapter;
private EditText mtv_input;
private Button button;
private List<ChatMessage> mDatas;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle("");
title();
init();
initData();
}
//向ChatMessage中添加一条数据你 第一条数据
private void initData() {
mDatas=new ArrayList<>();
ChatMessage chat=new ChatMessage("您好,我是蛋蛋,很高兴为您服务!!",new Date(), ChatMessage.Type.INCOMING);
mDatas.add(chat);
madapter=new MyAdapter(MainActivity.this,mDatas);
mlistview.setAdapter(madapter);
}
//初始化
private void init() {
mlistview= (ListView) findViewById(R.id.listview);
mtv_input= (EditText) findViewById(R.id.et_shuru);
button= (Button) findViewById(R.id.but_fasong);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ButClick();
}
});
}
//把输出的内容添加到ChatMessage
private void ButClick(){
mag=mtv_input.getText().toString();
if(TextUtils.isEmpty(mag)){
Toast.makeText(this, "输出框不能为空", Toast.LENGTH_SHORT).show();
}
ChatMessage chat=new ChatMessage();
chat.setDate(new Date());
chat.setMessage(mag);
chat.setType(ChatMessage.Type.OUTCOMING);
mDatas.add(chat);
//刷新适配器 吧ChatMessage的内容在listview中显示出来
madapter.notifyDataSetChanged();
mtv_input.setText("");
checkCardInfo();
}
private void title() {
toolbarTv= (TextView) findViewById(R.id.toolbarTv);
toolbar= (Toolbar) findViewById(R.id.toolbar1);
toolbarTv.setText("社会我荣哥人狠话不多");
setSupportActionBar(toolbar);
}
//最后吧输入的数据添加到接口请求中去
//返回数据并刷新适配器让数据在listview中显示出来
private void checkCardInfo() {
Call<Result> call= Retrofit_r.getInstance().mService.getResult(APIkey,mag);
call.enqueue(new Callback<Result>() {
@Override
public void onResponse(Call<Result> call, Response<Result> response) {
Log.d(TAG, "onResponse: "+response.body().getText());
ChatMessage chat=new ChatMessage();
chat.setDate(new Date());
chat.setMessage(response.body().getText());
chat.setType(ChatMessage.Type.INCOMING);
mDatas.add(chat);
madapter.notifyDataSetChanged();
}
@Override
public void onFailure(Call<Result> call, Throwable t) {
Toast.makeText(MainActivity.this, "请求失败", Toast.LENGTH_SHORT).show();
}
});
}
}