Android Studio(Java)RecyclerView在尝试解析JSON时崩溃



在过去的几天里,我一直在尝试在我的移动应用程序中实现一个回收视图,该视图将用图片显示所有结果。对于这个项目,我使用的是spoonacular API。我的问题是,每次我尝试运行它时,应用程序都会崩溃,并显示以下错误消息。在出现错误消息之前,我可以看到我收到了来自api的响应,但回收器视图没有膨胀。

当我注释掉整个parseJSON((时,会出现视图,但它显然只是一个空页面。

我也尝试了JsonObjectRequest stringRequest = new JsonObjectRequest(Request.Method.GET, uri.toString(), null, new Response.Listener<JSONObject>() {而不是当前的StringRequest

是我的解析JSON函数有问题,还是我看错了地方,适配器导致了viewholder的问题?

Logcat消息:

2021-12-15 20:34:32.138 28763-28763/com.example.foodapp D/AndroidRuntime: Shutting down VM
2021-12-15 20:34:32.142 28763-28763/com.example.foodapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.foodapp, PID: 28763
android.content.res.Resources$NotFoundException: Resource ID #0x0
at android.content.res.ResourcesImpl.getValue(ResourcesImpl.java:237)
at android.content.res.Resources.loadXmlResourceParser(Resources.java:2400)
at android.content.res.Resources.getLayout(Resources.java:1252)
at android.view.LayoutInflater.inflate(LayoutInflater.java:530)
at com.example.foodapp.FoodsAdapter.onCreateViewHolder(FoodsAdapter.java:28)
at com.example.foodapp.FoodsAdapter.onCreateViewHolder(FoodsAdapter.java:18)
at androidx.recyclerview.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:7078)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6235)
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 androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1873)
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 androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1873)
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 androidx.appcompat.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:536)
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)
2021-12-15 20:34:32.142 28763-28763/com.example.foodapp E/AndroidRuntime:     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)

JSON结果到搜索项";鸡肉;

