SQLite数据库游标返回了错误的资源ID

时间:2019-05-14 16:40:34

标签: java android string sqlite resources

我正在尝试使用对SQLite数据库中可绘制和String资源的引用,以在片段中显示适当的资源。我有一个用于填充数据库的数据库帮助程序文件,一个用于创建游标(或只是将游标数据获取数组中的数据)的数据库实用程序文件以及一个片段文件。

    DatabaseHelper.java
    DatabaseHelper(Context context) {
            super(context, DB_NAME, null, DB_VERSION);
        }

        private void updateMyDatabase(SQLiteDatabase db, int oldVersion, int newVersion) {
            if (oldVersion == 1) {
                db.execSQL("CREATE TABLE FOOD (_id INTEGER PRIMARY KEY AUTOINCREMENT, "
                        + "NAME TEXT, "
                        + "IMAGE_RESOURCE_ID INTEGER, "
                        + "QUOTE INTEGER);");

                insertFood(db,"Alcohol", R.drawable.alcohol, R.string.symptom9);
}

private static void insertFood(SQLiteDatabase db, String name, int toxicity, int resourceId, int quote){
        ContentValues foodValues = new ContentValues();
        foodValues.put("NAME", name);
        foodValues.put("TOXICITY", toxicity);
        foodValues.put("IMAGE_RESOURCE_ID", resourceId);
        foodValues.put("QUOTE", quote);
        db.insert("FOOD", null, foodValues);
    }
}

在这里,R.drawable.alcohol = 2131099733

我正在使用Android Studio,当我将鼠标悬停在要添加到数据库的值上并使用其中一个值显示可绘制对象时,这是正确的可绘制对象,但是当我请求一个游标(或基于游标),游标所包含的值与数据库中存储的值完全不同,并且会产生资源未找到错误。

我尝试从helper方法返回一个数据数组,但是这也为drawables和string提供了不正确的整数引用,因此,我改为从helper方法返回了光标:

DatabaseUtilities.java
//get all of the database data for a particular food given that food's name
    public static Cursor getFoodById(Context context, long itemId){

        try {
            SQLiteOpenHelper DatabaseHelper = new DatabaseHelper(context);
            SQLiteDatabase db = DatabaseHelper.getReadableDatabase();
            return db.query(DatabaseHelper.FOOD,
                    new String[]{
                            DatabaseHelper.NAME, DatabaseHelper.IMAGE_RESOURCE_ID,
                            DatabaseHelper.QUOTE},
                    "_id = ?", new String[] {Long.toString(itemId)}, null, null, null
            );

        } catch (SQLiteException e) {
            //TODO Add toast - food not available
            return null;
        }
    }

最后,我尝试在此处显示值:

DetailFragment.java
 @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        Cursor items = DatabaseUtilities.getFoodById(getActivity(), itemId);
        if(items.moveToFirst()) {    
            //set appropriate img
            int img = items.getInt(1);
            ImageView photo = (ImageView) view.getRootView().findViewById(R.id.detail_photo);
            photo.setImageResource(img);

            int quote = items.getInt(2);
            TextView desc = (TextView) view.getRootView().findViewById(R.id.detail_text);
            String descText = getString(quote);
            desc.setText(descText);
        }
    }

这是最后一个文件中所有游标列的日志输出:

DetailFragment - cursor: Alcohol, 2131165269, 2131558463

“酒精”之后的值应为R.drawable.alcohol,2131099733,但光标改为返回2131165269。可绘制引用之后的字符串引用也是如此。另外,光标为每个插入的行返回不同的值,它们只是错误的值,我不知道它们来自何处,或者是否有办法将它们转换为正确的值。

程序中的所有内容都可以正常工作,只是数据库没有返回正确的资源引用。

1 个答案:

答案 0 :(得分:4)

不要在表中存储资源的整数ID。
每次更改资源并重新编译项目时,它们的值都不能保证相同。
而是将资源ID存储为字符串文字。
因此,将表的定义更改为:

CREATE TABLE FOOD (_id INTEGER PRIMARY KEY AUTOINCREMENT, "
                    + "NAME TEXT, "
                    + "IMAGE_RESOURCE_ID TEXT, "
                    + "QUOTE TEXT);

现在在IMAGE_RESOURCE_IDQUOTE列中存储字符串ID。
使用游标从表中检索这样的字符串ID时,可以通过以下方式获取其整数ID:

int drawableId = getResources().getIdentifier(drawableString, "drawable", getPackageName());
int stringId = getResources().getIdentifier(stringString, "string", getPackageName()); 

您可能需要向ContextgetResources()提供有效的getPackageName(),例如:

context.getResources().getIdentifier(drawableString, "drawable", context.getPackageName());

drawableStringstringString替换为您从表格中检索到的图像和字符串值。
如果您对表的定义进行了上述建议的更改,则必须从设备/仿真器中卸载该应用程序并重新运行,以便使用表的新定义删除并重新创建数据库。