本文语言:Kotlin
在开发毕设程序的时候需要用到网络请求,比较耗时,因此需要显示一个progressDialog来告诉用户不用乱点,只需等待即可。于是写了一个progressDialog的类方便四处调用:
class MyProgressDialog(private val context: Context) {
private val progressDialog = ProgressDialog(context)
fun show() {
progressDialog.setMessage(context.getString(R.string.loading))
progressDialog.setCancelable(false)
progressDialog.show()
}
fun dismiss() {
if (progressDialog.isShowing) {
progressDialog.dismiss()
}
}
}
然后拿到Activity中去用,以下是原来的代码:
binding.generateParameters.setOnClickListener {
val user = UserBackground(this)
user.init()
val prompt = "xxx"
// 这里开始显示对话框!
val pd = MyProgressDialog(this)
pd.show()
CoroutineScope(Dispatchers.IO).launch{
var answer: String
try {
val ai = AIAssistant()
answer = ai.GetAnswer(prompt, "") as String
} catch (e: Exception) {
answer = "ERROR"
}
withContext(Dispatchers.Main) {
AlertDialog.Builder(this@AddParameterActivity)
.setTitle("PNF Master的建议")
.setMessage(answer)
.setPositiveButton(getString(R.string.Yes)) { dialog, _ -> dialog.dismiss() }
.show()
}
}
// 这里关闭对话框!
pd.dismiss()
}
但是运行的时候却发现根本不显示。。。经过排查之后确认是主线程堵塞的问题,原因在于pd.show()
和pd.dismiss()
都在主线程中执行,但是它们被阻塞了,因为我在主线程中启动了一个协程。
在协程中,launch
是一个挂起函数,它会阻塞当前线程直到协程执行完毕。因此,pd.dismiss()
在 pd.show()
后面立即执行,导致加载对话框没有显示。 解决这个问题的方法是将 pd.show()
和 pd.dismiss()
放入协程中,确保它们在正确的时间点执行。你可以在 launch
之前调用 pd.show()
,然后在协程的最后调用 pd.dismiss()
。这样,加载对话框就会在协程执行期间显示,协程执行完毕后对话框就会消失。
修改之后的代码是这样的:
binding.generateParameters.setOnClickListener {
val user = UserBackground(this)
user.init()
val prompt = "xxx"
val pd = MyProgressDialog(this)
pd.show()
CoroutineScope(Dispatchers.IO).launch{
var answer: String
try {
val ai = AIAssistant()
answer = ai.GetAnswer(prompt, "") as String
} catch (e: Exception) {
answer = "ERROR"
}
// 在这里切回主线程并关闭对话框!
withContext(Dispatchers.Main) {
pd.dismiss()
}
withContext(Dispatchers.Main) {
AlertDialog.Builder(this@AddParameterActivity)
.setTitle("PNF Master的建议")
.setMessage(answer)
.setPositiveButton(getString(R.string.Yes)) { dialog, _ -> dialog.dismiss() }
.show()
}
}
}
感谢Github Copilot大力提供技术支持。。。