{
"results": [{
"vegetarian": false,
"vegan": false,
"glutenFree": false,
"dairyFree": false,
"veryHealthy": true,
"cheap": false,
"veryPopular": false,
"sustainable": false,
"weightWatcherSmartPoints": 11,
"gaps": "no",
"lowFodmap": false,
"aggregateLikes": 2,
"spoonacularScore": 92.0,
"healthScore": 90.0,
"creditsText": "Foodista.com – The Cooking Encyclopedia Everyone Can Edit",
"license": "CC BY 3.0",
"sourceName": "Foodista",
"pricePerServing": 168.12,
"id": 654959,
"title": "Pasta With Tuna",
"readyInMinutes": 45,
"servings": 4,
"sourceUrl": "http://www.foodista.com/recipe/K6QWSKQM/pasta-with-tuna",
"image": "https://spoonacular.com/recipeImages/654959-312x231.jpg",
"imageType": "jpg",
"summary": "Pasta With Tuna might be just the main course you are searching for. One serving contains <b>421 calories</b>, <b>24g of protein</b>, and <b>10g of fat</b>. For <b>$1.68 per serving</b>, this recipe <b>covers 28%</b> of your daily requirements of vitamins and minerals. 1 person were impressed by this recipe. Head to the store and pick up flour, onion, peas, and a few other things to make it today. It is a good option if you're following a <b>pescatarian</b> diet. All things considered, we decided this recipe <b>deserves a spoonacular score of 92%</b>. This score is excellent. Try <a href="https://spoonacular.com/recipes/pasta-and-tuna-salad-ensalada-de-pasta-y-atn-226303">Pastan and Tuna Salad (Ensalada de Pasta y Atún)</a>, <a href="https://spoonacular.com/recipes/tuna-pasta-565100">Tuna Pasta</a>, and <a href="https://spoonacular.com/recipes/tuna-pasta-89136">Tuna Pasta</a> for similar recipes.",
"cuisines": [],
"dishTypes": ["lunch", "main course", "main dish", "dinner"],
"diets": ["pescatarian"],
"occasions": [],
"analyzedInstructions": [{
"name": "",
"steps": [{
"number": 1,
"step": "Cook pasta in a large pot of boiling water until al dente.",
"ingredients": [{
"id": 20420,
"name": "pasta",
"localizedName": "pasta",
"image": "fusilli.jpg"
}, {
"id": 14412,
"name": "water",
"localizedName": "water",
"image": "water.png"
}],
"equipment": [{
"id": 404752,
"name": "pot",
"localizedName": "pot",
"image": "stock-pot.jpg"
}]
}, {
"number": 2,
"step": "Drain and return to warm pot. Put olive oil in saucepan and add onion.",
"ingredients": [{
"id": 4053,
"name": "olive oil",
"localizedName": "olive oil",
"image": "olive-oil.jpg"
}, {
"id": 11282,
"name": "onion",
"localizedName": "onion",
"image": "brown-onion.png"
}],
"equipment": [{
"id": 404669,
"name": "sauce pan",
"localizedName": "sauce pan",
"image": "sauce-pan.jpg"
}, {
"id": 404752,
"name": "pot",
"localizedName": "pot",
"image": "stock-pot.jpg"
}]
}, {
"number": 3,
"step": "Saute until transparent. Stir in flour and cook for a few seconds and then whisk in milk. Stir constantly until this thickens.",
"ingredients": [{
"id": 20081,
"name": "all purpose flour",
"localizedName": "all purpose flour",
"image": "flour.png"
}, {
"id": 1077,
"name": "milk",
"localizedName": "milk",
"image": "milk.png"
}],
"equipment": [{
"id": 404661,
"name": "whisk",
"localizedName": "whisk",
"image": "whisk.png"
}]
}, {
"number": 4,
"step": "Add peas, tuna (shredded into chunks,) parsley, green onions, cheese and hot pepper sauce.",
"ingredients": [{
"id": 6168,
"name": "hot sauce",
"localizedName": "hot sauce",
"image": "hot-sauce-or-tabasco.png"
}, {
"id": 11291,
"name": "green onions",
"localizedName": "green onions",
"image": "spring-onions.jpg"
}, {
"id": 11297,
"name": "parsley",
"localizedName": "parsley",
"image": "parsley.jpg"
}, {
"id": 1041009,
"name": "cheese",
"localizedName": "cheese",
"image": "cheddar-cheese.png"
}, {
"id": 11304,
"name": "peas",
"localizedName": "peas",
"image": "peas.jpg"
}, {
"id": 10015121,
"name": "tuna",
"localizedName": "tuna",
"image": "canned-tuna.png"
}],
"equipment": []
}, {
"number": 5,
"step": "Pour over pasta and stir gently to mix.",
"ingredients": [{
"id": 20420,
"name": "pasta",
"localizedName": "pasta",
"image": "fusilli.jpg"
}],
"equipment": []
}, {
"number": 6,
"step": "Serve at once.",
"ingredients": [],
"equipment": []
}]
}],
"spoonacularSourceUrl": "https://spoonacular.com/pasta-with-tuna-654959"
}, {
"vegetarian": false,
"vegan": false,
"glutenFree": false,
"dairyFree": false,
"veryHealthy": false,
"cheap": false,
"veryPopular": false,
"sustainable": false,
"weightWatcherSmartPoints": 24,
"gaps": "no",
"lowFodmap": false,
"aggregateLikes": 1,
"spoonacularScore": 67.0,
"healthScore": 28.0,
"creditsText": "Pick Fresh Foods",
"license": "CC BY 3.0",
"sourceName": "Pick Fresh Foods",
"pricePerServing": 274.82,
"id": 511728,
"title": "Pasta Margherita",
"readyInMinutes": 45,
"servings": 4,
"sourceUrl": "http://pickfreshfoods.com/pasta-margherita/",
"image": "https://spoonacular.com/recipeImages/511728-312x231.jpg",
"imageType": "jpg",
"summary": "Pasta Margherita might be just the main course you are searching for. One serving contains <b>809 calories</b>, <b>34g of protein</b>, and <b>34g of fat</b>. This recipe serves 4 and costs $2.75 per serving. 1 person has made this recipe and would make it again. If you have basil, linguine pasta, garlic clove, and a few other ingredients on hand, you can make it. To use up the olive oil you could follow this main course with the <a href="https://spoonacular.com/recipes/sauteed-banana-granola-and-yogurt-parfait-624619">Sauteed Banana, Granolan and Yogurt Parfait</a> as a dessert. All things considered, we decided this recipe <b>deserves a spoonacular score of 69%</b>. This score is pretty good. Similar recipes include <a href="https://spoonacular.com/recipes/margherita-pizza-with-pesto-pasta-salad-31919">Margherita Pizza With Pesto Pasta Salad</a>, <a href="https://spoonacular.com/recipes/pasta-margherita-with-rhubarb-and-apple-compote-613006">Pasta margherita with rhubarb and apple compote</a>, and <a href="https://spoonacular.com/recipes/margherita-pizzette-516272">Margherita Pizzette</a>.",
"cuisines": [],
"dishTypes": ["lunch", "main course", "main dish", "dinner"],
"diets": [],
"occasions": [],
"analyzedInstructions": [{
"name": "",
"steps": [{
"number": 1,
"step": "Whisk oil, garlic, basil, salt together in large bowl.",
"ingredients": [{
"id": 11215,
"name": "garlic",
"localizedName": "garlic",
"image": "garlic.png"
}, {
"id": 2044,
"name": "basil",
"localizedName": "basil",
"image": "basil.jpg"
}, {
"id": 2047,
"name": "salt",
"localizedName": "salt",
"image": "salt.jpg"
}, {
"id": 4582,
"name": "cooking oil",
"localizedName": "cooking oil",
"image": "vegetable-oil.jpg"
}],
"equipment": [{
"id": 404661,
"name": "whisk",
"localizedName": "whisk",
"image": "whisk.png"
}, {
"id": 404783,
"name": "bowl",
"localizedName": "bowl",
"image": "bowl.jpg"
}]
}, {
"number": 2,
"step": "Add tomatoes and mozzarella then gently toss to combine; set aside.Cook pasta according to package directions for al dente.",
"ingredients": [{
"id": 1026,
"name": "mozzarella",
"localizedName": "mozzarella",
"image": "mozzarella.png"
}, {
"id": 11529,
"name": "tomato",
"localizedName": "tomato",
"image": "tomato.png"
}, {
"id": 20420,
"name": "pasta",
"localizedName": "pasta",
"image": "fusilli.jpg"
}],
"equipment": []
}, {
"number": 3,
"step": "Drain well.",
"ingredients": [],
"equipment": []
}, {
"number": 4,
"step": "Add pasta to tomato mixture and gently toss to combine.",
"ingredients": [{
"id": 11529,
"name": "tomato",
"localizedName": "tomato",
"image": "tomato.png"
}, {
"id": 20420,
"name": "pasta",
"localizedName": "pasta",
"image": "fusilli.jpg"
}],
"equipment": []
}, {
"number": 5,
"step": "Serve immediately.",
"ingredients": [],
"equipment": []
}]
}],
"spoonacularSourceUrl": "https://spoonacular.com/pasta-margherita-511728"
}],
"offset": 0,
"number": 2,
"totalResults": 211
}

