Java 添加一个新的drawable,它正在更改已解析xml的图标

Java 添加一个新的drawable,它正在更改已解析xml的图标,java,android,xml,android-fragments,xml-parsing,Java,Android,Xml,Android Fragments,Xml Parsing,我遇到了一个问题,只有在添加新的drawable时才会出现。 我将xml解析为Fragment,图标设置为int。 如果我添加了新的drawable,那么它会选择random drawable来显示解析的xml 我有一个适配器用于回收列表视图 一个Pojo类和DB,它扩展了SQLiteOpenHelper 如果我清除缓存和存储,那么它将恢复正常, 或者,如果我删除新添加的drawable,它将返回正常状态。 有人能帮我知道为什么更改图标会有影响。 我试图清理项目,并重建相同的。 使缓存无效并重新

我遇到了一个问题,只有在添加新的drawable时才会出现。
我将
xml
解析为
Fragment
图标设置为
int

如果我添加了新的drawable,那么它会选择random drawable来显示解析的
xml

我有一个
适配器
用于
回收列表视图

一个
Pojo
类和
DB
,它扩展了
SQLiteOpenHelper

如果我清除缓存和存储,那么它将恢复正常, 或者,如果我删除新添加的drawable,它将返回正常状态。
有人能帮我知道为什么更改图标会有影响。
我试图清理项目,并重建相同的。 使缓存无效并重新启动,但仍然相同

下面是代码,下面是问题的两张图片

public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

private static final int ITEM_TYPE_ONE = 0;
private static final int ITEM_TYPE_TWO = 1;
private final Handler handler = new Handler();
private final ArrayList<Bookmark> arrayList;
private final String BASE_URL = "https://besticon-demo.herokuapp.com/icon?url=";
private final Context context;

public MyAdapter(Context context, ArrayList<Bookmark> arrayList) {
    this.context = context;
    this.arrayList = arrayList;
}


@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

    View view = null;
    if (viewType == ITEM_TYPE_ONE) {
        view = LayoutInflater.from(context).inflate(R.layout.grid_item, parent, false);
        return new ViewHolder(view);
    } else if (viewType == ITEM_TYPE_TWO) {
        view = LayoutInflater.from(context).inflate(R.layout.add_bookmark, parent, false);
        return new ButtonViewHolder(view);
    } else {
        return null;
    }

}
 public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, final int position) {
    final int itemType = getItemViewType(position);
    final Bookmark bookmark = this.arrayList.get(position);
    if (itemType == ITEM_TYPE_ONE) {
        final ViewHolder viewHolder = (ViewHolder) holder;
        RequestOptions requestOptions = new RequestOptions();
        BookmarkDB bookmarkDB = new BookmarkDB(context);
        String imageUrl = BASE_URL + arrayList.get(position).getSearchUrl() + "&size=32";
        int resID = context.getResources().getIdentifier(String.valueOf(arrayList.get(position).getIcon()), "drawable", context.getPackageName());
        if (resID == 0) {
            Glide.with(context)
                    .load(imageUrl)
                    .apply(requestOptions
                            .placeholder(R.drawable.default_favicon)
                      .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
                            .fitCenter())
                    .into(viewHolder.tvIcon);
        } else {
            viewHolder.tvIcon.setImageResource(resID);
             String imageName = context.getResources().getResourceName(resID);
            Log.d("getIcons", imageName); // This is the log.
    } else if (itemType == ITEM_TYPE_TWO) {
        ButtonViewHolder buttonViewHolder = (ButtonViewHolder) holder;
        buttonViewHolder.imgButton.setImageResource(arrayList.get(position).getIcon());
    }
}
   class ViewHolder extends RecyclerView.ViewHolder {
    final ImageView tvIcon;

    ViewHolder(@NonNull final View itemView) {
        super(itemView);
        tvIcon = itemView.findViewById(R.id.image_view);
    }
}
这是
.XML
文件

<?xml version="1.0" encoding="utf-8"?>
<Bookmarks>
    <Bookmark name="Bing"
 hidden="true"
 icon="bing"
 id="0"
 nativeUrl=""
 searchUrl="https://www.bing.com" />
    <Bookmark
 name="Google"
  hidden="true"
 icon="google"
 id="1" 
nativeUrl=""
 searchUrl="https://www.google.com" />
<Bookmark
    name="Youtube"
    hidden="false"
    icon="youtube"
    id="2"
    nativeUrl="youtube://"
    searchUrl="https://m.youtube.com" />
<Bookmark
    name="Facebook"
    hidden="false"
    icon="facebook"
    id="3"
    nativeUrl="facebook://"
    searchUrl="https://m.facebook.com" />
<Bookmark
    name="Twitter"
    hidden="false"
    icon="twitter"
    id="4"
    nativeUrl=""
    searchUrl="https://mobile.twitter.com/" />
</Bookmarks>
这是
Pojo.class

public class Bookmark implements Parcelable, Comparable, Comparator<Bookmark> {
public static final Creator<Bookmark> CREATOR = new Creator<Bookmark>() {
    @Override
    public Bookmark createFromParcel(Parcel in) {
        return new Bookmark(in);
    }

    @Override
    public Bookmark[] newArray(int size) {
        return new Bookmark[size];
    }
};
private String name;
private String id;
private String nativeUrl;
private String searchUrl;
private String hidden;
private long db_id;
private int icon;
private int viewType;

private Bookmark(Parcel in) {
    name = in.readString();
    id = in.readString();
    nativeUrl = in.readString();
    searchUrl = in.readString();
    db_id = in.readLong();
    icon = in.readInt();
    viewType = in.readInt();
    hidden = in.readString();
}

public Bookmark() {
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public int getIcon() {
    return icon;
}

public void setIcon(int icon) {
    this.icon = icon;
}

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
    this.db_id = Integer.parseInt(id);
}

public String getNativeUrl() {
    return nativeUrl;
}

public void setNativeUrl(String nativeUrl) {
    this.nativeUrl = nativeUrl;
}

public String getSearchUrl() {
    return searchUrl;
}

public void setSearchUrl(String searchUrl) {
    this.searchUrl = searchUrl;
}

public int getViewType() {
    return viewType;
}

public void setViewType(int viewType) {
    this.viewType = viewType;
}

public String getHidden() {
    return hidden;
}

public void setHidden(String hidden) {
    this.hidden = hidden;
}

@Override
public String toString() {
    return "Bookmark{" +
            "name='" + name + '\'' +
            ", id='" + id + '\'' +
            ", nativeUrl='" + nativeUrl + '\'' +
            ", searchUrl='" + searchUrl + '\'' +
            ", hidden='" + hidden + '\'' +
            ", db_id=" + db_id +
            ", icon=" + icon +
            ", viewType=" + viewType +
            '}';
}

@Override
public int compareTo(Object o) {
    return 0;
}

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(name);
    dest.writeString(id);
    dest.writeString(nativeUrl);
    dest.writeString(searchUrl);
    dest.writeLong(db_id);
    dest.writeInt(icon);
    dest.writeInt(viewType);
    dest.writeString(hidden);
}

@Override
public int compare(Bookmark o1, Bookmark o2) {
    return 0;
}
}
我已经创建了一个LogCat来显示它需要什么,这就是结果

