问题描述
我正在尝试在回收视图中显示图像列表。但是,当我将图像添加到我的回收器时,我收到一个致命错误。
我将我的回收器放在一个片段中:
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);
}
}
如果我提供一个空的数组列表,应用程序启动时不会出错,但在调用 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$1.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 解决了我的问题