学习进度条

今日所花时间:一小时
今日代码量:100行
博客量:一篇
了解到的知识点:深入学习androidStudio 继续优化完成课程管理系统
创建Empty Views Activity项目
在build.gradle.kts添加依赖

// Retrofit 依赖
    implementation("com.squareup.retrofit2:retrofit:2.9.0")
    implementation("com.squareup.retrofit2:converter-gson:2.9.0")
    // RecyclerView 依赖
    implementation("androidx.recyclerview:recyclerview:1.3.2")
    implementation(libs.recyclerview)

在文件夹下创建adapters软件包
创建CourseAdapter

package com.example.demo0314.adapters;


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 com.example.demo0314.models.Course;
import com.example.demo0314.R;
import java.util.List;
//CourseAdapter是适配器,用来绑定课程数据到RecyclerView
public class CourseAdapter extends RecyclerView.Adapter<CourseAdapter.CourseViewHolder> {

    private List<Course> courseList;//课程数据列表

    // 构造函数,传入课程列表
    public CourseAdapter(List<Course> courseList) {
        this.courseList = courseList;
    }

    // 创建ViewHolder
    @NonNull
    @Override
    public CourseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        // 加载布局文件 item_course.xml
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_course, parent, false);
        return new CourseViewHolder(view);//返回ViewHolder实例
    }

    // 绑定数据到ViewHolder
    @Override
    public void onBindViewHolder(@NonNull CourseViewHolder holder, int position) {
        Course course = courseList.get(position);//获取当前项的数据
        holder.bind(course);//将数据绑定到ViewHolder
    }

    // 返回数据项的数量
    @Override
    public int getItemCount() {
        return courseList.size();
    }

    // ViewHolder类,用于缓存视图
    public static class CourseViewHolder extends RecyclerView.ViewHolder {
        private TextView textCourseName, textTeacher, textLocation;// 视图组件

        public CourseViewHolder(@NonNull View itemView) {
            super(itemView);
            // 初始化视图
            textCourseName = itemView.findViewById(R.id.textCourseName);
            textTeacher = itemView.findViewById(R.id.textTeacher);
            textLocation = itemView.findViewById(R.id.textLocation);
        }

        // 绑定数据到视图
        public void bind(Course course) {
            textCourseName.setText(course.getCourseName());
            textTeacher.setText("教师: " + course.getTeacher());
            textLocation.setText("地点: " + course.getLocation());
        }
    }
}

创建api软件包
创建ApiService接口

package com.example.demo0314.api;

import com.example.demo0314.models.Course;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.POST;
import java.util.List;
//定义与后端API的交互方法
public interface ApiService {
    @GET("courses/all")//与后端保持一致
    Call<List<Course>> getAllCourses();

    @POST("courses/add")
    Call<String> addCourse(@Body Course course);
}

创建RetrofitClient

package com.example.demo0314.api;


import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import java.util.concurrent.TimeUnit;
//配置Retrofit客户端
public class RetrofitClient {
    private static final String BASE_URL = "http://192.168.188.118:8080/";
    private static Retrofit retrofit = null;

    public static ApiService getApiService() {
        if (retrofit == null) {
            // 创建 Gson 实例,设置为 lenient 模式
            Gson gson = new GsonBuilder()
                    .setLenient() // 允许解析非标准 JSON
                    .create();

            OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    .connectTimeout(30, TimeUnit.SECONDS)
                    .readTimeout(30, TimeUnit.SECONDS)
                    .writeTimeout(30, TimeUnit.SECONDS)
                    .build();

            retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .client(okHttpClient)
                    .addConverterFactory(GsonConverterFactory.create(gson)) // 使用自定义的 Gson 实例
                    .build();
        }
        return retrofit.create(ApiService.class);
    }
}

创建models包
Course实体类

package com.example.demo0314.models;

//课程数据模型
public class Course {
    private Long id;
    private String courseName;
    private String teacher;
    private String location;

    // Getters and Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getCourseName() {
        return courseName;
    }

    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }

    public String getTeacher() {
        return teacher;
    }

    public void setTeacher(String teacher) {
        this.teacher = teacher;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }
}

在MainActivity书写以下代码

