RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1544784
Accepted
mister_svinia
mister_svinia
Asked:2023-10-09 04:13:37 +0000 UTC2023-10-09 04:13:37 +0000 UTC 2023-10-09 04:13:37 +0000 UTC

在 MainUIThread 中访问小部件时出错(两种相同的情况,一种发生,另一种则不发生)

  • 772

我有两个小部件:

<TextView
    android:id="@+id/debugView"
    android:layout_width="256dp"
    android:layout_height="128dp"
    android:layout_marginBottom="120dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.5"
    app:layout_constraintStart_toStartOf="parent" />

<TextView
    android:id="@+id/activityAuthorization_widgets_responseStatus"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintBottom_toTopOf="@+id/activityAuthorization_widgets_login"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/activityAuthorization_widgets_inputPassword" />

有这个活动(未完成):

class ActivityAuthorization : AppCompatActivity() {
    private val httpClient = HttpClient()

    private lateinit var debugView: TextView

    private lateinit var inputLogin: TextInputEditText
    private lateinit var inputPassword: TextInputEditText
    private lateinit var buttonLogIn: Button
    private lateinit var showPassword: CheckBox
    private lateinit var responseStatusView: TextView

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

        supportActionBar?.hide()

        binder()
    }

    @SuppressLint("SetTextI18n")
    @OptIn(DelicateCoroutinesApi::class)
    private fun binder() {
        debugView = findViewById(R.id.debugView)

        inputLogin = findViewById(R.id.activityAuthorization_widgets_inputLogin)
        inputPassword = findViewById(R.id.activityAuthorization_widgets_inputPassword)
        buttonLogIn = findViewById(R.id.activityAuthorization_widgets_login)

        showPassword = findViewById(R.id.activityAuthorization_widgets_showPassword)
        responseStatusView = findViewById(R.id.activityAuthorization_widgets_responseStatus)

        buttonLogIn.setOnClickListener {
            GlobalScope.launch(Dispatchers.IO) {
                val response: HttpResponse =
                    httpClient.request(
                        URLS.AUTHORIZATION
                    ) {
                        method = HttpMethod.Get
                        url {
                            parameters.append(
                                URLS.AUTHORIZATION_USERNAME,
                                inputLogin.text.toString()
                            )
                            parameters.append(
                                URLS.AUTHORIZATION_PASSWORD,
                                inputPassword.text.toString()
                            )
                        }
                    }

                when (response.status.value) {
                    200 -> completeAuthorization(response.bodyAsText())
                    404 -> userNotFound()
                    else -> unprocessedResponse()
                }
            }
        }

        showPassword.setOnCheckedChangeListener { _, isChecked ->
            if (isChecked) inputPassword.setInputType(InputType.TYPE_CLASS_TEXT)
            else inputPassword.setInputType(InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD)
        }
    }

    @SuppressLint("SetTextI18n")
    private fun completeAuthorization(responseText: String) {
        val responseData = JsonIterator.deserialize(
            responseText,
            ResponsePackets.AC.Authorization.Done::class.java
        )

        try {
            responseData?.apply {
                debugView.text = "id: ${
                    responseData.data.id
                }\ntoken: ${responseData.data.token}"
            } ?: unprocessedResponse()
        } catch (_: NullPointerException) { unprocessedResponse() }
    }

    @SuppressLint("SetTextI18n")
    private fun userNotFound() {
        responseStatusView.text = "123"
    }

    @SuppressLint("SetTextI18n")
    private fun unprocessedResponse() {
        responseStatusView.text = "123"
    }
}

服务器(Python Django)返回三个之一(取决于结果)

return JsonResponse({
    'status': 'Done',
    'data': {
        'id': id,
        'token': helper.DBOperator.create_token(request.META.get('HTTP_USER_AGENT'), id)
    }
}, status=200)

return JsonResponse({
    'status': 'Refused',
    'reason': 'BadRequest',
    'description': 'UserNotFound'
}, status=404)

return JsonResponse({
    'status': 'Refused',
    'reason': 'BadRequest',
    'description': 'LackOfArguments'
}, status=406)

好吧,429,但我出于调试目的将其注释掉了。

如果状态200通过并且数据正确(而且确实是正确的),那么就id正常token显示。没有错误发生。但如果返回的不是 200,那么我会切换到unprocessedResponse()(暂时也是暂时的)并得到:

