大概时序图
登录成功保存token,然后带token请求获取用户列表
实现效果:
依赖
build.gradle(:app)
dependencies {
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation 'com.google.code.gson:gson:2.8.9'
implementation 'com.tencent:mmkv-static:1.2.9'
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
}
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
MainActivity
import androidx.appcompat.app.AppCompatActivity;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.tencent.mmkv.MMKV;
import org.json.JSONObject;
import java.io.IOException;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity {
private EditText usernameEditText;
private EditText passwordEditText;
private Button loginButton;
private String token;
@SuppressLint("MissingInflatedId")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
usernameEditText = findViewById(R.id.userNameEditText);
passwordEditText = findViewById(R.id.passwordEditText);
loginButton = findViewById(R.id.loginButton);
//初始化
MMKV.initialize(this);
//点击事件
loginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String username = usernameEditText.getText().toString();
String password = passwordEditText.getText().toString();
if (isValidUsernameAndPassword(username, password)) {
LoginTask loginTask = new LoginTask();
loginTask.execute();
} else {
Toast.makeText(MainActivity.this, "用户名或密码无效", Toast.LENGTH_SHORT).show();
}
}
});
}
private boolean isValidUsernameAndPassword(String username, String password) {
// 在这里可以添加验证用户名和密码的逻辑,例如检查用户名和密码的格式等
return true;
}
private class LoginTask extends AsyncTask<Void, Void, String> {
private final OkHttpClient client = new OkHttpClient();
@Override
protected String doInBackground(Void... voids) {
String username = usernameEditText.getText().toString();
String password = passwordEditText.getText().toString();
//post请求的URL
String url = "https://2k317b5009.goho.co/login?username=" + username + "&password=" + password; // 替换为实际的登录接口地址
try {
//创建了一个新的Request对象。Request对象用于封装请求的各种参数,如URL、HTTP方法、请求头、请求体等
Request request = new Request.Builder()
.url(url)
//设置了请求的方法为POST,并创建了请求体。
//请求体中包含了以JSON格式发送的用户名和密码。
// MediaType.parse("application/json")指示了请求体的格式是JSON。
.post(RequestBody.create(okhttp3.MediaType.parse("application/json"), "{\"username\":\"" + username + "\", \"password\":\"" + password + "\"}")) // 将username和password以JSON格式发送给服务器
.build();
Response response = client.newCall(request).execute();//发送了请求并获取了响应
return response.body().string();//从响应中获取了响应体,并将其转换为字符串格式
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String response) {
if (response != null) {
try {
JSONObject jsonObject = new JSONObject(response);
token = jsonObject.getJSONObject("userMsg").getString("token"); // 获取token字段的值,根据实际情况修改字段名称和JSON解析方式
MMKVUtil.putString("key",token);//MMKVUtil储存token
Log.e("MainActivity", token);
Toast.makeText(MainActivity.this, "登录成功", Toast.LENGTH_SHORT).show();//弹框提示
Intent intent = new Intent(MainActivity.this, ListActivity.class);//跳转页面
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(MainActivity.this, "登录失败", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(MainActivity.this, "没有服务", Toast.LENGTH_SHORT).show();
}
}
}
}
ListActivity 将数据解析转换为list进行列表展示
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.json.JSONException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class ListActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private final List<User> mUserList = new ArrayList<>();
private final String TAG = "ListActivity";
private Handler mHandler;
private MyAdapter mMyAdapter;
@SuppressLint("MissingInflatedId")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
mRecyclerView = findViewById(R.id.recyclerView);
//创建了一个新的Handler对象,在Android的主线程(UI线程)上执行特定的任务
mHandler = new Handler();
//创建了一个新的线程来执行后面的代码 不会阻塞主线程
new Thread(new Runnable() {//定义了新线程要执行的操作
@Override
public void run() {
try {
//获取处理好的网络数据
String JSON = getUserjson();
List<User> userList = getList(JSON);
//将新的Runnable对象添加到Handler中,这使得Runnable中的代码将在主线程上执行
mHandler.post(new Runnable() {
@Override
public void run() {
//设置了一个线性布局管理器
mRecyclerView.setLayoutManager(new LinearLayoutManager(ListActivity.this));
//实例化适配器
mMyAdapter = new MyAdapter(userList);
//将适配器设置为RecyclerView的适配器
mRecyclerView.setAdapter(mMyAdapter);
if (userList != null) {
// 处理响应结果
} else {
// 处理错误情况
}
}
});
} catch (IOException | JSONException e) {
e.printStackTrace();
}
}
}).start();
}
public String getUserjson() throws IOException, JSONException {
// 创建OkHttpClient实例
OkHttpClient client = new OkHttpClient();
// 设置请求的URL和token
String strurl = "https://2k317b5009.goho.co/userList";
String Token = MMKVUtil.getString("key");//获取token
// 创建请求头部,包括token
Request request = new Request.Builder()
.url(strurl)
.addHeader("token", Token)//添加headers信息
.build();
Log.e(TAG, request.toString());
// 发送GET请求并获取响应
String responseBody = null;
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
// 处理成功响应
responseBody = response.body().string();
}
}
return responseBody;
}
public List<User> getList(String responseBody) {
//创建了一个新的JsonParser对象。JsonParser是Gson库中的一个类,
//提供了从JSON文本字符串解析JSON并生成JsonElement对象的方法
JsonParser parser = new JsonParser();
//使用JsonParser对象来解析responseBody中的JSON文本,并将解析的结果存储在一个JsonElement对象中
JsonElement element = parser.parse(responseBody);
//解析得到的element是否是一个JSON数组
if (element.isJsonArray()) {
//获取上一步解析得到的element作为一个JsonArray对象
JsonArray array = element.getAsJsonArray();
//遍历上一步得到的JsonArray对象中的每一个元素
for (JsonElement e : array) {
//检查当前的元素e是否是一个JSON对象
if (e.isJsonObject()) {
JsonObject obj = e.getAsJsonObject();
String name = obj.get("name").getAsString();
String password = obj.get("password").getAsString();
int Id = obj.get("id").getAsInt();
String sex = obj.get("sex").getAsString();
int age = obj.get("age").getAsInt();
//String token = obj.get("token").getAsString();
String msg1 = obj.get("msg1").getAsString();
String msg2 = obj.get("msg2").getAsString();
String msg3 = obj.get("msg3").isJsonNull() ? "default" : obj.get("msg3").getAsString();
User user = new User(name, password, Id, sex, age, "", msg1, msg2, msg3);
mUserList.add(user);
// 在这里将每个User对象进行存储或处理
}
// 在这里对响应数据进行解析和处理
Log.e(TAG, "————————————————————————");
}
}
return mUserList;
}
}
MMKVUtil 管理token
import com.tencent.mmkv.MMKV;
/**
* 管理token
*/
public class MMKVUtil {
private static MMKV mmkv;
//获取实例
private static MMKV getInstance() {
if (mmkv == null) {
mmkv = MMKV.defaultMMKV();
}
return mmkv;
}
//存
public static void putString(String key, String value) {
getInstance().encode(key, value);
}
//取
public static String getString(String key) {
return getInstance().decodeString(key);
}
//删
public static void remove(String key) {
getInstance().removeValueForKey(key);
}
}
MyAdapter RecyclerView适配器
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
/**
* RecyclerView适配器
*/
//ViewHolder类通常用于持有RecyclerView的item视图中的控件,并可以避免频繁的 findViewById() 调用
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private final List<User> mUserList;
public MyAdapter(List<User> mUserList) {
this.mUserList = mUserList;
}
//onCreateViewHolder接受一个ViewGroup(通常是RecyclerView)和一个视图类型整数值作为参数,并返回一个新的ViewHolder实例,该实例持有新创建或复用的视图
@NonNull
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//使用LayoutInflater从parent的上下文中获取一个实例
//并使用R.layout.list_item(一个XML布局文件)来inflate(填充)一个新的视图。这个新视图被赋值给view变量
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
//ViewHolder将负责管理和操作这个视图以及其中的控件
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
@Override
//onBindViewHolder在RecyclerView中显示数据
public void onBindViewHolder(ViewHolder holder, int i) {
User user = mUserList.get(i);
holder.mName.setText(user.getName());
holder.mPwd.setText(user.getPassword());
holder.mId.setText(String.valueOf(user.getId()));
holder.mSex.setText(user.getSex());
holder.mAge.setText(String.valueOf(user.getAge()));
holder.mToken.setText(user.getToken());
holder.mMsg1.setText(user.getMsg1());
holder.mMsg2.setText(user.getMsg2());
holder.mMsg3.setText(user.getMsg3());
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public int getItemCount() {
return mUserList.size();
}
/**
* 创建了一个ViewHolder类,
* 用于保存和提供对RecyclerView列表项视图中各种文本视图(如姓名、密码、ID等)的引用,
* 以便在处理列表项视图时能方便地访问这些视图并进行相应的操作
*/
public class ViewHolder extends RecyclerView.ViewHolder {
//ViewHolder类通常用于保存每个列表项的视图以及与这些视图相关的数据
private final TextView mName;
private final TextView mPwd;
private final TextView mId;
private final TextView mSex;
private final TextView mAge;
private final TextView mToken;
private final TextView mMsg1;
private final TextView mMsg2;
private final TextView mMsg3;
//ViewHolder类的构造函数,它接收一个View对象作为参数。在构造函数中,通过给定的View对象找到并保存了对应的TextView
public ViewHolder(View view) {
super(view);
mName = view.findViewById(R.id.name);
mPwd = view.findViewById(R.id.pwd);
mId = view.findViewById(R.id.id);
mSex = view.findViewById(R.id.sex);
mAge = view.findViewById(R.id.age);
mToken = view.findViewById(R.id.token);
mMsg1 = view.findViewById(R.id.msg1);
mMsg2 = view.findViewById(R.id.msg2);
mMsg3 = view.findViewById(R.id.msg3);
}
}
}
User
public class User {
private String Name;
private String Password;
private int Id;
private String Sex;
private int Age;
private String Token;
private String Msg1;
private String Msg2;
private String Msg3;
public User() {
}
public User(String name, String password, int id, String sex, int age, String token, String msg1, String msg2, String msg3) {
Name = name;
Password = password;
Id = id;
Sex = sex;
Age = age;
Token = token;
Msg1 = msg1;
Msg2 = msg2;
Msg3 = msg3;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public String getPassword() {
return Password;
}
public void setPassword(String password) {
Password = password;
}
public int getId() {
return Id;
}
public void setId(int id) {
Id = id;
}
public String getSex() {
return Sex;
}
public void setSex(String sex) {
Sex = sex;
}
public int getAge() {
return Age;
}
public void setAge(int age) {
Age = age;
}
public String getToken() {
return Token;
}
public void setToken(String token) {
Token = token;
}
public String getMsg1() {
return Msg1;
}
public void setMsg1(String msg1) {
Msg1 = msg1;
}
public String getMsg2() {
return Msg2;
}
public void setMsg2(String msg2) {
Msg2 = msg2;
}
public String getMsg3() {
return Msg3;
}
public void setMsg3(String msg3) {
Msg3 = msg3;
}
}
activity_mian.xml 登录页面
<?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"
tools:context=".MainActivity"
android:orientation="horizontal"
android:gravity="center">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center_horizontal"
android:orientation="vertical"
android:gravity="center">
<EditText
android:id="@+id/userNameEditText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="text"
android:hint="用户名"/>
<EditText
android:id="@+id/passwordEditText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPassword"
android:hint="密码"/>
<CheckBox
android:id="@+id/rememberPwdCheckBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="记住密码"
android:checked="true" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center_horizontal"
android:orientation="horizontal"
android:gravity="center">
<Button
android:id="@+id/loginButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" 登 录 "/>
<Button
android:id="@+id/logoutButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="退出登录"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
acitivty_list.xml 列表页面
<?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:layout_margin="5dp"
android:orientation="vertical"
tools:context=".ListActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#BBD5E1"
tools:ignore="MissingConstraints">
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center"
android:text="name"
android:textSize="10dp" />
<TextView
android:id="@+id/pwd"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center"
android:text="pwd"
android:textSize="10dp" />
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center"
android:text="id"
android:textSize="10dp" />
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center"
android:text="sex"
android:textSize="10dp" />
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center"
android:text="age"
android:textSize="10dp" />
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center"
android:text="token"
android:textSize="10dp" />
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center"
android:text="msg1"
android:textSize="10dp" />
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center"
android:text="msg2"
android:textSize="10dp" />
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center"
android:text="msg3"
android:textSize="10dp" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
list_item.xml 列表项页面
<?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="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5sp"
android:layout_weight="1"
android:layout_gravity="center"
android:orientation="horizontal">
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center"
android:text="name"
android:textSize="10dp" />
<TextView
android:id="@+id/pwd"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center"
android:text="pwd"
android:textSize="10dp" />
<TextView
android:id="@+id/id"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center"
android:text="id"
android:textSize="10dp" />
<TextView
android:id="@+id/sex"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center"
android:text="sex"
android:textSize="10dp" />
<TextView
android:id="@+id/age"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center"
android:text="age"
android:textSize="10dp" />
<TextView
android:id="@+id/token"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center"
android:text="token"
android:textSize="10dp" />
<TextView
android:id="@+id/msg1"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center"
android:text="msg1"
android:textSize="10dp" />
<TextView
android:id="@+id/msg2"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center"
android:text="msg2"
android:textSize="10dp" />
<TextView
android:id="@+id/msg3"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center"
android:text="msg3"
android:textSize="10dp" />
</LinearLayout>
</LinearLayout>