Android(Kotlin)应用连接本地MySQL数据库失败求助
Android Kotlin本地MySQL注册无响应问题排查与解决
我是Android应用开发新手,用Kotlin编写代码,现在要实现应用连接本地MySQL所在电脑的服务器,完成用户注册数据提交和登录功能,但点击注册按钮完全没反应。已有网站能正常连接该本地服务器和数据库,以下是相关代码:
Dbhelper.kt
package com.example.myapplication import java.sql.Connection import java.sql.DriverManager import java.sql.ResultSet import java.sql.SQLException class Dbhelper(private val url: String, private val user: String, private val password: String) { init { try { Class.forName("com.mysql.cj.jdbc.Driver") } catch (e: ClassNotFoundException) { e.printStackTrace() } } fun connect(): Connection? { try { return DriverManager.getConnection(url, user, password) } catch (e: SQLException) { e.printStackTrace() } return null } fun isUserExists(login: String, email: String): Boolean { connect()?.use { connection -> val query = "SELECT * FROM appmovie_users WHERE login = ? OR email = ?" val preparedStatement = connection.prepareStatement(query) preparedStatement.setString(1, login) preparedStatement.setString(2, email) val resultSet: ResultSet = preparedStatement.executeQuery() return resultSet.next() } return false } fun addUser(login: String, email: String, password: String): Boolean { connect()?.use { connection -> val query = "INSERT INTO appmovie_users (login, email, password) VALUES (?, ?, ?)" val preparedStatement = connection.prepareStatement(query) preparedStatement.setString(1, login) preparedStatement.setString(2, email) preparedStatement.setString(3, password) val rowsAffected = preparedStatement.executeUpdate() return rowsAffected > 0 } return false } }
RegistrationActivity.kt
package com.example.myapplication import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.widget.Button import android.widget.EditText import android.widget.TextView import android.widget.Toast import androidx.lifecycle.ViewModelProvider class RegistrationActivity : AppCompatActivity() { private lateinit var viewModel: RegistrationViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.registration) val userLogin = findViewById<EditText>(R.id.user_login) val userEmail = findViewById<EditText>(R.id.user_email) val userPass = findViewById<EditText>(R.id.user_pass) val button = findViewById<Button>(R.id.button_reg) val linkToAuth = findViewById<TextView>(R.id.link_to_auth) val logoName = findViewById<TextView>(R.id.logoName) val dbUrl = "jdbc:mysql://localhost:3306/database-users-movieapp" val dbUser = "root" val dbPassword = "" val dbHelper = Dbhelper(dbUrl, dbUser, dbPassword) viewModel = ViewModelProvider(this)[RegistrationViewModel::class.java] button.setOnClickListener { val login = userLogin.text.toString().trim() val email = userEmail.text.toString().trim() val pass = userPass.text.toString().trim() if (login == "" || email == "" || pass == "") { Toast.makeText(this, "Not all fields are filled", Toast.LENGTH_LONG).show() } else { if (dbHelper.isUserExists(login, email)) { Toast.makeText(this, "User with the same login or email already exists", Toast.LENGTH_LONG).show() } else { viewModel.registerUser(login, email, pass) } } } } }
RegistrationViewModel.kt
package com.example.myapplication import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch class RegistrationViewModel : ViewModel() { private val DB_URL = "jdbc:mysql://localhost:3306/database-users-movieapp" private val DB_USER = "root" private val DB_PASSWORD = "" private val databaseHelper = Dbhelper(DB_URL, DB_USER, DB_PASSWORD) val registrationResult = MutableLiveData<Boolean>() fun registerUser(login: String, email: String, password: String) { viewModelScope.launch(Dispatchers.IO) { val isRegistrationSuccessful = databaseHelper.addUser(login, email, password) registrationResult.postValue(isRegistrationSuccessful) } } }
问题排查与解决方案
1. 主线程执行耗时操作导致阻塞
isUserExists方法直接在主线程调用数据库连接和查询,Android禁止主线程执行耗时操作,会触发ANR(应用无响应),导致按钮点击后无反馈。
解决:
将用户存在性检查移到协程中执行:
// 修改RegistrationActivity的按钮点击事件 button.setOnClickListener { val login = userLogin.text.toString().trim() val email = userEmail.text.toString().trim() val pass = userPass.text.toString().trim() if (login.isEmpty() || email.isEmpty() || pass.isEmpty()) { Toast.makeText(this, "请填写所有字段", Toast.LENGTH_LONG).show() } else { lifecycleScope.launch(Dispatchers.IO) { val exists = dbHelper.isUserExists(login, email) launch(Dispatchers.Main) { if (exists) { Toast.makeText(this@RegistrationActivity, "该登录名或邮箱已存在", Toast.LENGTH_LONG).show() } else { viewModel.registerUser(login, email, pass) } } } } }
需确保Activity依赖协程库,并添加导入:import kotlinx.coroutines.launch、import kotlinx.coroutines.Dispatchers。
2. 本地MySQL连接地址错误
Android设备/模拟器的localhost指向自身,而非运行MySQL的电脑。需替换为电脑的本地IP地址(如192.168.xxx.xxx),同时确保MySQL允许远程连接、防火墙开放3306端口。
修改连接URL:
// 替换为你的电脑本地IP,添加必要参数 val dbUrl = "jdbc:mysql://192.168.1.100:3306/database-users-movieapp?useSSL=false&serverTimezone=UTC"
3. 未监听注册结果反馈
ViewModel的registrationResult已发送注册状态,但Activity未监听,导致成功/失败都无提示,看起来像无响应。
添加结果监听:
在RegistrationActivity的onCreate方法中添加:
viewModel.registrationResult.observe(this) { success -> if (success) { Toast.makeText(this, "注册成功", Toast.LENGTH_LONG).show() // 可跳转至登录页面 } else { Toast.makeText(this, "注册失败,请重试", Toast.LENGTH_LONG).show() } }
4. 额外安全提示
当前代码直接存储明文密码,存在安全风险,建议使用SHA-256或BCrypt加密后再存入数据库。
内容的提问来源于stack exchange,提问作者nothin7
相关产品推荐
相关产品推荐