正确的方法

drawable/youtube
drawable/facebook
drawable/twitter
添加可绘图或矢量资源或图像后

drawable/wiki
drawable/facebook
drawable/trash

尝试执行
myAdapter.notifyDataSetChanged()在arrayList在FragmentBookmark中添加工作后:

 Bookmark bookmark = new Bookmark();
 bookmark.setViewType(1);
 bookmark.setIcon(R.drawable.add_new_bookmark_icon);
 arrayList.add(bookmark);
 myAdapter.notifyDataSetChanged();
顺便说一句:xml解析工作和数据库操作通常应该异步处理

已更新:将书签中的类型
图标
字段从int更改为String,并修改
loadBookMarksFromXML
中的一些代码,从

int drawableResourceId = 
getResources().getIdentifier(
        xpp.getAttributeValue(null, "icon"), "drawable",mContext.getPackageName());
bookmark.setIcon(drawableResourceId);

在类
MyAdapter
中的
onBindViewHolder
中更改一些代码,从:

int resID = context.getResources().getIdentifier(String.valueOf(arrayList.get(position).getIcon()), "drawable", context.getPackageName());


您可以很容易地修复因更改
图标
字段的类型而导致的其他错误,然后再次运行,让我知道结果。Thx.

也许您应该将图标从res文件夹移动到assets,然后使用Glide加载它

if (getResources().getAssets().list("").contains("icon.png")) {
    Glide.with(fragment)
        .load(Uri.parse("file:///android_asset/icon.png"))
        .into(imageView);
} else {
    // load from web
}

要将图像存储到sqlite或任何其他本地数据库,必须存储变量的名称(我在使用本地数据库时这样做,也许有更好的方法)

所以,当您想要存储可拉伸

使用此代码

bookmark.setIcon("add_new_bookmark_icon");//don't forget to change icon to String in bookmark
而不是这个

bookmark.setIcon(R.drawable.add_new_bookmark_icon);//you use this in onViewCreate and buildBookmarkArrayListfromDB
现在,当您想从数据库中显示drawable时,请使用以下代码

