ไม่สามารถใส่ SharedPreferences สองเท่า


90

ได้รับข้อผิดพลาดเมธอด put double ไม่ได้กำหนดไว้สำหรับเอดิเตอร์ sharedPreferences ประเภทนี้ Eclipse ได้รับการแก้ไขด่วนหนึ่งรายการเพิ่ม cast ให้กับเอดิเตอร์ แต่เมื่อฉันทำเช่นนั้นข้อผิดพลาดยังคงได้รับเหตุใดฉันจึงใส่ double ไม่ได้

รหัส:

@Override
protected void onPause() {
    // TODO Auto-generated method stub
    super.onPause();

    if (TextUtils.isEmpty(editBl.getText().toString())) {
        numberOfBl = 0;
    } else {
        numberOfBl = Integer.parseInt(editBl.getText().toString();

    }
    if (TextUtils.isEmpty(editSt.getText().toString())) {
        tonOfSt = 0;
    } else {
        tonOfSt = Double.parseDouble(editSt.getText().toString());

    }

    SharedPreferences prefs = getSharedPreferences(
            "SavedTotals", Context.MODE_PRIVATE);

    SharedPreferences.Editor editor = prefs.edit();

    editor.putInt("savedBl", numberOfBl);
    editor.putDouble("savedSt", tonOfSt);


    editor.commit();
}

2
คุณช่วยระบุข้อผิดพลาดที่คุณพบได้ไหม
dumbfingers

1
ดูบรรทัดแรกของคำถาม
โรเบิร์ต

ฉันสงสัยว่าทำไมพวก Android ถึงไม่ใช้ putDouble ใน API
luky

คำตอบ:


339

ผู้ที่แนะนำให้ใช้putFloatและgetFloatนั้นผิดพลาดอย่างมาก การโยนสองครั้งเพื่อลอยสามารถส่งผลให้

  1. สูญเสียความแม่นยำ
  2. ล้น
  3. Underflow
  4. ลูกแมวตาย

ผู้ที่แนะนำtoStringและparseStringนั้นไม่ผิด แต่เป็นวิธีแก้ปัญหาที่ไม่มีประสิทธิภาพ

วิธีที่ถูกต้องในการจัดการกับสิ่งนี้คือการแปลง double ให้เทียบเท่า 'raw long bits' และเก็บไว้นานนั้น เมื่อคุณอ่านค่าให้แปลงกลับเป็นสองเท่า

เนื่องจากข้อมูลทั้งสองประเภทมีขนาดเท่ากันคุณจะไม่สูญเสียความแม่นยำและคุณจะไม่ทำให้เกิดโฟลว์ {over, under}

Editor putDouble(final Editor edit, final String key, final double value) {
   return edit.putLong(key, Double.doubleToRawLongBits(value));
}

double getDouble(final SharedPreferences prefs, final String key, final double defaultValue) {
return Double.longBitsToDouble(prefs.getLong(key, Double.doubleToLongBits(defaultValue)));
}

หรือคุณสามารถเขียน getter เป็น:

double getDouble(final SharedPreferences prefs, final String key, final double defaultValue) {
if ( !prefs.contains(key))
        return defaultValue;

return Double.longBitsToDouble(prefs.getLong(key, 0));
}

9
สวยสะอาดและสง่างาม
Bogdan Alexandru

9
วิธีการ putDouble จะยังคงดีและสอดคล้องกันแม้ว่าจะมี API อื่น ๆ ในระบบนิเวศของ Android (เช่นสามารถแยกวิเคราะห์ได้และบันเดิล) กรณีทั่วไปของ Google ที่รวดเร็วและเลอะเทอะอีกครั้ง

2
ทำไมการบันทึกเป็นสตริงจึงไม่มีประสิทธิภาพ
KKO

2
@KKO ชนิดข้อมูลแบบยาวคือจำนวนเต็มเสริมของสอง 64 บิต ดังนั้นจึงใช้เวลาเพียง 4 ไบต์ แต่ถ้าคุณเก็บdoubleค่านั้นเป็นสตริงคุณจะทำลายที่เก็บของคุณและทำให้มันเป็นซาก !!
semsamot

1
prefs.getLong (คีย์ 0d) ไม่ถูกต้องไม่ใช่สองเท่า ควรจะไม่มี d.
Ahmed Hegazy

28

วิธีขยาย Kotlin (สวยกว่าการใช้คลาสเครื่องมือแปลก ๆ หรืออะไรก็ตาม)

fun SharedPreferences.Editor.putDouble(key: String, double: Double) =
    putLong(key, java.lang.Double.doubleToRawLongBits(double))

fun SharedPreferences.getDouble(key: String, default: Double) =
    java.lang.Double.longBitsToDouble(getLong(key, java.lang.Double.doubleToRawLongBits(default)))

2
เยี่ยมมากฉันคิดว่าจะวางตรงนี้ ขอบคุณ!
wzieba

16

สิ่งที่ฉันทำคือบันทึกการตั้งค่าเป็นสตริง:

getSharedPreferences("PREFERENCE", MODE_PRIVATE).edit().putString("double", "0.01").commit();

จากนั้นเพื่อดึงข้อมูลคู่เพียงใช้ Double.parseDouble:

Double.parseDouble(getSharedPreferences("PREFERENCE", MODE_PRIVATE).getString("double", "0.01"));

4
คุณกำลังเสียพื้นที่เก็บข้อมูล นอกจากนี้ยังช้ากว่าdoubleToRawLongBitsวิธีการที่กล่าวมาแล้ว นี่เป็นวิธีที่ผิดไม่ใช่เพราะมันใช้ไม่ได้ แต่เป็นเพราะมันไม่มีประสิทธิภาพมาก
copolii

10
@copolii วิชาการนั่นเอง ในทางปฏิบัติในทางอุตสาหกรรมมันไม่ได้สร้างความแตกต่างให้กับเรื่องใน 99% ของกรณีมากพอและในความเป็นจริงสิ่งนี้อาจอ่านได้ง่ายกว่าและเข้าใจได้ง่ายกว่าเมื่อนำคนใหม่เข้ามา
Dennis L

@DennisL #PracticalDev
Aba

9

คุณสามารถใช้ SharedPreferences และปิดการใช้งาน Android ได้ตลอดเวลา

package com.company.sharedpreferences;

import android.content.Context;
import android.content.SharedPreferences;


import java.util.Map;
import java.util.Set;

public class EnhancedSharedPreferences implements SharedPreferences {

    public static class NameSpaces {
        public static String MY_FUN_NAMESPACE = "MyFunNameSpacePrefs";
    }

    public static EnhancedSharedPreferences getPreferences(String prefsName) {
        return new EnhancedSharedPreferences(SomeSingleton.getInstance().getApplicationContext().getSharedPreferences(prefsName, Context.MODE_PRIVATE));
    }

    private SharedPreferences _sharedPreferences;

    public EnhancedSharedPreferences(SharedPreferences sharedPreferences) {
        _sharedPreferences = sharedPreferences;
    }

    //region Overrides

    @Override
    public Map<String, ?> getAll() {
        return _sharedPreferences.getAll();
    }

    @Override
    public String getString(String key, String defValue) {
        return _sharedPreferences.getString(key, defValue);
    }

    @Override
    public Set<String> getStringSet(String key, Set<String> defValues) {
        return _sharedPreferences.getStringSet(key, defValues);
    }

    @Override
    public int getInt(String key, int defValue) {
        return _sharedPreferences.getInt(key, defValue);
    }

    @Override
    public long getLong(String key, long defValue) {
        return _sharedPreferences.getLong(key, defValue);
    }

    @Override
    public float getFloat(String key, float defValue) {
        return _sharedPreferences.getFloat(key, defValue);
    }

    @Override
    public boolean getBoolean(String key, boolean defValue) {
        return _sharedPreferences.getBoolean(key, defValue);
    }

    @Override
    public boolean contains(String key) {
        return _sharedPreferences.contains(key);
    }

    @Override
    public Editor edit() {
        return new Editor(_sharedPreferences.edit());
    }

    @Override
    public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
        _sharedPreferences.registerOnSharedPreferenceChangeListener(listener);
    }

    @Override
    public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
        _sharedPreferences.unregisterOnSharedPreferenceChangeListener(listener);
    }

    //endregion

    //region Extension

    public Double getDouble(String key, Double defValue) {
        return Double.longBitsToDouble(_sharedPreferences.getLong(key, Double.doubleToRawLongBits(defValue)));
    }

    //endregion

    public static class Editor implements SharedPreferences.Editor {

        private SharedPreferences.Editor _editor;

        public Editor(SharedPreferences.Editor editor) {
            _editor = editor;
        }

        private Editor ReturnEditor(SharedPreferences.Editor editor) {
            if(editor instanceof Editor)
                return (Editor)editor;
            return new Editor(editor);
        }

        //region Overrides

        @Override
        public Editor putString(String key, String value) {
            return ReturnEditor(_editor.putString(key, value));
        }

        @Override
        public Editor putStringSet(String key, Set<String> values) {
            return ReturnEditor(_editor.putStringSet(key, values));
        }

        @Override
        public Editor putInt(String key, int value) {
            return ReturnEditor(_editor.putInt(key, value));
        }

        @Override
        public Editor putLong(String key, long value) {
            return ReturnEditor(_editor.putLong(key, value));
        }

        @Override
        public Editor putFloat(String key, float value) {
            return ReturnEditor(_editor.putFloat(key, value));
        }

        @Override
        public Editor putBoolean(String key, boolean value) {
            return ReturnEditor(_editor.putBoolean(key, value));
        }

        @Override
        public Editor remove(String key) {
            return ReturnEditor(_editor.remove(key));
        }

        @Override
        public Editor clear() {
            return ReturnEditor(_editor.clear());
        }

        @Override
        public boolean commit() {
            return _editor.commit();
        }

        @Override
        public void apply() {
            _editor.apply();
        }

        //endregion

        //region Extensions

        public Editor putDouble(String key, double value) {
            return new Editor(_editor.putLong(key, Double.doubleToRawLongBits(value)));
        }

        //endregion
    }
}

นี่คือคำตอบที่ถูกต้อง ฉันหวังว่าฉันจะได้เห็นสิ่งนี้ก่อนที่จะเริ่มพิมพ์ การคืนค่า 'this' ในวิธีการแก้ไขจะมีประสิทธิภาพมากกว่าหรือไม่? ช่วยให้คุณไม่ต้องเรียกใช้เมธอด 'instanceof' หรือคุณลองแล้วมันทำให้เกิดปัญหา?
copolii

0

ตรวจสอบส่วนสำคัญนี้https://gist.github.com/john1jan/b8cb536ca51a0b2aa1da4e81566869c4

ฉันได้สร้างคลาส Preference Utils ที่จะจัดการกับทุกกรณี

ใช้งานง่าย

จัดเก็บไว้ในความชอบ

PrefUtils.saveToPrefs(getActivity(), PrefKeys.USER_INCOME, income);

ได้รับจากความชอบ

Double income = (Double) PrefUtils.getFromPrefs(getActivity(), PrefKeys.USER_INCOME, new Double(10));
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.