runOnUiThread有时不起作用 - 为什么



我使用OkHttpClient从服务器获取数据并将其显示在runOnUiThread事件中,但该事件并不总是有效

基本逻辑是,我点击一个按钮,OkHttpClient从服务器获取一个json,解析它并向我显示json数据。不知道为什么,有时它工作正常,但在大多数情况下,我需要点击几次才能正常工作。我测试并发现 json 数据总是成功获取,所以问题似乎是runOnUiThread事件没有以正确的方式触发?对不起,我是安卓新手

private void getDocDetail() {
OkHttpClient client = new OkHttpClient.Builder().build();
RequestBody post = new FormBody.Builder()
.add("DocTypeID", Integer.toString(DocTypeID))
.add("DocID", Integer.toString(DocID))
.build();
final Request req = new Request.Builder()
.url("http://127.0.0.1/GetDocData.php"))
.post(post)
.build();
client.newCall(req).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(Call call, final Response response) throws IOException {
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
final String s = response.body().string();
JSONObject jo = new JSONObject(s);
AttachCount = jo.optInt("Attach");
edtAttach.setText(String.valueOf(AttachCount));
} catch (JSONException e) { e.printStackTrace(); }
catch (IOException e) { e.printStackTrace(); }
catch (Exception e) { e.printStackTrace(); }
});
}
});
}

完全没有错误消息。我需要的是每次点击按钮时,我都可以正确看到AttachCount,而不是点击 10 次并且只有 1 次有效

当它工作正常时,日志非常简单,如下所示:

2019-07-16 10:56:16.553 13332-13332/com.example.lance.platform I/时间线:

时间轴:Activity_launch_request时间:5633500 意图:意图{ cmp=com.example.lance.platform/.DocsignActivity (有额外的功能) }

2019-07-16 10:56:16.624 13332-13379/com.example.lance.platform I/ContentCatcher: ViewContentFetcher : ViewContentFetcher

2019-07-16 10:56:17.093 13332-13337/com.example.lance.platform I/zygote64:执行完整的代码缓存收集,代码=481KB,数据=346KB

2019-07-16 10:56:17.095 13332-13337/com.example.lance.platform I/zygote64:代码缓存收集后,代码=470KB,数据=294KB

但是,如果我点击并且没有任何反应,日志将变为如下:

2019-07-16 10:48:14.443 12870-12870/com.example.lance.platform I/时间轴: 时间轴: Activity_launch_request时间:5151391 intent:Intent { cmp=com.example.lance.platform/.DocsignActivity (有 额外内容) }

2019-07-16 10:48:14.554 12870-12896/com.example.lance.platform D/ViewContentFactory: initViewContentFetcherClass

2019-07-16 10:48:14.554 12870-12896/com.example.lance.platform I/ContentCatcher: ViewContentFetcher : ViewContentFetcher

2019-07-16 10:48:14.554 12870-12896/com.example.lance.platform D/ViewContentFactory:创建拦截器花了 1 毫秒

2019-07-16 10:48:14.810 12870-12875/com.example.lance.platform I/zygote64:编译器分配了 7MB 来编译 void android.widget.TextView.(android.content.Context, android.util.AttributeSet, int, int)

2019-07-16 10:48:14.845 12870-12870/com.example.lance.platform W/Looper:慢帧:doFrame延迟318ms

2019-07-16 10:48:15.065 12870-12870/com.example.lance.platform W/System.err: android.os.NetworkOnMainThreadException

2019-07-16 10:48:15.066 12870-12870/com.example.lance.platform W/System.err: at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1450)

2019-07-16 10:48:15.066 12870-12870/com.example.lance.platform W/System.err: at java.net.SocketInputStream.read(SocketInputStream.java:169)

2019-07-16 10:48:15.066 12870-12870/com.example.lance.platform W/System.err: at java.net.SocketInputStream.read(SocketInputStream.java:139)

2019-07-16 10:48:15.066 12870-12870/com.example.lance.platform W/System.err: at okio.Okio$2.read(Okio.java:139)

2019-07-16 10:48:15.067 12870-12870/com.example.lance.platform W/System.err: at okio.AsyncTimeout$2.read(AsyncTimeout.java:237)

2019-07-16 10:48:15.067 12870-12870/com.example.lance.platform W/System.err: at 奥基奥。RealBufferedSource.read(RealBufferedSource.java:46)

2019-07-16 10:48:15.067 12870-12870/com.example.lance.platform W/System.err: at okhttp3.internal.http1.Http1Codec$FixedLengthSource.read(Http1Codec.java:384)

2019-07-16 10:48:15.067 12870-12870/com.example.lance.platform W/System.err: at okhttp3.internal.Util.skipAll(Util.java:171)

2019-07-16 10:48:15.067 12870-12870/com.example.lance.platform W/System.err: at okhttp3.internal.Util.discard(Util.java:153)

2019-07-16 10:48:15.067 12870-12870/com.example.lance.platform W/System.err: at okhttp3.internal.http1.Http1Codec$FixedLengthSource.close(Http1Codec.java:400)

2019-07-16 10:48:15.067 12870-12870/com.example.lance.platform W/System.err: at 奥基奥。RealBufferedSource.close(RealBufferedSource.java:455)

2019-07-16 10:48:15.068 12870-12870/com.example.lance.platform W/System.err: at okhttp3.internal.Util.closeQuietly(Util.java:106)

2019-07-16 10:48:15.068 12870-12870/com.example.lance.platform W/System.err: at 好的http3.ResponseBody.string(ResponseBody.java:177)

2019-07-16 10:48:15.068 12870-12870/com.example.lance.platform W/System.err: at com.example.lance.platform.DocsignActivity$1$1.run(DocsignActivity.java:229)

2019-07-16 10:48:15.068 12870-12870/com.example.lance.platform W/System.err: at android.os.Handler.handleCallback(Handler.java:794)

2019-07-16 10:48:15.068 12870-12870/com.example.lance.platform W/System.err: at android.os.Handler.dispatchMessage(Handler.java:99)

2019-07-16 10:48:15.068 12870-12870/com.example.lance.platform W/System.err: at android.os.Looper.loop(Looper.java:176)

2019-07-16 10:48:15.068 12870-12870/com.example.lance.platform W/System.err: at android.app.ActivityThread.main(ActivityThread.java:6651)

2019-07-16 10:48:15.069 12870-12870/com.example.lance.platform W/System.err: at java.lang.reflect.Method.invoke(Native Method)

2019-07-16 10:48:15.069 12870-12870/com.example.lance.platform W/System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)

2019-07-16 10:48:15.069 12870-12870/com.example.lance.platform W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:824)

2019-07-16 10:48:15.098 12870-12898/com.example.lance.platform D/OpenGLRenderer: endAllActiveAnimators on 0x6fd8b62000 (ListView) 带手柄0x6fd8ac0460

这段代码有问题。

final String s = response.body().string();

如日志所示,

2019-07-16 10:48:15.068 12870-12870/com.example.lance.platform W/System.err: at okhttp3.ResponseBody.string(ResponseBody.java:177)

很可能网络响应没有完全接收,这将调用网络套接字来获取内容,这些内容最终将成为UI线程上的网络。

所以解决方案是创建一个成员变量 mString 并在 onResponse 中设置:

public void onResponse(Call call, final Response response) throws IOException 
{
mString = response.body().string();

在runOnUiThread中,使用此mString,而不是response.body().string()。

最新更新