从零开始玩Android 实战项目 5 (前后端交互)

1,987 阅读4分钟

Hello 小伙伴们大家好,我是Krain

先简单介绍一下自己的情况:毕业没多久的社畜小牛犊,目前已工作一年的初级Java(可能还算不上),凭借自己对编程开发的热爱踏上这个卷不死就往死里卷的行业,接下来我将以自己CV战士(新手小白)的身份记录成长历程、督促自己学习、遇见错误记录、加深编码记忆、技术相互交流。

特此声明:本人萌新,文章如提及技术分析均为自己理解,有错还请大佬纠正

经过前4章,我们完成了登录注册页面并实现了两个页面的相互跳转,有了页面,就要给他赋予功能,也就是我们常说的前后端交互,很多小伙伴有这么一种情况,页面我能做出来,后端接口我也能写出来,但就是不知道怎么将他两绑定在一起实施交互。

交互其实并不难,只需要确定好前端发送的参数格式与后端接口接收的格式一致,并且请求方法一致就可以了,通俗点说,请求方法常见的无非就是get和post,用get发送请求,接口就用@GetMapping,post请求就用@PostMapping,数据格式呢就是 看前端发送的数据是啥样子的,例如常见的Json格式、Map键值对、list列表、表单之类的,直接上代码。

我们这里使用okhttp来实施通信,需要在build.gradle中导入依赖,

implementation 'com.squareup.okhttp3:okhttp:4.4.1'

找到要实行通信控件所属xml对应的Activity,用findViewById()拿到我们输入值的控件的值,一般来说应该都是ExidText,转换成字符串,注意getText()前是个整体,例如

String username=((EditText)findViewById(R.id.username)).getText().toString();
String password=((EditText)findViewById(R.id.password)).getText().toString();

由于后端我们是创建了实体类来接收参数

public boolean login(User user){
    。。。
    }

前端用FormBody来打包要传的参数,双引号中并非随便定义,需要和实体类接收的名字保持一致,有几条参数就有几个add

FormBody formBody=new FormBody.Builder().add("mobile",username).add("password",password).build();

接着我们用okhttp发送请求,这一步就是前后端交互的桥梁

OkHttpClient client=new OkHttpClient();
Request request=new Request.Builder()
        .url("http://自己ip地址:端口号/请求路径")
        .post(formBody)
        .build();

端口号就是后端在SpingBoot配置文件中定义的,请求路径就是@PostMapping定义的路径,如果类上定义了@RequestMapping千万别把他漏掉

既然请求了,就肯定会有响应,告诉你有没有请求成功,响应接收

Response response=client.newCall(request).execute();

由于请求可能会失败,我们需要对整段代码加上try catch捕获异常。

好了,至此为止我们已经交互成功了,成功了怎么样、失败了又怎么样,if语句大家应该都会写了吧,和java格式一样。

Android的提示信息格式如下

Toast.makeText(当前Activity名称.this,"登录成功",Toast.LENGTH_SHORT).show();

以下是登录页面Activity完整代码,注册页面类似

package com.example.firstdemo;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;

import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class LoginActivity extends AppCompatActivity{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        Button loginButton=(Button) findViewById(R.id.login);        //初始化控件
        Button registButton=(Button) findViewById(R.id.registration);//初始化控件
        loginButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                System.out.println("点击按钮了");
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                        String username=((EditText)findViewById(R.id.username)).getText().toString(); //获取文本框输入的内容
                        String password=((EditText)findViewById(R.id.password)).getText().toString(); //获取文本框输入的内容
                        FormBody formBody=new FormBody.Builder().add("mobile",username).add("password",password).build();
                        OkHttpClient client=new OkHttpClient();  //建立通信,请求与响应
                        Request request=new Request.Builder()
                                .url("http://111.111.1.11/api/login") 
                                .post(formBody)
                                .build();
                        Response response=client.newCall(request).execute();
                            if (!(username.isEmpty()||password.isEmpty())){ //判断文本框内容是否为空
                                if (Boolean.parseBoolean(response.body().string())){ //后端接收到的值转化成true或false,注意这里不是toString
                                    Intent intent=new Intent(LoginActivity.this,MainActivity.class); //登录成功跳转页面
                                    startActivity(intent);
                                    runOnUiThread(new Runnable() { //每次使用Toast尽量新开一个子线程,防止操作不流畅卡顿
                                        @Override
                                        public void run() {
                                            Toast.makeText(LoginActivity.this,"登录成功",Toast.LENGTH_SHORT).show();
                                        }
                                    });
                                }else{
                                    runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            Toast.makeText(LoginActivity.this,"请检查用户名密码是否正确",Toast.LENGTH_SHORT).show();
                                        }
                                    });
                                }
                            }else {
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        Toast.makeText(LoginActivity.this,"请输入正确的用户名密码",Toast.LENGTH_SHORT).show();
                                    }
                                });
                            }
                        } catch (Exception e) {  //捕获异常
                            e.printStackTrace();
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    Toast.makeText(LoginActivity.this,"网络连接失败",Toast.LENGTH_SHORT).show();
                                }
                            });
                        }
                    }
                }).start();

            }
        });
        registButton.setOnClickListener(new View.OnClickListener() { //注册按钮跳转页面
            @Override
            public void onClick(View view) {
                Intent intent=new Intent(LoginActivity.this,RegisterActivity.class);
                startActivity(intent);
            }
        });

    }
}