【问题标题】:Response is not showing while fetching data from an api从 api 获取数据时未显示响应
【发布时间】:2020-02-20 21:04:20
【问题描述】:

我正在尝试从 api 获取数据,但我收到以下错误我无法找出问题出在哪里我使用单独的 UI 线程来获取数据然后应用程序也崩溃了。

2020-02-20 17:20:01.088 22802-22802/com.example.flypped E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.flypped, PID: 22802
android.os.NetworkOnMainThreadException
    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1513)
    at com.android.org.conscrypt.Platform.blockGuardOnNetwork(Platform.java:415)
    at com.android.org.conscrypt.ConscryptFileDescriptorSocket$SSLInputStream.read(ConscryptFileDescriptorSocket.java:560)
    at okio.InputStreamSource.read(Okio.kt:102)
    at okio.AsyncTimeout$source$1.read(AsyncTimeout.kt:159)
    at okio.RealBufferedSource.request(RealBufferedSource.kt:62)
    at okio.RealBufferedSource.require(RealBufferedSource.kt:55)
    at okio.RealBufferedSource.readHexadecimalUnsignedLong(RealBufferedSource.kt:299)
    at okhttp3.internal.http1.Http1ExchangeCodec$ChunkedSource.readChunkSize(Http1ExchangeCodec.kt:450)
    at okhttp3.internal.http1.Http1ExchangeCodec$ChunkedSource.read(Http1ExchangeCodec.kt:429)
    at okhttp3.internal.connection.Exchange$ResponseBodySource.read(Exchange.kt:279)
    at okio.RealBufferedSource.select(RealBufferedSource.kt:93)
    at okhttp3.internal.Util.readBomAsCharset(Util.kt:256)
    at okhttp3.ResponseBody.string(ResponseBody.kt:187)
    at com.example.flypped.MainActivity$2$1.run(MainActivity.java:110)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7156)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975)
    Suppressed: android.os.NetworkOnMainThreadException
    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1513)
    at com.android.org.conscrypt.Platform.blockGuardOnNetwork(Platform.java:415)
    at com.android.org.conscrypt.ConscryptFileDescriptorSocket$SSLInputStream.read(ConscryptFileDescriptorSocket.java:560)
    at okio.InputStreamSource.read(Okio.kt:102)
    at okio.AsyncTimeout$source$1.read(AsyncTimeout.kt:159)
    at okio.RealBufferedSource.request(RealBufferedSource.kt:62)
    at okio.RealBufferedSource.require(RealBufferedSource.kt:55)
    at okio.RealBufferedSource.readHexadecimalUnsignedLong(RealBufferedSource.kt:299)
    at okhttp3.internal.http1.Http1ExchangeCodec$ChunkedSource.readChunkSize(Http1ExchangeCodec.kt:450)
    at okhttp3.internal.http1.Http1ExchangeCodec$ChunkedSource.read(Http1ExchangeCodec.kt:429)
    at okhttp3.internal.Util.skipAll(Util.kt:337)
    at okhttp3.internal.Util.discard(Util.kt:358)
    at okhttp3.internal.http1.Http1ExchangeCodec$ChunkedSource.close(Http1ExchangeCodec.kt:471)
    at okio.ForwardingSource.close(ForwardingSource.kt:34)
    at okhttp3.internal.connection.Exchange$ResponseBodySource.close(Exchange.kt:306)
    at okio.RealBufferedSource.close(RealBufferedSource.kt:461)
    at kotlin.io.CloseableKt.closeFinally(Closeable.kt:56)
    at okhttp3.ResponseBody.string(ResponseBody.kt:186)

下面是我的代码:

XML 代码:

 <?xml version="1.0" encoding="utf-8"?>

<androidx.drawerlayout.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/drawer_layout"
android:fitsSystemWindows="true"
tools:context=".MainActivity"
tools:openDrawer="start">


<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">

<com.google.android.material.appbar.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppTheme.AppBarOverlay">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay" />

</com.google.android.material.appbar.AppBarLayout>

<include layout="@layout/content_main" />

<com.google.android.material.bottomnavigation.BottomNavigationView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/bottomBar"
    android:layout_gravity="bottom"
    app:menu="@menu/bottom_menu"
    android:background="#fff"
    app:itemIconTint="@drawable/nav_check"
    app:itemTextColor="@drawable/nav_check"/>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

<com.google.android.material.navigation.NavigationView
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:id="@+id/nav_view">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <include
            layout="@layout/nav_header"
            android:id="@+id/header"/>

        <androidx.recyclerview.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/header"
            android:id="@+id/menuRecycler"
            android:layout_marginTop="20dp"/>

    </RelativeLayout>

</com.google.android.material.navigation.NavigationView>

</androidx.drawerlayout.widget.DrawerLayout>

