Adding a new drawable it is changing the icons of the parsed xml

血红的双手。 提交于 2019-12-06 12:03:50

You're calling String.valueOf(bookmark.getIcon()) to store the icon in your database. As the icon is an int representing the resource, this stores the resource id as a string. The issue now is that resource ids are not stable and might change any time you create a new APK. Therefore it works while you don't update the app, but starts failing after.

Instead you should store the name of the res and keep these stable. You're already using the name with your XML data, so I'd assume that's your goal anyhow.

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));

Now you only need to implement the mapping from name to id.

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

int iconRes(String icon) {
    return getResources().getIdentifier(icon, "drawable", mContext.getPackageName())
}

Also you need to unset mContext on detach or don't store it and use getContext() or requireContext() instead. Of course you'd have to check for null if you use it in some background operation.

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

Try to do myAdapter.notifyDataSetChanged(); after your arrayList adding work in the FragmentBookmark:

 Bookmark bookmark = new Bookmark();
 bookmark.setViewType(1);
 bookmark.setIcon(R.drawable.add_new_bookmark_icon);
 arrayList.add(bookmark);
 myAdapter.notifyDataSetChanged();

BTW:The xml parse work and database operations should generally be handled asynchronously.

Updated:Change your the type icon field in Bookmark from int to String,and modify some code in loadBookMarksFromXML,from

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

to

bookmark.setIcon(xpp.getAttributeValue(null, "icon"));

change some code in onBindViewHolder in class MyAdapter,from:

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

to

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

You can easily fix other errors caused by changing the icon field's type and run again,let me know the result.Thx.

For storing image to sqlite or any other local database you must store name of variable(i do this when use local database maybe there is better way)

So when you want to store drawable

Use this code

bookmark.setIcon("add_new_bookmark_icon");//don't forget to change icon to String in bookmark

Instead of this

bookmark.setIcon(R.drawable.add_new_bookmark_icon);//you use this in onViewCreate and buildBookmarkArrayListfromDB

Now when you want show drawable from database use this code

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

Note

You must change all place use setIcon or getIcon and all code you use icon as int like in getAllBookmarks -> csr.getInt(csr.getColumnIndex(COL_ICON) and others

I do this several years ago and i don't check it still works. try it and tell me what happens

As the Resource id will be kept on changing at every install or apk generation, it is wise to store the name of the icon resource and fetch it during display time. To do this you can store a string value of the name of the icon(you can also use the same name as of the bookmark, but make sure the drawable of the same name).
Change icon field to String in Database (Bookmark.db) & Pojo.
Remove this line in your Fragment of RecyclerView

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

Change next line

                bookmark.setIcon(xpp.getAttributeValue(null, "name"));

In onBindViewHolder in MyAdapter class get icon resource using

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

Maybe you should move icons from res folder to assets, then load it with 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
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!