Không thể đặt đôi SharedPreferences


90

Gặp lỗi, phương thức put double không được xác định đối với loại trình soạn thảo sharedPreferences này.

Mật mã:

@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
bạn có thể vui lòng chỉ rõ bạn đã gặp lỗi gì không?
câm

1
Nhìn vào dòng đầu tiên của câu hỏi
Robert

Tôi tự hỏi tại sao những người Android lại không triển khai putDouble trong API?
luky

Câu trả lời:


337

Những người đề xuất sử dụng putFloatgetFloat rất tiếc là rất sai lầm. Truyền một nhân đôi đến một phao có thể dẫn đến

  1. Mất độ chính xác
  2. Tràn ra
  3. Dòng chảy
  4. Mèo con chết

Những đề xuất một toStringparseString không sai, nhưng đó là một giải pháp không hiệu quả.

Cách chính xác để giải quyết vấn đề này là chuyển đôi thành 'bit dài thô' tương đương của nó và lưu trữ dài đó. Khi bạn đang đọc giá trị, hãy chuyển đổi lại thành gấp đôi.

Vì hai loại dữ liệu có cùng kích thước nên bạn không mất độ chính xác và sẽ không gây ra luồng {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)));
}

Ngoài ra, bạn có thể viết getter là:

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
Thật đẹp, sạch sẽ và thanh lịch.
Bogdan Alexandru

9
Phương thức putDouble sẽ vẫn tốt và nhất quán với các API khác trong hệ sinh thái android (như parceable và các gói). Một trường hợp điển hình của việc Google lại nhanh và cẩu thả.

2
tại sao lưu nó dưới dạng chuỗi lại không hiệu quả?
KKO

2
@KKO Kiểu dữ liệu dài là số nguyên bù hai của 64 bit. Vì vậy, nó chỉ mất 4 byte. Nhưng nếu bạn lưu trữ doublegiá trị đó dưới dạng một chuỗi thì bạn sẽ làm hỏng bộ lưu trữ của mình và biến nó thành đống đổ nát !!
semsamot

1
prefs.getLong (key, 0d) không chính xác, nó không phải là một kép. nên không có dấu d.
Ahmed Hegazy

28

Cách mở rộng Kotlin (đẹp hơn nhiều so với việc sử dụng các lớp utils kỳ lạ hoặc bất cứ thứ gì)

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
Thật tuyệt, chính xác là tôi đã nghĩ đến việc đặt cái này ở đây. Cảm ơn!
wzieba

16

Những gì tôi đã làm là lưu tùy chọn dưới dạng Chuỗi:

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

và sau đó để truy xuất đôi, chỉ cần sử dụng Double.parseDouble:

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

4
Bạn đang lãng phí bộ nhớ. Nó cũng chậm hơn nhiều so với doubleToRawLongBitsphương pháp đã được đề cập. Đây là cách làm sai , không phải vì nó sẽ không hiệu quả mà vì nó rất kém hiệu quả.
copolii

10
@copolii Về mặt học thuật, chắc chắn. Thực tế, trong ngành công nghiệp, nó thực sự không tạo ra sự khác biệt đủ lớn trong 99% trường hợp và trên thực tế, điều này có lẽ dễ đọc hơn và dễ nắm bắt hơn khi đưa một ai đó mới vào.
Dennis L

@DennisL #PracticalDev
Aba

9

Bạn luôn có thể triển khai SharedPreferences và kết thúc việc triển khai 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
    }
}

Đây là câu trả lời chính xác. Tôi ước tôi đã nhìn thấy điều này trước khi tôi bắt đầu nhập. Sẽ không hiệu quả hơn nếu chỉ trả về 'this' trong các phương thức của trình soạn thảo? Nó giúp bạn không phải gọi phương thức 'instanceof'. Hoặc bạn đã thử điều đó và nó gây ra vấn đề?
copolii

0

Kiểm tra ý chính này https://gist.github.com/john1jan/b8cb536ca51a0b2aa1da4e81566869c4

Tôi đã tạo một lớp Preference Utils sẽ xử lý tất cả các trường hợp.

Dễ sử dụng

Lưu trữ vào tùy chọn

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

Nhận từ sở thích

Double income = (Double) PrefUtils.getFromPrefs(getActivity(), PrefKeys.USER_INCOME, new Double(10));
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.