Java 代码:

 private void getMenuData(){


    OkHttpClient client = new OkHttpClient.Builder()
            .readTimeout(20, TimeUnit.SECONDS)
            .writeTimeout(20,TimeUnit.SECONDS)
            .build();

    Request request = new Request.Builder().url(URL).build();

    client.newCall(request).enqueue(new Callback() {

        @Override
        public void onResponse(@NotNull Call call, @NotNull final Response response) throws IOException {

            runOnUiThread(new Runnable() {
                @Override
                public void run() {

                    try {

                        JSONArray jsonArray = new JSONArray(response.body().string());

                      //  Log.d("array", String.valueOf(jsonArray));

                       if(jsonArray.length() > 0){

                            for(int i=0;i<jsonArray.length();i++){

                                JSONObject jsonObject = jsonArray.getJSONObject(i);

                                String str1 = jsonObject.getString("name");
                                String str2 = jsonObject.getString("term_id");

                                MenuModel model = new MenuModel(str1,str2);
                                list.add(model);
                            }

                            adapter = new MenuAdapter(list,getApplicationContext());
                            menuRecycler.setAdapter(adapter);
                        }

                    } catch (JSONException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        @Override
        public void onFailure(@NotNull Call call, @NotNull final IOException e) {

            runOnUiThread(new Runnable() {
                @Override
                public void run() {

                    Toast.makeText(getApplicationContext(),e.getMessage(),Toast.LENGTH_SHORT).show();
                }
            });
        }

    });

}

Log cat 在下面一行显示错误

JSONArray jsonArray = new JSONArray(response.body().string());

有人请让我知道我做错了什么。任何帮助将不胜感激。

谢谢

【问题讨论】:

  • 它包含 https
  • 删除runOnUiThread部分以避免NetworkOnMainThreadException,它需要在后台线程中运行,默认情况下必须这样做。
  • 在删除 runOnUiThread() 时 ts 显示以下错误 FATAL EXCEPTION: OkHttp Dispatcher
  • runOnUiThread() 用于在单独的线程中执行网络操作
  • 请参阅 Jake Wharton 的 this answer,回调在后台线程中运行,添加 runOnUiThread 会按照字面意思在 UI 线程上运行,从而导致问题。

标签: android


【解决方案1】:

将您的 api 调用放在运行块中。

Thread thread = new Thread(new Runnable() {

    @Override
    public void run() {

       //Your code goes here

    }
});
thread.start(); 

【讨论】:

  • 实际上我在导航抽屉中显示这些数据
  • 您在 getMenuData 方法中编写的需要在运行块中编写的整个代码。
  • 我把我的方法放在运行块中,但仍然报错
  • 尝试将运行块放入方法中。
【解决方案2】:

回调在后台线程上运行。如果您想立即处理 UI 中的某些内容,则需要发布到主线程。

private void hitApi(HttpCallBacks cb){ 
client.newCall(request).enqueue(new Callback() {

        @Override
        public void onResponse(@NotNull Call call, @NotNull final Response response) throws IOException {

            mainHandler.post(new Runnable() {

                    @Override
                    public void run() {
                        cb.onSuccess(null, throwable);
                    }
                });

        }

        @Override
        public void onFailure(@NotNull Call call, @NotNull final IOException e) {

             mainHandler.post(new Runnable() {

                    @Override
                    public void run() {
                        cb.onFailure( throwable);
                    }
                });
        }

    });

}
}
interface HttpCallBacks{
    void onFailure(Throwable t);
    void onSuccess(Response r);

}

【讨论】:

    【解决方案3】:

    在这里试试这个代码,看看它是否有帮助。我在主线程上使用处理程序,因为主要问题是您不能直接使用 UI 线程作为响应,也不能在后台线程中更新 UI。

    您需要再声明 2 个全局变量,例如:

        Handler mainHandler = new Handler(Looper.getMainLooper());
        String mStringResponse;
    

    把你的方法写成:

    private void getMenuData(){
    
            OkHttpClient client = new OkHttpClient.Builder()
                    .readTimeout(20, TimeUnit.SECONDS)
                    .writeTimeout(20,TimeUnit.SECONDS)
                    .build();
    
            Request request = new Request.Builder().url(URL).build();
    
            client.newCall(request).enqueue(new Callback() {
                @Override
                public void onResponse(@NotNull Call call, @NotNull final Response response) throws IOException {
    
                    mStringResponse = String.valueOf(response.body());
    
                    mainHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                JSONArray jsonArray = new JSONArray(mStringResponse);
                                if (jsonArray.length() > 0) {
                                    for (int i = 0; i < jsonArray.length(); i++) {
                                        JSONObject jsonObject = jsonArray.getJSONObject(i);
                                        String str1 = jsonObject.getString("name");
                                        String str2 = jsonObject.getString("term_id");
                                        MenuModel model = new MenuModel(str1, str2);
                                        list.add(model);
                                    }
                                    adapter = new MenuAdapter(list, getApplicationContext());
                                    menuRecycler.setAdapter(adapter);
                                }
                            }catch (JSONException e) { }
    
                        }
                    });
                }
                @Override
                public void onFailure(@NotNull Call call, @NotNull final IOException e) {
                    mainHandler.post(new Runnable() {
                        @Override
                        public void run() { 
                              Toast.makeText(getApplicationContext(),e.getMessage(),Toast.LENGTH_SHORT).show();
                                }
                 } 
            });
    
        }
    
    

    UI 更改应该像这样工作,不确定您的适配器限制,但试试这个并检查它是否有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-03
      • 2021-03-13
      • 2020-11-22
      • 1970-01-01
      • 1970-01-01
      • 2021-01-19
      • 2022-09-25
      • 1970-01-01
      相关资源
      最近更新 更多