
在android应用开发中,直接将r.drawable的整数id存储在外部数据(如json)中并在运行时使用会导致resources$notfoundexception,因为这些id在每次编译后可能不稳定。本文将详细介绍如何通过将drawable的字符串名称存储在数据模型中,并利用context.getresources().getidentifier()方法在运行时动态查找并加载对应的drawable资源,从而优雅地解决这一问题。
在Android项目中,我们通过R.drawable.image_name来引用图片资源。这里的R.drawable.image_name实际上是一个由AAPT(Android Asset Packaging Tool)在编译时生成的整数ID。这个ID在每次项目编译时都可能发生变化,因此它并不是一个稳定的、可以长期存储在外部文件(如JSON、数据库或SharedPreferences)中的标识符。
当我们将这些不稳定的整数ID存储在JSON文件中,并在运行时尝试通过ImageView.setImageResource()方法加载时,如果当前的编译生成的ID与JSON中存储的ID不匹配,系统将无法找到对应的资源,从而抛出android.content.res.Resources$NotFoundException异常。
例如,原始代码中尝试直接使用从JSON中读取的整数ID:
// Ingredient.java
public class Ingredient {
// ...
private int ingredientDrawableTag; // 存储的是整数ID
// ...
}
// IngredientRecyclerViewAdapter.java
@Override
public void onBindViewHolder(@NonNull IngredientViewHolder holder, int position) {
holder.imageView.setImageResource(this.ingredients[position].getIngredientDrawableTag()); // 运行时可能找不到资源
}而JSON数据可能如下:
{
"ingredient_name": "Tomato",
"ingredient_drawable_tag": 700003 // 这个ID在下次编译时可能就变了
}这种做法虽然直观,但由于资源ID的不稳定性,在实际应用中极易导致运行时错误。
为了解决资源ID不稳定的问题,最佳实践是避免在外部数据中存储资源ID的整数值。取而代之,我们应该存储资源的字符串名称。Android提供了一个API,允许我们根据资源的名称在运行时动态查找其对应的整数ID。
核心思路如下:
首先,我们需要更新Ingredient数据类,将ingredientDrawableTag字段的类型从int更改为String。
package me.eyrim.foodrecords2;
import com.google.gson.annotations.SerializedName;
public class Ingredient {
@SerializedName("ingredient_name")
private String ingredientName;
@SerializedName("ingredient_drawable_tag")
private String ingredientDrawableTag; // 类型改为String
public String getIngredientName() {
return this.ingredientName;
}
public String getIngredientDrawableTag() { // 返回类型也改为String
return this.ingredientDrawableTag;
}
}相应的,JSON数据也需要更新,存储Drawable的名称,例如"tomato"对应R.drawable.tomato。
{
"recipe_name": "My test recipe 1 updated",
"recipe_id": "0",
"recipe_desc": "this is a test desc for my test recipe 1",
"ingredients": [{
"ingredient_name": "Tomato",
"ingredient_drawable_tag": "tomato" // 存储Drawable的名称
},
{
"ingredient_name": "Pepper",
"ingredient_drawable_tag": "pepper" // 存储Drawable的名称
}
]
}接下来,在RecyclerView.Adapter的onBindViewHolder方法中,我们需要利用Context实例来调用getResources().getIdentifier()方法。这意味着IngredientRecyclerViewAdapter需要能够访问到Context。
首先,修改适配器的构造函数以接收Context并将其保存为成员变量:
package me.eyrim.foodrecords2.recipeviewactivity;
import android.content.Context; // 导入Context
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import me.eyrim.foodrecords2.Ingredient;
import me.eyrim.foodrecords2.R;
public class IngredientRecyclerViewAdapter extends RecyclerView.Adapter<IngredientRecyclerViewAdapter.IngredientViewHolder> {
private final Ingredient[] ingredients;
private final Context context; // 保存Context实例
public IngredientRecyclerViewAdapter(Ingredient[] ingredients, Context context) {
this.ingredients = ingredients;
this.context = context; // 初始化Context
}
// ... 其他方法不变
}然后,在onBindViewHolder方法中,使用context.getResources().getIdentifier()来获取Drawable的实际ID:
public class IngredientRecyclerViewAdapter extends RecyclerView.Adapter<IngredientRecyclerViewAdapter.IngredientViewHolder> {
// ...
@Override
public void onBindViewHolder(@NonNull IngredientViewHolder holder, int position) {
String drawableName = this.ingredients[position].getIngredientDrawableTag();
int drawableId = context.getResources().getIdentifier(
drawableName, // Drawable的名称
"drawable", // 资源类型
context.getPackageName() // 应用包名
);
if (drawableId != 0) { // 检查是否成功找到资源
holder.imageView.setImageResource(drawableId);
} else {
// 处理资源未找到的情况,例如设置一个默认图片
holder.imageView.setImageResource(R.drawable.default_ingredient_image);
// 或者记录日志
// Log.w("IngredientAdapter", "Drawable not found for name: " + drawableName);
}
}
// ...
}通过将Drawable资源的字符串名称存储在外部数据中,并结合Context.getResources().getIdentifier()方法在运行时动态查找资源ID,我们能够有效地解决Android资源ID不稳定性带来的问题。这种方法不仅提高了应用的健壮性和可维护性,也使得数据模型与UI资源的解耦更加优雅,是Android开发中处理动态资源加载的推荐实践。
以上就是Android开发:动态加载Drawable资源以解决ID不稳定性问题的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号