我的回收者查看片段

public class RecyclerViewFragment extends Fragment {
private RecyclerView mRecyclerView;
private FoodsAdapter mFoodsAdapter;
private ArrayList<FoodListItem> mFoodList = new ArrayList<FoodListItem>();
private RequestQueue mRequestQueue;
private static final String TAG = "RecyclerViewFragment";

// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
public static final String ARG_FOOD_NAME = "foodName";
public static final String ARG_DIET_PLAN = "dietPlan";
private String mFoodName;
private String mDietPlan;
public RecyclerViewFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param foodName the name of the food from user input.
* @param dietPlan the diet plan selected on the spinner.
* @return A new instance of fragment RecyclerViewFragment.
*/
public static RecyclerViewFragment newInstance(String foodName, String dietPlan) {
RecyclerViewFragment fragment = new RecyclerViewFragment();
Bundle args = new Bundle();
args.putString(ARG_FOOD_NAME, foodName);
args.putString(ARG_DIET_PLAN, dietPlan);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mFoodName = getArguments().getString(ARG_FOOD_NAME);
mDietPlan = getArguments().getString(ARG_DIET_PLAN);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_recycler_view, container, false);
mRecyclerView = view.findViewById(R.id.rv_foodlist);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(view.getContext()));
mRecyclerView.setAdapter(new FoodsAdapter(mFoodList));
mFoodList = new ArrayList<>();
mRequestQueue = Volley.newRequestQueue(view.getContext());
return view;
}
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
parseJSON();
}
private void parseJSON() {
Uri uri = Utils.buildUri("https://api.spoonacular.com/recipes/complexSearch?apiKey=5da441b5a0254a19a401525d92b6cd73", "query", mFoodName, "addRecipeInformation", "true","number", "2");
StringRequest stringRequest = new StringRequest(Request.Method.GET, uri.toString(), new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d(TAG, response);
try {
// fetch JSONArray named results
JSONObject rootObject = new JSONObject(response);
JSONArray jsonArray = rootObject.getJSONArray("results");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject result = jsonArray.getJSONObject(i);
mFoodList.add(new FoodListItem(result.getString("title"), result.getString("image"), result.getInt("readyInMinutes")));
}
mFoodsAdapter = new FoodsAdapter(mFoodList);
mRecyclerView.setAdapter(mFoodsAdapter);
} catch (JSONException e) {
Toast.makeText(getActivity(), getString(R.string.toast_error_downloading_food), Toast.LENGTH_LONG);
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
mRequestQueue.add(stringRequest);
}
}

