【问题标题】:How to convert from java.util.HashMap to android.content.ContentValues?如何从 java.util.HashMap 转换为 android.content.ContentValues?
【发布时间】:2014-09-25 11:49:36
【问题描述】:

有没有一种简单的方法可以将 java Map<String,Object> 转换为 android.content.ContentValues

android.content.ContentValues在android数据库编程中用于将database-row的数据保存为name-value-pairs。

背景:

我尝试将现有 android 应用的业务逻辑移植到 j2se-swing-app

我的目标是拥有 android 特定的代码 和 android 独立代码进入一个单独的库,可供 android 和 swing-gui 使用。

目前正在分析

  • 如果我必须使用大量冗余代码实现一组完整的独立存储库实现
  • 或者如果有可以在(j2se-swing- 和 android-)存储库实现中使用的通用代码。

Repository-Database-Code 依赖于使用android.content.ContentValues 的数据库-字段-名称-值对。

我认为我的 android 独立版本可以使用 HashMap<String,Object> insead 或 ContentValues 并创建代码以在两者之间进行转换。

依赖于 android 的版本如下所示

    // android dependant code in android-app
    class AndroidTimeSliceCategoryRepsitory implements ICategoryRepsitory {

        public long createTimeSliceCategory(final TimeSliceCategory category) {

            // get values from android independant layer
            Map<String, Object> columsToBeInserted = TimeSliceCategorySql.asHashMap(category);

// >>>> this is where i am stuck
            ContentValues androidColumsToBeInserted = DbUtils.asContentValues(columsToBeInserted);

            final long newID = AndroidTimeSliceCategoryRepsitory.DB.getWritableDatabase()
                    .insert(TimeSliceCategorySql.TIME_SLICE_CATEGORY_TABLE, null, androidColumsToBeInserted);
            category.setRowId((int) newID);
            return newID;
        }
    }

这是android独立部分:

    // android independant code in common jar
    class TimeSliceCategorySql {....

        /** converts {@link ....model.TimeSliceCategory}  to {@link java.util.HashMap} */
        public static Map<String, Object> asHashMap(final TimeSliceCategory category) {
            final Map<String, Object> values = new HashMap<String, Object>();
            values.put(TimeSliceCategorySql.COL_CATEGORY_NAME,
                    category.getCategoryName());
            values.put(TimeSliceCategorySql.COL_DESCRIPTION,
                    category.getDescription());

            // ... more values

            return values;
        }
    }

目前我被困在这里:

    public class AndroidDatabaseUtil {
        /** converts from android independeant {@link java.util.Map} to android dependent {@link android.content.ContentValues} */
        public static ContentValues toContentValues(Map<String, Object> src) {
            ContentValues result = new ContentValues();

            for (String name : src.keySet()) {

// this is not possible because ContentValues does not define put(String name, Object value)
                result.put(name, src.get(name));

// using this would loose ContentValues.getAsLong() throw exception.
// result.put(name, src.get(name).toString());

            }
            src.entrySet()
            return result;
        }
    }

【问题讨论】:

  • 你的 hashmap 中Object 的类型是什么?
  • 目前我有String、Integer、Long、Double、Boolean

标签: java android sqlite platform-independent database-independent


【解决方案1】:

How to marshal/unmarshal ContentValues to insert generic type into ContentProvider?

Location loc = mLocationClient.getLastLocation();
HashMap hm = new HashMap();
hm.put("LOCATIONS", loc);
Parcel myParcel = Parcel.obtain();    
myParcel.writeMap(hm);
myParcel.setDataPosition(0);

ContentValues values = ContentValues.CREATOR.createFromParcel(myParcel);

getContentResolver().insert(MyDumbUri, values);

然后

@Override
public Uri insert( final Uri uri, final ContentValues oldvalues ){
SQLiteDatabase db = GAELdatabase.getWritableDatabase();

Uri result = null;
Location loc = (Location)oldvalues.get("LOCATIONS");

ContentValues values = new ContentValues();

values.put("ALTITUDE", loc.getAltitude());//meters above sea level
values.put("LATITUDE", loc.getLatitude());
values.put("LONGITUDE", loc.getLongitude());

long rowID = db.insert( "MyTABLE_NAME", "", values);
db.close();
return result;
}

【讨论】:

  • 我希望在我决定实施“字符串表示”解决方案之前看到过这种方法 ;-)
【解决方案2】:

您可以在if 语句中使用instanceof 关键字对其进行过滤。

例子:

if( src.get(name) instanceof String){
  // convert to string
}

您也可以使用对象中的getClass 方法:

对象 ob = src.get(name);

  if(ob instanceof ob.getClass()){
   // convert to type
  }

【讨论】:

  • 这将解决我的问题。让我们看看是否有比为所涉及的每种类型都有一个if 更优雅的解决方案:String、Integer、Long、Double、Boolean
【解决方案3】:

看起来您在 Map 中输入的值是字符串。

因此您可以将 Map 的定义更改为

final Map<String, String> values = new HashMap<String, String>();

这将允许您将值放入 ContentValues 实例中:

result.put(name, src.get(name));

【讨论】:

  • 在我的示例中,我只使用了字符串。在我的代码项目中,我还有 Integer、Long、Double 和 Boolean
  • @k3b 在这种情况下,您可以使用 instanceof 检查值的类型并将其转换为 Integer、Long、Double 等,然后再将其放入 ContentValues 中,使用相关的put 方法。
  • 我决定将除了 blob-s 之外的所有内容都映射到字符串,因为无论如何我都必须实现向另一个方向 getInt(Map,key) 的转换。这就是为什么我接受了这个答案而不是@Kyle Emmanuel
  • 虽然我已经实现了这种务实的方法,但我只是将接受的答案从这个更改为 @JDOaktown 答案,它具有我正在寻找的通用解决方案
猜你喜欢
  • 1970-01-01
  • 2023-03-29
  • 2018-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-14
  • 2019-05-05
相关资源
最近更新 更多