2023-10-08 23:03:39.732  5012-5180  AndroidRuntime          com.gct.cl.android                   E  FATAL EXCEPTION: DefaultDispatcher-worker-4
                                                                                                    Process: com.gct.cl.android, PID: 5012
                                                                                                    android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
                                                                                                        at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:11586)
                                                                                                        at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:2648)
                                                                                                        at android.view.View.requestLayout(View.java:27623)
                                                                                                        at android.view.View.requestLayout(View.java:27623)
                                                                                                        at android.view.View.requestLayout(View.java:27623)
                                                                                                        at android.view.View.requestLayout(View.java:27623)
                                                                                                        at android.view.View.requestLayout(View.java:27623)
                                                                                                        at android.view.View.requestLayout(View.java:27623)
                                                                                                        at androidx.constraintlayout.widget.ConstraintLayout.requestLayout(ConstraintLayout.java:3605)
                                                                                                        at android.view.View.requestLayout(View.java:27623)
                                                                                                        at android.widget.TextView.checkForRelayout(TextView.java:10904)
                                                                                                        at android.widget.TextView.setText(TextView.java:6965)
                                                                                                        at android.widget.TextView.setText(TextView.java:6751)
                                                                                                        at android.widget.TextView.setText(TextView.java:6703)
                                                                                                        at com.gct.cl.android.ActivityAuthorization.userNotFound(ActivityAuthorization.kt:106)
                                                                                                        at com.gct.cl.android.ActivityAuthorization.access$userNotFound(ActivityAuthorization.kt:23)
                                                                                                        at com.gct.cl.android.ActivityAuthorization$binder$1$1.invokeSuspend(ActivityAuthorization.kt:76)
                                                                                                        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
                                                                                                        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
                                                                                                        at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115)
                                                                                                        at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:103)
                                                                                                        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
                                                                                                        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
                                                                                                        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
                                                                                                        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
                                                                                                        Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@a649923, Dispatchers.IO]

据我了解,该错误是由于尝试responseStatusView从发出请求的 Coruntine 进行访问而发生的。但为什么GET 200我没有收到类似的状态错误呢?为了以防万一,我附加了模式类和存储类:

package com.gct.cl.android;


public class ResponsePackets {
    static class AC {
        static class Authorization {
            static class Done {
                String status;

                AuthData data;
            }
            static class ClientError {
                String status;
                String reason;
                String description;
            }
            static class NotFound {
                String status;
                String reason;
                String description;
            }
        }
        static class AuthData {
            long id;
            String token;
        }
    }
}
package com.gct.cl.android

object URLS {
    const val AUTHORIZATION = "http://192.168.196.60:8082/auth" // Я подключаюсь через прокси
    const val AUTHORIZATION_USERNAME = "username"
    const val AUTHORIZATION_PASSWORD = "password"
}

UDP 我将文本输出移至debugView:

@SuppressLint("SetTextI18n")
private fun completeAuthorization(responseText: String) {
    val responseData = JsonIterator.deserialize(
        responseText,
        ResponsePackets.AC.Authorization.Done::class.java
    )
    try {
        runOnUiThread {
            Thread {
                responseData?.apply {
                    debugView.text = "id: ${responseData.data.id}\ntoken: ${responseData.data.token}"
                } ?: unprocessedResponse()
            }.start()
        }
    } catch (_: NullPointerException) {
        unprocessedResponse()
    }
}

@SuppressLint("SetTextI18n")
private fun userNotFound() {
    debugView.text = "123"
}

@SuppressLint("SetTextI18n")
private fun unprocessedResponse() {
    debugView.text = "123"
}

Aaand...一切都按预期进行。

我尝试这样做:

@SuppressLint("SetTextI18n")
private fun userNotFound() {
    runOnUiThread {
        Thread {
            debugView.setText(R.string.authorization_widgets_responseStatus_userNotFound.toString())
        }
    }
}

Aaand...同样的错误。该代码在 4 部手机和两个模拟器上进行了测试。结果到处都一样。

java
  • 1 1 个回答
  • 45 Views

1 个回答

  • Voted
  1. Best Answer
    Eugene Krivenja
    2023-10-10T04:22:36Z2023-10-10T04:22:36Z

    此链接完美地解释了有关如何从任何线程访问 UI 的所有内容。
    https://developer.android.com/guide/components/processes-and-threads

    将您的分层流程设计替换为

    debugView.post {
      debugView.text = "id: ${responseData.data.id}\ntoken:${responseData.data.token}"
    }
    

    和

    responseStatusView.post {
      responseStatusView.text = "123"
    }
    

    您可以从任何线程调用此代码。

    • 0

相关问题

  • wpcap 找不到指定的模块

  • 如何以编程方式从桌面应用程序打开 HTML 页面?

  • Android Studio 中的 R.java 文件在哪里?

  • HashMap 初始化

  • 如何使用 lambda 表达式通过增加与原点的距离来对点进行排序?

  • 最大化窗口时如何调整元素大小?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5