int resourceId = getResources().getIdentifier("", "drawable", getPackageName());
Drawable yourImage = ContextCompat.getDrawable(this,resourceId);
imageView.setImageDrawable(yourImage);

必须将所有位置使用setIcon或getIcon以及所有使用图标的代码更改为int,如
getAllBookmarks
->
csr.getInt(csr.getColumnIndex(COL_图标)
和其他


我几年前就这样做了,但我不检查它是否仍然有效。请尝试并告诉我您正在调用的
String.valueOf(bookmark.getIcon())发生了什么
将图标存储在数据库中。由于图标是表示资源的
int
,因此将资源id存储为字符串。现在的问题是,资源id不稳定,在创建新APK时可能会更改。因此,它在不更新应用程序时工作,但在更新后开始失败

相反,您应该存储res的名称并保持其稳定。您已经在XML数据中使用了该名称,因此我认为这是您的目标

mDB.addBookmark(
        Long.valueOf(bookmark.getId()),
        bookmark.getName(),
        bookmark.getViewType() > 0,
        iconName(bookmark.getIcon()),
        bookmark.getNativeUrl(),
        bookmark.getSearchUrl()
);

String Icon = csr.getString(csr.getColumnIndex(COL_ICON));
b.setIcon(iconRes(Icon));
现在您只需要实现从name到id的映射

String iconName(int icon) {
    return getResources().getResourceEntryName(icon);
}

int iconRes(String icon) {
    return getResources().getIdentifier(icon, "drawable", mContext.getPackageName())
}
此外,您还需要在分离时取消设置
mContext
,或者不存储它,而是使用
getContext()
requireContext()
。当然,如果在某些后台操作中使用它,您必须检查null

@Override
public void onDetach() {
    mContext = null;
    super.onDetach();
}

由于资源id在每次安装或生成apk时都会不断更改,因此明智的做法是存储图标资源的名称,并在显示期间获取它。为此,您可以存储图标名称的字符串值(您也可以使用与书签相同的名称,但确保相同名称的可绘制性)。
将数据库(Bookmark.db)&Pojo中的图标字段更改为字符串。
删除RecyclerView片段中的这一行

                int drawableResourceId = getResources().getIdentifier(xpp.getAttributeValue(null, "icon"), "drawable", mContext.getPackageName());
换行

                bookmark.setIcon(xpp.getAttributeValue(null, "name"));
在MyAdapter类的onBindViewHolder中,使用获取图标资源

int iresourceid = getResources().getIdentifier(arrayList.get(position).getIcon(),"drawable",getPackageName());

这也是同样的问题。您提供的代码看起来不完整。请提供完整的代码。我添加了更多的代码,包括
Pojo.class
我忘了添加这些代码,并且为此添加了完整的
DB
。“如果我添加了新的可绘制文件,那么它会选择随机可绘制文件来显示解析xml的图标。”我看到两个地方你在FragmentBookmark中添加了新的书签图标项,一个在buildBookmarkArrayListfromDB方法中,另一个在onCreateView中,你指的是哪一个?添加到FragmentBookmark中的书签图标是第二个视图,它只有加号按钮。如果我正确地遵循了你的描述,那是因为您正在将图标作为数字资源ID存储在数据库中。添加(或删除,或更改)时在您的资源中添加一个drawable,然后重新生成,drawable很可能不会具有与以前相同的数字ID。最简单的修复方法可能是只存储图标的名称,而不是它们的数字ID。@MikeM。是的,这些图标以int形式保存在数据库中。您能提供关于这个问题的答案吗您所说的是最简单的修复方法吗?您的意思是将所有内容从int改为String吗?@Spritzig是的,但我认为如果用我的代码替换bookmark.setIcon,您的问题可以解决,但不确定我在
FragmentBookmark
bookmark.setIcon()
处确实有问题,返回此错误
setIcon(java.lang.String)in Bookmark无法应用于(android.graphics.drawable.drawable)
不要将drawable发送到Bookmark!仅当您希望将其显示到imageView时,请使用drawable。为此,您必须将可绘制图像的名称发布到setIcon。我不知道您必须发布到书签的图标是什么使用此书签。setIcon(“添加新书签图标”);
String iconName(int icon) {
    return getResources().getResourceEntryName(icon);
}

int iconRes(String icon) {
    return getResources().getIdentifier(icon, "drawable", mContext.getPackageName())
}
@Override
public void onDetach() {
    mContext = null;
    super.onDetach();
}
                int drawableResourceId = getResources().getIdentifier(xpp.getAttributeValue(null, "icon"), "drawable", mContext.getPackageName());
                bookmark.setIcon(xpp.getAttributeValue(null, "name"));
int iresourceid = getResources().getIdentifier(arrayList.get(position).getIcon(),"drawable",getPackageName());