Android Studio前后端实战:构建一个简单的Todo应用

在现代软件开发中,前后端分离已成为一种流行的架构模式。前端处理用户界面(UI)和用户体验(UX),而后端则负责数据处理、存储和业务逻辑。在这篇文章中,我们将介绍如何使用 Android Studio 开发一个简单的 Todo 应用,包含前后端的协作。

项目结构

我们的 Todo 应用将由两个部分组成:Android 前端和后端 API 服务。前端使用 Kotlin 编写 Android 应用程序,后端使用 Node.js 来提供 RESTful API。

状态图

首先,让我们理解一下应用的状态。以下是我们的状态图,展示了 Todo 应用中可能的状态:

stateDiagram
    [*] --> 无任务
    无任务 --> 有任务
    有任务 --> 任务已完成
    任务已完成 --> 有任务
    有任务 --> 无任务

后端开发

我们使用 Node.js 和 Express 框架来搭建后端服务。以下是一个简单的 Todo API 示例代码:

// server.js
const express = require('express');
const bodyParser = require('body-parser');

const app = express();
app.use(bodyParser.json());

let todos = [];

// 创建任务
app.post('/todos', (req, res) => {
    const todo = { id: Date.now(), title: req.body.title, completed: false };
    todos.push(todo);
    res.status(201).send(todo);
});

// 获取所有任务
app.get('/todos', (req, res) => {
    res.send(todos);
});

// 更新任务
app.put('/todos/:id', (req, res) => {
    const todo = todos.find(t => t.id == req.params.id);
    if (todo) {
        todo.completed = req.body.completed;
        res.send(todo);
    } else {
        res.status(404).send('Todo not found');
    }
});

// 删除任务
app.delete('/todos/:id', (req, res) => {
    todos = todos.filter(t => t.id != req.params.id);
    res.status(204).send();
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});

前端开发

在 Android Studio 中,我们将使用 Kotlin 来创建应用界面和处理 HTTP 请求。以下是一个简单的 UI 以及如何与后端 API 交互的示例代码。

UI 布局

res/layout/activity_main.xml 中,我们定义一个简单的布局:

<LinearLayout xmlns:android="
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="输入任务" />

    <Button
        android:id="@+id/addButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="添加" />

    <ListView
        android:id="@+id/todoList"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

主Activity代码

MainActivity.kt 中,编写网络请求代码:

import android.os.Bundle
import android.view.View
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.EditText
import android.widget.ListView
import androidx.appcompat.app.AppCompatActivity
import okhttp3.*
import java.io.IOException

class MainActivity : AppCompatActivity() {
    private val client = OkHttpClient()
    private val todos = mutableListOf<String>()
    private lateinit var adapter: ArrayAdapter<String>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val editText: EditText = findViewById(R.id.editText)
        val addButton: Button = findViewById(R.id.addButton)
        val todoList: ListView = findViewById(R.id.todoList)

        adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, todos)
        todoList.adapter = adapter

        addButton.setOnClickListener {
            val todoText = editText.text.toString()
            if (todoText.isNotEmpty()) {
                addTodo(todoText)
                editText.text.clear()
            }
        }

        fetchTodos()
    }

    private fun addTodo(todoText: String) {
        val requestBody = RequestBody.create(
            MediaType.parse("application/json"),
            """{"title": "$todoText"}"""
        )

        val request = Request.Builder()
            .url("
            .post(requestBody)
            .build()

        client.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                e.printStackTrace()
            }

            override fun onResponse(call: Call, response: Response) {
                response.body()?.string() ?.let {
                    runOnUiThread {
                        todos.add(todoText)
                        adapter.notifyDataSetChanged()
                    }
                }
            }
        })
    }

    private fun fetchTodos() {
        val request = Request.Builder()
            .url("
            .build()

        client.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                e.printStackTrace()
            }

            override fun onResponse(call: Call, response: Response) {
                response.body()?.string() ?.let {
                    runOnUiThread {
                        // 解析返回的JSON并更新UI
                        // 这里省略了JSON解析的代码
                    }
                }
            }
        })
    }
}

流程图

接下来,让我们看一下从用户添加任务到显示任务的整个流程:

flowchart TD
    A[用户输入任务] -->|点击添加| B[发送请求到后端API]
    B --> C{请求成功?}
    C -->|是| D[更新本地任务列表]
    C -->|否| E[显示错误信息]
    D --> F[重绘UI]
    F --> G[用户查看任务列表]

结论

在本文中,我们通过构建一个简单的 Todo 应用程序,展示了 Android Studio 中前后端的实战应用。后端使用 Node.js 构建 RESTful API,而前端则使用 Kotlin 编写 Android 应用。我们通过实际的代码示例,说明了如何在两个部分之间进行数据交互、状态管理及用户反馈。这一架构能够有效地提高开发效率,并使得开发人员能够更专注于业务逻辑的实现。希望通过这篇文章,能够帮助大家初步理解 Android 开发中的前后端合作模式。