Android中的领域保存(RealmList <realmstring>):值被保存到RealmString模型两次

时间:2017-01-20 08:04:53

标签: android realm

我需要Realm的一些帮助。 我有一个Realm对象:PokemonExperience RealmList<RealmString>

public class PokemonExperience extends RealmObject {

    public RealmList<RealmString> mainSkills;

    public RealmList<RealmString> getMainSkills() {
        return mainSkills;
    }

    public void setMainSkills(RealmList<RealmString> mainSkills) {
        this.mainSkills = mainSkills;
    }

我也有RealmString个对象,只有值字段。

有了这个,我有一个带有复选框的多选列表,这些复选框有onClickListeners。当我选中复选框时,我想将所有值保存到RealmString模型中,然后将RealmStrings保存到RealmList<RealmString>模型中的PokemonExperience

这是我的代码:

public View getView(final int position, View convertView, final ViewGroup parent) {
    final ViewHolder viewHolder;

    if (convertView == null) {
        //inflate Layout
        convertView = layoutInflater.inflate(R.layout.fragment_multiple_choice_adapter, parent, false);
        convertView.findViewById(R.id.fragment_multiple_choice_checkbox);
        viewHolder.checkBox.setOnClickListener(view -> {
            setCheckListener(viewHolder);
        });
    convertView.setTag(viewHolder);

    if (selectedPositions.size() == 0) {
        Method getter = getGetter(field);
        try {           
            List<Object> values = Arrays.asList(data.values().toArray());
            Object result = getter.invoke(object);
            List<Object> resultAsList = (List<Object>) result;
            for (int i = 0; i < values.size(); i++) {
                 if (resultAsList.contains(values.get(i))) {
                      selectedPositions.add(i);
                 }
                viewHolder.checkBox.setChecked(position == selectedPositions.get(i));
                viewHolder.position = position;
            }
        } catch (Exception e) {}
    }

    List<Object> keys = Arrays.asList(data.keySet().toArray());
    viewHolder.textView.setText(keys.get(position).toString());
    viewHolder.position = position;
    return convertView;
}

private Method getSetter(Field field) {
    return settersMap.get(field);
}

private Method getGetter(Field field) {
    return gettersMap.get(field);
}

private boolean isGetter(Method method) {
    return method.getName().startsWith("get") &&
            method.getParameterTypes().length == 0 &&
            !void.class.equals(method.getReturnType());
}

private boolean isSetter(Method method) {
    return method.getName().startsWith("set") &&
            method.getParameterTypes().length == 1;
}

private String croppedMethodName(boolean isGetter, boolean isSetter, Method method) {
    if (!isGetter && !isSetter) {
        return null;
    }

    if (isSetter &&
            method.getParameterTypes()[0].getName().equals(boolean.class.getCanonicalName())) {

        char[] c = new StringBuilder(method.getName()).substring(2).toCharArray();
        c[0] = Character.toLowerCase(c[0]);
        return new String(c);
    }

    char[] c = new StringBuilder(method.getName()).substring(3).toCharArray();
    c[0] = Character.toLowerCase(c[0]);
    return new String(c);
}

private void setCheckListener(ViewHolder viewHolder) {
    selectedPosition = viewHolder.position;
    Log.d(TAG, "getView: 111: " + selectedPosition);
    // We save our values here to Realm
    Realm realm = Realm.getDefaultInstance();
    realm.beginTransaction();
    Method setter = getSetter(field);
    try {
        List<Object> values = Arrays.asList(data.values().toArray());
        // taking a piece of string based on viewHolder.position to determine
        // what is the "object" we should be saving
        Object selectedObject = values.get(viewHolder.position);
        Log.d(TAG, "selectedObject: " + selectedObject);
        RealmString selectedRealmString = (RealmString) selectedObject;
        Log.d(TAG, "realmString: " + selectedRealmString);
        String selectedRealmStringValue = selectedRealmString.getValue();
        Log.d(TAG, "realmStringValue: " + selectedRealmStringValue);
        RealmResults<RealmString> realmStrings = realm.where(RealmString.class).findAll();
        if (!realmStrings.contains(selectedRealmStringValue)) {
            selectedRealmString = new RealmString();
            selectedRealmString.setValue(selectedRealmStringValue);
            realm.copyToRealm(selectedRealmString);
        }
        Log.d(TAG, "saved realmString: " + selectedRealmString);
        Log.d(TAG, "saved realmStringValue: " + selectedRealmStringValue);
        Log.d(TAG, "RealmResult size: " + realmStrings.size());
        Log.d(TAG, "RealmResult: " + realmStrings.toArray().toString());
        Method getter = getGetter(field);
        Log.d(TAG, "getter name: " + getter.getName());
        Object existingObjects = getter.invoke(object);
        Log.d(TAG, "existingObjects: " + existingObjects);
        RealmList<RealmString> existingValues;
        existingValues = (RealmList<RealmString>) existingObjects;
        Log.d(TAG, "existingValues1: " + existingValues);
        if (!existingValues.contains(selectedRealmString)) {
            Log.d(TAG, "existingValues2: " + existingValues);
            existingValues.add(selectedRealmString);
        }
        Log.d(TAG, "existingValues3: " + existingValues);
        setter.invoke(object, existingValues);
        Log.d(TAG, "setCheckListener: setter is: " + setter.getName());
    } catch (Exception e) {
        e.printStackTrace();
    }
    realm.commitTransaction();
    realm.close();
    viewHolder.checkBox.setChecked(true);
    notifyDataSetChanged();
}

我的问题:

  1. 为什么我的值会保存到My RealmString模型两次?每当我点击任何复选框时,该复选框的字符串值都会保存两次。

  2. 为什么将值保存到RealmString模型,即使有检查。

    if(!realmStrings.contains(selectedRealmStringValue)){    // ... }

  3. 这应该确保只保存新值。

    1. RealmList<RealmString>未保存到我的PokemonExperience的mainSkills字段中。
    2. 感谢任何帮助。非常感谢!

3 个答案:

答案 0 :(得分:0)

我认为你应该这样检查

if (!realmStrings.contains(selectedRealmString)) {
   ...    
}

因为selectedRealmStringRealmString类的实例,selectedRealmStringValueString类的实例而您的RealmResults包含RealmString

答案 1 :(得分:0)

selectedRealmString是一个非托管对象,您将两次插入您的领域(realm.copyToRealm(selectedRealmString)existingValues.add(selectedRealmString))。您可以执行selectedRealmStringManaged = realm.copyToRealm(selectedRealmString),然后执行existingValues.add(selectedRealmStringManaged)

答案 2 :(得分:0)

if (!realmStrings.contains(selectedRealmString)) {
   ...    
}

上述方法不起作用,因为我们真正需要做的是比较对象的价值。 这有效:

        ArrayList<String> existingValuesArrayList = new ArrayList<>();
        for (int i = 0; i < existingValues.size(); i++) {
            existingValuesArrayList.add(existingValues.get(i).getValue());
        }
        if (!existingValuesArrayList.contains(selectedRealmString.getValue())) {
        //...
        }