Android 回收商 E/AndroidRuntime:致命异常:main

Android Recycler E/AndroidRuntime: FATAL EXCEPTION: main

我正在尝试在 recyclerview 中显示图像列表。但是,当我将图像添加到我的回收站时,我收到一个致命错误。

我把我的回收器放在碎片里:

public class SearchOverviewFragment extends Fragment
{
    private RecyclerView recyclerView;
    private SearchDogAdapter searchDogAdapter;

    private final static String BREED_API = "https://dog.ceo/api/breed/{breed}/images";

    public SearchOverviewFragment()
    {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_search_overview, container, false);

        recyclerView = view.findViewById(R.id.searchRecycler);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

        ArrayList<String> test = new ArrayList<String>();
        test.add("https://images.dog.ceo/breeds/african/n02116738_9829.jpg");
        searchDogAdapter = new SearchDogAdapter(test, (MainActivity) getActivity());

        recyclerView.setAdapter(searchDogAdapter);

        return view;
    }

    public void setBreedURLList(String breed)
    {
        Log.e("URL", "Started");
        if(breed.equals(BreedConstants.DEFAULT_SELECTION))
        {
            searchDogAdapter.updateList(new ArrayList<String>());
            return;
        }

        URL url = null;
        try
        {
            url = new URL(BREED_API.replace("{breed}", breed));
        }
        catch (MalformedURLException e)
        {
            throw new Error("Malformed Breed URL");
        }
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url.toString(), null,
            new Response.Listener<JSONObject>()
            {
                @Override
                public void onResponse(JSONObject response)
                {
                    try
                    {
                        JSONArray listdata = new JSONArray(response.getString("message"));
                        Log.e("ListData: ", String.valueOf(listdata.length()));
                        ArrayList<String> breedsURL = new ArrayList<>();
                        for (int i = 0; i < listdata.length(); i++)
                        {
                            Log.w("test", listdata.getString(i));
                            breedsURL.add(listdata.getString(i));
                        }

                        searchDogAdapter.updateList(breedsURL);

                    }
                    catch (JSONException jsonException)
                    {
                        jsonException.printStackTrace();
                    }
                }
            },
            new Response.ErrorListener()
            {
                @Override
                public void onErrorResponse(VolleyError error)
                {
                    error.printStackTrace();
                }
            });

        RequestQueue queue = Volley.newRequestQueue(getActivity());

        queue.add(jsonObjectRequest);
    }
}

我的适配器 包裹 com.example.mydogapplication.services.adapters;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.recyclerview.widget.RecyclerView;

import com.example.mydogapplication.R;
import com.example.mydogapplication.controllers.MainActivity;
import com.example.mydogapplication.models.viewholders.SearchDogVH;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

public class SearchDogAdapter extends RecyclerView.Adapter<SearchDogVH>
{
    private List<String> _breedsURL;
    private MainActivity _context;

    public SearchDogAdapter(List<String> breedsURL, MainActivity context){
        _breedsURL = breedsURL;
        _context = context;
    }

    @Override
    public SearchDogVH onCreateViewHolder(ViewGroup parent, int viewType)
    {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View view = inflater.inflate(R.layout.item_search_dog, parent, false);

        return new SearchDogVH(view);
    }

    @Override
    public void onBindViewHolder(SearchDogVH holder, int position)
    {
        URL url = null;
        try
        {
            url = new URL(_breedsURL.get(position));
            Bitmap bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
            holder.imageView.setImageBitmap(bmp);
        }
        catch (MalformedURLException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    @Override
    public int getItemCount()
    {
        return _breedsURL.size();
    }

    public void updateList(List<String> breedsURL)
    {
        _breedsURL.clear();

        _breedsURL.addAll(breedsURL);
        Log.e("Test: ", _breedsURL.toString());

        notifyDataSetChanged();
    }
}

ViewHolder

package com.exampler.mydogapplication.models.viewholders;

import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import androidx.recyclerview.widget.RecyclerView;
import com.example.mydogapplication.R;


public class SearchDogVH extends RecyclerView.ViewHolder
{
    public ImageView imageView;
    public Button buttonView;

    public SearchDogVH(View view)
    {
        super(view);

        imageView = view.findViewById(R.id.imageSearchDog);
        buttonView = view.findViewById(R.id.buttonSearchDog);
    }
}

如果我提供一个空的 arraylist 应用程序启动时没有错误,但是在调用 setBreedURLList 时我收到相同的致命异常,并且包含数据的 ArrayList 被添加到我的适配器中。为什么我的应用程序在我向 Adaper 添加数据时崩溃?

更新:崩溃日志

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.mydogapplication, PID: 10497
    android.os.NetworkOnMainThreadException
        at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1605)
        at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:115)
        at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:103)
        at java.net.InetAddress.getAllByName(InetAddress.java:1152)
        at com.android.okhttp.Dns.lookup(Dns.java:41)
        at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:178)
        at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:144)
        at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:86)
        at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:176)
        at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:128)
        at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:97)
        at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:289)
        at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:232)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:465)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:411)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:248)
        at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getInputStream(DelegatingHttpsURLConnection.java:211)
        at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:30)
        at com.example.mydogapplication.services.adapters.SearchDogAdapter.onBindViewHolder(SearchDogAdapter.java:46)
        at com.example.mydogapplication.services.adapters.SearchDogAdapter.onBindViewHolder(SearchDogAdapter.java:20)
        at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7065)
        at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7107)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6012)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6279)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
        at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
        at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627)
        at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
        at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
        at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
        at android.view.View.layout(View.java:22844)
E/AndroidRuntime:     at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at androidx.appcompat.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:530)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
        at com.android.internal.policy.DecorView.onLayout(DecorView.java:784)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:3470)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2938)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1952)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8171)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:972)
        at android.view.Choreographer.doCallbacks(Choreographer.java:796)
        at android.view.Choreographer.doFrame(Choreographer.java:731)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:957)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

您正在尝试在主应用程序线程上执行网络 I/O。这是默认禁止的,因为这几乎保证了糟糕的用户体验,因为你的 UI 在 I/O 正在进行时被阻止。

一个编写良好的图像加载库(Glide、Picasso、coil 等)将在后台线程上执行网络 I/O,仅在主应用程序线程上更新您的 ImageView图片准备就绪时。

我使用 NetworkImageView 而不是常规 ImageView 解决了我的问题