Tidak dapat menempatkan SharedPreferences ganda

90

Mendapatkan error, metode put double tidak terdefinisi untuk jenis editor sharedPreferences ini. Eclipse diberikan satu perbaikan cepat tambahkan cast ke editor, tetapi ketika saya melakukan itu masih diberikan kesalahan, Why cant i put double.

Kode:

@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();
}
Robert
sumber
2
bisakah Anda menjelaskan kesalahan apa yang Anda dapatkan?
dumbfingers
1
Lihatlah baris pertama pertanyaan
Robert
saya bertanya-tanya bagaimana bisa orang-orang android tidak menerapkan putDouble di API?
luky

Jawaban:

337

Mereka yang menyarankan untuk menggunakan putFloat dan getFloat sayangnya sangat salah. Mentransmisikan dobel ke float bisa berakibat

  1. Kehilangan presisi
  2. Meluap
  3. Mengalir
  4. Anak kucing mati

Mereka yang menyarankan toString dan parseString tidak salah, tetapi ini adalah solusi yang tidak efisien.

Cara yang benar untuk mengatasinya adalah dengan mengubah double menjadi padanan 'raw long bits' dan menyimpannya sepanjang itu. Saat Anda membaca nilainya, ubah kembali menjadi dua kali lipat.

Karena kedua tipe data memiliki ukuran yang sama Anda tidak kehilangan presisi dan Anda tidak akan menyebabkan aliran {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)));
}

Cara lainnya, Anda dapat menulis getter sebagai:

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

return Double.longBitsToDouble(prefs.getLong(key, 0));
}
copolii
sumber
9
Sangat cantik, bersih dan elegan.
Bogdan Alexandru
9
Metode putDouble akan tetap bagus dan konsisten meskipun dengan API lain dalam ekosistem android (seperti parceable dan bundel). Kasus khas Google yang cepat dan ceroboh lagi.
2
mengapa menyimpannya sebagai string tidak efisien?
KKO
2
@KKO Tipe data panjang adalah bilangan bulat komplemen dua 64-bit. Jadi hanya dibutuhkan 4-byte. Tetapi jika Anda menyimpan doublenilai itu sebagai string maka Anda merusak penyimpanan Anda dan menjadikannya reruntuhan !!
semsamot
1
prefs.getLong (key, 0d) salah itu bukan double. harus tanpa d.
Ahmed Hegazy
28

Cara ekstensi Kotlin (jauh lebih cantik daripada menggunakan kelas utils yang aneh atau apa pun)

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)))
Dima Rostopira
sumber
2
Bagus, saya benar-benar berpikir untuk meletakkan ini di sini. Terima kasih!
wzieba
16

Apa yang saya lakukan adalah menyimpan preferensi sebagai String:

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

dan kemudian untuk mengambil ganda, cukup gunakan Double.parseDouble:

Double.parseDouble(getSharedPreferences("PREFERENCE", MODE_PRIVATE).getString("double", "0.01"));
John
sumber
4
Anda membuang-buang penyimpanan. Ini juga jauh lebih lambat daripada doubleToRawLongBitsmetode yang telah disebutkan. Ini cara yang salah , bukan karena tidak akan berhasil, tetapi karena sangat tidak efisien.
copolii
10
@copolii Secara akademis, tentu. Praktis, dalam industri, hal itu tidak membuat perbedaan yang cukup penting dalam 99% kasus dan pada kenyataannya ini mungkin lebih mudah dibaca dan lebih mudah dipahami ketika membawa seseorang yang baru.
Dennis L
@DennisL #PracticalDev
Aba
9

Anda selalu dapat mengimplementasikan SharedPreferences dan menggabungkan implementasi 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
    }
}
bprice
sumber
Ini jawaban yang benar. Saya berharap saya telah melihat ini sebelum saya mulai mengetik. Bukankah lebih efisien jika mengembalikan 'ini' dalam metode editor? Ini menyelamatkan Anda dari memanggil metode 'instanceof'. Atau apakah Anda sudah mencobanya dan itu menyebabkan masalah?
copolii
0

Periksa inti ini https://gist.github.com/john1jan/b8cb536ca51a0b2aa1da4e81566869c4

Saya telah membuat kelas Preference Utils yang akan menangani semua kasus.

Mudah Digunakan

Menyimpan ke dalam preferensi

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

Mendapatkan dari preferensi

Double income = (Double) PrefUtils.getFromPrefs(getActivity(), PrefKeys.USER_INCOME, new Double(10));
John
sumber