1

I use OkHttpClient to fetch data from server and show it in runOnUiThread event, but the event does not always work

Basic logic is that I tap on a button, and OkHttpClient gets a json from the server, parse it and shows me the json data. Don't know why, sometimes it works fine but in more cases I need to tap for several times for this to work. I test and find out that the json data is always successfully fetched so the problems seems to be that the runOnUiThread event is not triggered in a proper way? Sorry I'm new to android

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(); }
            });
            }
    });
}

no error message at all. What I need is that each time I tap the button I can see the AttachCount correctly, instead of tapping for 10 times and only 1 time works

when it works fine, the log is very simple like this:

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

Timeline: Activity_launch_request time:5633500 intent:Intent { cmp=com.example.lance.platform/.DocsignActivity (has extras) }

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: Do full code cache collection, code=481KB, data=346KB

2019-07-16 10:56:17.095 13332-13337/com.example.lance.platform I/zygote64: After code cache collection, code=470KB, data=294KB

But if I tap and nothing happens, the log becomes as below:

2019-07-16 10:48:14.443 12870-12870/com.example.lance.platform I/Timeline: Timeline: Activity_launch_request time:5151391 intent:Intent { cmp=com.example.lance.platform/.DocsignActivity (has extras) }

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: createInterceptor took 1ms

2019-07-16 10:48:14.810 12870-12875/com.example.lance.platform I/zygote64: Compiler allocated 7MB to compile 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: Slow Frame: doFrame is 318ms late

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 okio.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 okio.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 okhttp3.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) with handle 0x6fd8ac0460

shb
  • 5,957
  • 2
  • 15
  • 32
Lance
  • 21
  • 2
  • A good idea is to have debug logs. It makes it easier to find the source of these problems – Kevin Jul 15 '19 at 09:51
  • yeah post your logs must be a minor problem\ – Pemba Tamang Jul 15 '19 at 10:31
  • I think you can just need the `setText` to be just the only content of `runOnUiThread`. Also one trick I do is pass the `View` I need to do something on as parameter of a method. And please learn to format your questions properly, especially the log part. – rminaj Jul 16 '19 at 04:33
  • somewhat on-topic, `onResponse` is already on the UI-thread, so no need to call `runOnUiThread`. – Zun Jul 16 '19 at 07:11
  • Thanks but the problem still occurs. Also I formatted the log as advised – Lance Jul 16 '19 at 07:13
  • In that case attach a debugger. Please read on Google how to use it. Example link: https://developer.android.com/studio/debug – Zun Jul 16 '19 at 07:15
  • You are parsing a huge JSON string in the Main Thread. – Enzokie Jul 16 '19 at 07:24
  • *when it works fine, the log is very simple like this:* ?? this log is full of errors – Tim Jul 16 '19 at 08:04
  • @Enzokie This is the point! I tried to simplify the json file and the problem is solved! Again thanks for everyone! – Lance Jul 16 '19 at 10:04

1 Answers1

0

This code has problem.

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

As the log indicates,

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

It is very possible network response is not fully received and this will call network socket to get content which will finally become network on UI thread.

So solution is create a member variable mString and set in onResponse:

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

and in runOnUiThread, use this mString, instead of response.body().string().

AIMIN PAN
  • 1,563
  • 1
  • 9
  • 13