package com.example.demo0314;

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 androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.example.demo0314.adapters.CourseAdapter;
import com.example.demo0314.api.ApiService;
import com.example.demo0314.api.RetrofitClient;
import com.example.demo0314.models.Course;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private CourseAdapter adapter;
    private List<Course> courseList = new ArrayList<>();

    private EditText editCourseName, editTeacher, editLocation;
    private Button btnAddCourse;

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

        // 初始化UI
        recyclerView = findViewById(R.id.recyclerView);
        editCourseName = findViewById(R.id.editCourseName);
        editTeacher = findViewById(R.id.editTeacher);
        editLocation = findViewById(R.id.editLocation);
        btnAddCourse = findViewById(R.id.btnAddCourse);

        // 设置RecyclerView
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        adapter = new CourseAdapter(courseList);
        recyclerView.setAdapter(adapter);

        // 加载课程列表
        loadCourses();

        // 添加课程按钮点击事件
        btnAddCourse.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                addCourse();
            }
        });
    }

    // 加载课程列表
    private void loadCourses() {
        ApiService apiService = RetrofitClient.getApiService();
        apiService.getAllCourses().enqueue(new Callback<List<Course>>() {
            @Override
            public void onResponse(Call<List<Course>> call, Response<List<Course>> response) {
                if (response.isSuccessful() && response.body() != null) {
                    courseList.clear();
                    if (response.body().isEmpty()) {
                        Toast.makeText(MainActivity.this, "没有课程数据", Toast.LENGTH_SHORT).show();
                    } else {
                        courseList.addAll(response.body());
                    }
                    adapter.notifyDataSetChanged();
                } else {
                    Toast.makeText(MainActivity.this, "数据加载失败: " + response.message(), Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onFailure(Call<List<Course>> call, Throwable t) {
                Log.e("Error", t.getMessage());
                Toast.makeText(MainActivity.this, "网络请求失败,请检查网络连接", Toast.LENGTH_SHORT).show();
            }
        });
    }

    // 添加新课程
    private void addCourse() {
        String courseName = editCourseName.getText().toString().trim();
        String teacher = editTeacher.getText().toString().trim();
        String location = editLocation.getText().toString().trim();

        if (courseName.isEmpty() || teacher.isEmpty() || location.isEmpty()) {
            Toast.makeText(this, "请填写所有字段", Toast.LENGTH_SHORT).show();
            return;
        }

        Course newCourse = new Course();
        newCourse.setCourseName(courseName);
        newCourse.setTeacher(teacher);
        newCourse.setLocation(location);

        Log.d("Request", "Sending: " + newCourse.toString());
        ApiService apiService = RetrofitClient.getApiService();
        apiService.addCourse(newCourse).enqueue(new Callback<String>() {
            @Override
            public void onResponse(Call<String> call, Response<String> response) {
                if (response.isSuccessful()) {
                    Log.d("Response", "Success: " + response.body());
                    Toast.makeText(MainActivity.this, response.body(), Toast.LENGTH_SHORT).show();
                    editCourseName.setText("");
                    editTeacher.setText("");
                    editLocation.setText("");
                    loadCourses(); // 刷新课程列表
                } else {
                    try {
                        // 打印错误信息
                        String errorBody = response.errorBody().string();
                        Log.e("Response", "Failed: " + errorBody);
                        Toast.makeText(MainActivity.this, "添加课程失败: " + errorBody, Toast.LENGTH_SHORT).show();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

            @Override
            public void onFailure(Call<String> call, Throwable t) {
                Log.e("Error", t.getMessage());
                Toast.makeText(MainActivity.this, "网络请求失败,请检查网络连接", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

在layout包下创建item_course.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="vertical"
    android:padding="8dp">

    <TextView
        android:id="@+id/textCourseName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="课程名称"
        android:textSize="18sp" />

    <TextView
        android:id="@+id/textTeacher"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="任课教师" />

    <TextView
        android:id="@+id/textLocation"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="上课地点" />
</LinearLayout>

在activity_main.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="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <EditText
        android:id="@+id/editCourseName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="课程名称"
        android:minHeight="48dp" />

    <EditText
        android:id="@+id/editTeacher"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="48dp"
        android:hint="任课教师" />

    <EditText
        android:id="@+id/editLocation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="48dp"
        android:hint="上课地点" />

    <Button
        android:id="@+id/btnAddCourse"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="48dp"
        android:text="添加课程" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp" />
</LinearLayout>

在xml包下创建network_security_config.xml保证能够访问本地开发服务器

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <!-- 允许访问本地开发服务器 -->
    <!--网络安全配置文件-->
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">10.0.2.2</domain>
        <domain includeSubdomains="true">192.168.188.118</domain>
    </domain-config>
</network-security-config>

通过以上代码的编写可以连接springboot完成的后端程序代码完成手机端的功能实现。

posted @ 2025-03-13 20:46  haoyinuo  阅读(29)  评论(0)    收藏  举报