我的RecyclerView适配器

public class FoodsAdapter extends RecyclerView.Adapter<FoodsAdapter.RecyclerViewHolder> {
private ArrayList<FoodListItem> mFoodList;
public FoodsAdapter(ArrayList<FoodListItem> foodList){
mFoodList = foodList;
}
@NonNull
@Override
public RecyclerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
return new RecyclerViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull RecyclerViewHolder holder, int position) {
FoodListItem currentItem = mFoodList.get(position);
String imageUrl = currentItem.getImageUrl();
String foodName = currentItem.getFoodName();
int timeToMake = currentItem.getTimeToMake();
holder.mTextViewFoodName.setText(foodName);
holder.mTextViewTimeToMake.setText("Preparation time: " + timeToMake);
Picasso.get().load(imageUrl).fit().centerInside().into(holder.mImageView);
}
@Override
public int getItemCount() {
if (mFoodList != null)
return mFoodList.size();
else
return 0;
}
public class RecyclerViewHolder extends RecyclerView.ViewHolder{
public ImageView mImageView;
public TextView mTextViewFoodName;
public TextView mTextViewTimeToMake;
public RecyclerViewHolder(@NonNull View itemView) {
super(itemView);
mImageView = itemView.findViewById(R.id.iv_title_image);
mTextViewFoodName = itemView.findViewById(R.id.tv_food_name);
mTextViewTimeToMake = itemView.findViewById(R.id.tv_food_time_to_make);
}
}
}

FoodListItem.java

public class FoodListItem {
private String mImageUrl;
private String mFoodName;
private int mTimeToMake;
public FoodListItem(String imageUrl, String foodName, int timeToMake) {
mImageUrl = imageUrl;
mFoodName = foodName;
mTimeToMake = timeToMake;
}
public String getImageUrl(){
return mImageUrl;
}
public void setFoodName(String inFoodName){
this.mFoodName = inFoodName;
}
public String getFoodName(){
return mFoodName;
}
public int getTimeToMake(){
return mTimeToMake;
}
}

Uri生成器

@NonNull
public static Uri buildUri(String base, String paramName, String paramValue, String requestParamName, String requestParamValue, String numberOfItemsName, String numberOfItemsValue){
Uri uri = Uri.parse(base);
// create a URI Builder and add the parameter
Uri.Builder uriBuilder = uri.buildUpon();
uriBuilder.appendQueryParameter(paramName, paramValue).appendQueryParameter(requestParamName, requestParamValue).appendQueryParameter(numberOfItemsName, numberOfItemsValue);
return uriBuilder.build();
}

正如我在您的适配器中看到的,请检查BindViewHolder((。您必须膨胀布局项来代替viewType,下面的代码将根据您的要求运行。请运行以下代码

/////////////我的RecyclerView片段/////////\////////

public class RecyclerViewFragment extends AppCompatActivity {
private RecyclerView mRecyclerView;
private FoodsAdapter mFoodsAdapter;
private ArrayList<FoodListItem> mFoodList = new ArrayList<FoodListItem>();
private RequestQueue mRequestQueue;
private static final String TAG = "RecyclerViewFragment";
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
public static final String ARG_FOOD_NAME = "foodName";
public static final String ARG_DIET_PLAN = "dietPlan";
private String mFoodName = "foodName";
private String mDietPlan = "dietPlan";
private Uri buildUri(String base, String paramName, String paramValue, String requestParamName, String requestParamValue, String numberOfItemsName, String numberOfItemsValue) {
Uri uri = Uri.parse(base);
// create a URI Builder and add the parameter
Uri.Builder uriBuilder = uri.buildUpon();
uriBuilder.appendQueryParameter(paramName, paramValue).appendQueryParameter(requestParamName, requestParamValue).appendQueryParameter(numberOfItemsName, numberOfItemsValue);
return uriBuilder.build();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler_view_fragment);
mRecyclerView = findViewById(R.id.rv_foodlist);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setAdapter(new FoodsAdapter(mFoodList));
mFoodList = new ArrayList<>();
mRequestQueue = Volley.newRequestQueue(this);
parseJSON();
}
private void parseJSON() {
Uri uri = buildUri("https://api.spoonacular.com/recipes/complexSearch?apiKey=5da441b5a0254a19a401525d92b6cd73", "query", "chicken", "addRecipeInformation", "true", "number", "2");
StringRequest stringRequest = new StringRequest(Request.Method.GET, uri.toString(), new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d(TAG, response);
try {
// fetch JSONArray named results
JSONObject rootObject = new JSONObject(response);
JSONArray jsonArray = rootObject.getJSONArray("results");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject result = jsonArray.getJSONObject(i);
mFoodList.add(new FoodListItem(result.getString("image"), result.getString("title"), result.getInt("readyInMinutes")));
}
mFoodsAdapter = new FoodsAdapter(mFoodList);
mRecyclerView.setAdapter(mFoodsAdapter);
} catch (JSONException e) {
Toast.makeText(RecyclerViewFragment.this, getString(R.string.toast_error_downloading_food), Toast.LENGTH_LONG);
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
mRequestQueue.add(stringRequest);
}
}

//////////////我的RecyclerView适配器/////////////////

public class FoodsAdapter extends RecyclerView.Adapter<FoodsAdapter.RecyclerViewHolder> {
private ArrayList<FoodListItem> mFoodList;
public FoodsAdapter(ArrayList<FoodListItem> foodList) {
mFoodList = foodList;
}
@NonNull
@Override
public RecyclerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.foods, parent, false);
return new RecyclerViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull RecyclerViewHolder holder, int position) {
FoodListItem currentItem = mFoodList.get(position);
String imageUrl = currentItem.getImageUrl();
String foodName = currentItem.getFoodName();
int timeToMake = currentItem.getTimeToMake();
holder.mTextViewFoodName.setText(foodName);
holder.mTextViewTimeToMake.setText("Preparation time: " + timeToMake);
Picasso.get().load(imageUrl).fit().centerInside().into(holder.mImageView);
}
@Override
public int getItemCount() {
if (mFoodList != null)
return mFoodList.size();
else
return 0;
}
public class RecyclerViewHolder extends RecyclerView.ViewHolder {
public ImageView mImageView;
public TextView mTextViewFoodName;
public TextView mTextViewTimeToMake;
public RecyclerViewHolder(@NonNull View itemView) {
super(itemView);
mImageView = itemView.findViewById(R.id.iv_title_image);
mTextViewFoodName = itemView.findViewById(R.id.tv_food_name);
mTextViewTimeToMake = itemView.findViewById(R.id.tv_food_time_to_make);
}
}
}

//////添加食物.xml/////////

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp">

<ImageView
android:id="@+id/iv_title_image"
android:layout_width="60dp"
android:layout_height="60dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/whatsappchatbackground" />
<TextView
android:id="@+id/tv_food_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="TextView"
android:textSize="14sp"
android:textAlignment="center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/iv_title_image"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_food_time_to_make"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="TextView"
android:textSize="14sp"
android:textAlignment="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/iv_title_image" />
</androidx.constraintlayout.widget.ConstraintLayout>

//////////////FoodListItem.java/////////

public class FoodListItem {
private String mImageUrl;
private String mFoodName;
private int mTimeToMake;
public FoodListItem(String imageUrl, String foodName, int timeToMake) {
mImageUrl = imageUrl;
mFoodName = foodName;
mTimeToMake = timeToMake;
}
public String getImageUrl() {
return mImageUrl;
}
public void setFoodName(String inFoodName) {
this.mFoodName = inFoodName;
}
public String getFoodName() {
return mFoodName;
}
public int getTimeToMake() {
return mTimeToMake;
}
}

最新更新