จัดเก็บและเรียกใช้คลาสอ็อบเจ็กต์ในการกำหนดค่าตามความชอบที่ใช้ร่วมกัน


111

ใน Android เราสามารถจัดเก็บออบเจ็กต์ของคลาสในการตั้งค่าร่วมกันและเรียกคืนวัตถุในภายหลังได้หรือไม่?

ถ้าเป็นไปได้จะทำอย่างไร? ถ้าเป็นไปไม่ได้มีความเป็นไปได้อื่น ๆ ในการทำอย่างไร?

ฉันรู้ว่าการทำให้เป็นอนุกรมเป็นทางเลือกหนึ่ง แต่ฉันกำลังมองหาความเป็นไปได้โดยใช้ความชอบร่วมกัน


ฉันเพิ่มคลังผู้ช่วยในกรณีที่มีคนต้องการ: github.com/ionull/objectify
Tsung Goh

นี่คือตัวอย่างthegeekyland.blogspot.com/2015/11/…
Arlind

นี่คือคำตอบสำหรับคำถามที่คล้ายกัน
tpk


คุณสามารถใช้ไลบรารีนี้ซึ่งมีคุณสมบัติมากมายที่สร้างขึ้น github.com/moinkhan-in/PreferenceSpider
Moinkhan

คำตอบ:


15

เป็นไปไม่ได้.

คุณสามารถจัดเก็บเฉพาะค่าง่ายๆใน SharedPrefences SharePreferences.Editor

คุณต้องประหยัดอะไรเป็นพิเศษเกี่ยวกับชั้นเรียน


1
ขอบคุณฉันต้องการจัดเก็บสมาชิกข้อมูลบางส่วนของคลาสและฉันไม่ต้องการจัดเก็บค่าข้อมูลแต่ละค่าโดยใช้การตั้งค่าที่ใช้ร่วมกันฉันต้องการจัดเก็บเป็นวัตถุหากไม่ได้ใช้ความชอบร่วมกันตัวเลือกอื่น ๆ ของฉันคืออะไร?
androidGuy

5
ต่ออนุกรมและจัดเก็บในฐานข้อมูล (SQLite) / ในไฟล์แบบแบน
Blundell

5
คำตอบยังไม่สมบูรณ์ วิธีแก้ปัญหาที่เป็นไปได้คือการเปลี่ยน pojo เป็น ByteArrayOutPutStream และบันทึกเป็น String ใน SharedPreferences
rallat

27
ตัวเลือกอื่นจะถูกบันทึกเป็น json แล้วแมปกลับ ด้วย GSON หรือ jackSON นั้นง่ายมาก
rallat

2
ขอฉันเอาไทม์แมชชีนกลับไปปี 2011 แล้วคิดออก
Blundell

324

ใช่เราสามารถทำได้โดยใช้Gson

ดาวน์โหลด Working code จากGitHub

SharedPreferences mPrefs = getPreferences(MODE_PRIVATE);

สำหรับบันทึก

Editor prefsEditor = mPrefs.edit();
Gson gson = new Gson();
String json = gson.toJson(myObject); // myObject - instance of MyObject
prefsEditor.putString("MyObject", json);
prefsEditor.commit();

เพื่อรับ

Gson gson = new Gson();
String json = mPrefs.getString("MyObject", "");
MyObject obj = gson.fromJson(json, MyObject.class);

Update1

รุ่นล่าสุดของ GSON สามารถดาวน์โหลดได้จากgithub.com/google/gson

Update2

หากคุณใช้ Gradle / Android Studio เพียงแค่ใส่สิ่งต่อไปนี้ในbuild.gradleส่วนการอ้างอิง -

implementation 'com.google.code.gson:gson:2.6.2'

ไม่ทำงานในกรณีของฉัน แม้ว่าหลังจากใส่ jar ใน libs และการตั้งค่าใน build path แล้วคลาส Gson ก็ไม่ได้รับการแก้ไข
Shirish Herwade

โปรเจคคลีนแล้วลอง @ShirishHerwade
Parag Chauhan

@parag ที่ยังใช้งานไม่ได้ คุณช่วยบอกขั้นตอนในการใช้ขวดนั้นเพื่อลบข้อผิดพลาดข้างต้น เนื่องจากฉันเพิ่ม jar นั้นในโฟลเดอร์ libs สำเร็จแล้วใน "java build path" ก็พยายามเพิ่ม json ที่จัดเก็บภายนอกบนเดสก์ท็อปของฉันด้วย
Shirish Herwade

7
คำตอบนี้จะดียิ่งขึ้นหากมีการกล่าวถึงข้อ จำกัด ด้วย วัตถุชนิดใดที่เราสามารถจัดเก็บและเรียกคืนในลักษณะนี้ไม่ได้? เห็นได้ชัดว่าจะใช้ไม่ได้กับทุกชั้นเรียน
wvdz

3
String json = gson.toJson("MyObject");ควรเป็นวัตถุที่ไม่ใช่ String
Ahmed Hegazy

44

เราสามารถใช้ Outputstream เพื่อส่งออก Object ของเราไปยังหน่วยความจำภายใน และแปลงเป็นสตริงจากนั้นบันทึกตามความต้องการ ตัวอย่างเช่น:

    mPrefs = getPreferences(MODE_PRIVATE);
    SharedPreferences.Editor ed = mPrefs.edit();
    ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();

    ObjectOutputStream objectOutput;
    try {
        objectOutput = new ObjectOutputStream(arrayOutputStream);
        objectOutput.writeObject(object);
        byte[] data = arrayOutputStream.toByteArray();
        objectOutput.close();
        arrayOutputStream.close();

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        Base64OutputStream b64 = new Base64OutputStream(out, Base64.DEFAULT);
        b64.write(data);
        b64.close();
        out.close();

        ed.putString(key, new String(out.toByteArray()));

        ed.commit();
    } catch (IOException e) {
        e.printStackTrace();
    }

เมื่อเราต้องการแยก Object จาก Preference ใช้รหัสดังต่อไปนี้

    byte[] bytes = mPrefs.getString(indexName, "{}").getBytes();
    if (bytes.length == 0) {
        return null;
    }
    ByteArrayInputStream byteArray = new ByteArrayInputStream(bytes);
    Base64InputStream base64InputStream = new Base64InputStream(byteArray, Base64.DEFAULT);
    ObjectInputStream in;
    in = new ObjectInputStream(base64InputStream);
    MyObject myObject = (MyObject) in.readObject();

สวัสดีฉันรู้ว่าสิ่งนี้ถูกโพสต์เมื่อไม่นานมานี้ แต่คุณแน่ใจหรือไม่ว่ารหัสที่คุณมีสำหรับการแยกวัตถุที่จัดเก็บนั้นถูกต้อง ฉันได้รับข้อผิดพลาดหลายรายการใน 2 บรรทัดสุดท้ายซึ่งเกี่ยวกับวิธีการกำหนดคอนสตรัคเตอร์ที่ชัดเจนแทนที่จะมี "ObjectInputStream ใหม่ (byteArray)" ขอบคุณสำหรับความช่วยเหลือ!
Wakka Wakka Wakka

สวัสดีจู่ๆฉันก็ได้รับ EOFException ใน = ObjectInputStream ใหม่ (base64InputStream); ฉันกำลังเขียนมันลงในการตั้งค่าที่ใช้ร่วมกันในลักษณะเดียวกับที่คุณทำ คุณคิดว่าอะไรผิด?
เรียนเก้

คุณมีข้อยกเว้นเมื่อคุณเขียน Object to pref หรือไม่? จาก SDK: โยน EOFException เมื่อโปรแกรมพบจุดสิ้นสุดของไฟล์หรือสตรีมระหว่างการดำเนินการป้อนข้อมูล
Kislingk

ความรุ่งโรจน์นี่เป็นทางออกที่ดีที่สุดที่ฉันเจอสำหรับปัญหานี้จนถึงตอนนี้ ไม่มีการอ้างอิง อย่างไรก็ตามควรสังเกตว่าเพื่อให้สามารถใช้ ObjectOutput / InputStream สำหรับอ็อบเจ็กต์ได้อ็อบเจ็กต์ดังกล่าวและอ็อบเจ็กต์ที่กำหนดเองทั้งหมดภายในนั้นจะต้องใช้อินเทอร์เฟซ Serializable
user1112789

8

ฉันมีปัญหาเดียวกันนี่คือวิธีแก้ปัญหาของฉัน:

ฉันมีคลาส MyClass และ ArrayList <MyClass> ที่ฉันต้องการบันทึกลงใน Shared Preferences ในตอนแรกฉันได้เพิ่มวิธีการใน MyClass ที่แปลงเป็นวัตถุ JSON:

public JSONObject getJSONObject() {
    JSONObject obj = new JSONObject();
    try {
        obj.put("id", this.id);
        obj.put("name", this.name);
    } catch (JSONException e) {
        e.printStackTrace();
    }
    return obj;
}

ต่อไปนี้เป็นวิธีการบันทึกวัตถุ "ArrayList <MyClass> items":

SharedPreferences mPrefs = context.getSharedPreferences("some_name", 0);
    SharedPreferences.Editor editor = mPrefs.edit();

    Set<String> set= new HashSet<String>();
    for (int i = 0; i < items.size(); i++) {
        set.add(items.get(i).getJSONObject().toString());
    }

    editor.putStringSet("some_name", set);
    editor.commit();

และนี่คือวิธีการดึงวัตถุ:

public static ArrayList<MyClass> loadFromStorage() {
    SharedPreferences mPrefs = context.getSharedPreferences("some_name", 0);

    ArrayList<MyClass> items = new ArrayList<MyClass>();

    Set<String> set = mPrefs.getStringSet("some_name", null);
    if (set != null) {
        for (String s : set) {
            try {
                JSONObject jsonObject = new JSONObject(s);
                Long id = jsonObject.getLong("id"));
                String name = jsonObject.getString("name");
                MyClass myclass = new MyClass(id, name);

                items.add(myclass);

            } catch (JSONException e) {
                e.printStackTrace();
         }
    }
    return items;
}

โปรดทราบว่า StringSet ใน Shared Preferences พร้อมใช้งานตั้งแต่ API 11


แก้ไขปัญหาของฉัน ฉันต้องการเพิ่มบางสิ่งบางอย่าง สำหรับการใช้งานครั้งแรกเราต้องตรวจสอบว่าเซตนั้นเป็นโมฆะหรือไม่ if (set! = null) {สำหรับ (String s: set) {.. }}
xevser

@xevser ฉันได้เพิ่มการตรวจสอบค่าว่างตามที่แนะนำแล้ว ขอบคุณ
Micer

6

การใช้ Gson Library:

dependencies {
compile 'com.google.code.gson:gson:2.8.2'
}

เก็บ:

Gson gson = new Gson();
//Your json response object value store in json object
JSONObject jsonObject = response.getJSONObject();
//Convert json object to string
String json = gson.toJson(jsonObject);
//Store in the sharedpreference
getPrefs().setUserJson(json);

ดึงข้อมูล:

String json = getPrefs().getUserJson();

พัสดุไม่ใช่กลไกการทำให้เป็นลำดับตามวัตถุประสงค์ทั่วไป คลาสนี้ (และ Parcelable API ที่สอดคล้องกันสำหรับการวางวัตถุโดยพลการลงใน Parcel) ได้รับการออกแบบให้เป็นการขนส่ง IPC ที่มีประสิทธิภาพสูง ด้วยเหตุนี้จึงไม่เหมาะสมที่จะวางข้อมูลพัสดุลงในที่จัดเก็บถาวร: การเปลี่ยนแปลงในการนำข้อมูลใด ๆ ในพัสดุไปใช้งานอาจทำให้ข้อมูลเก่าไม่สามารถอ่านได้
Marcos Vasconcelos

1

คุณสามารถทำได้โดยใช้ PowerPreferenceห้องสมุดใน 3 ขั้นตอนง่ายๆ!

https://github.com/AliAsadi/PowerPreference

1. สร้างวัตถุ

Object obj = new Object();

2. เขียนถึงความชอบที่ใช้ร่วมกัน

PowerPreference.getDefaultFile().put("object",obj);

3. รับวัตถุ

Object obj = PowerPreference.getDefaultFile()
                            .getObject("object", Object.class);

0

การใช้วัตถุนี้ -> TinyDB - Android-Shared-Preferences-Turboนั้นง่ายมาก คุณสามารถบันทึกอ็อบเจ็กต์ที่ใช้บ่อยที่สุดได้เช่นอาร์เรย์จำนวนเต็มรายการสตริงเป็นต้น


เจ๋ง แต่ฉันคิดว่ามันใช้ได้กับประเภท primitie (String, double, int, ฯลฯ ) ไม่ใช่สำหรับวัตถุที่กำหนดเอง (POJOS)
CommonSenseCode

ตอนนี้ใช้งานได้กับวัตถุที่กำหนดเองตรวจสอบ ReadMe ได้รับการอัปเดตแล้ว
kc ochibili

0

คุณสามารถใช้ได้ Complex Preferences Android - โดยไลบรารีFelipe Silvestreเพื่อจัดเก็บวัตถุที่คุณกำหนดเอง โดยทั่วไปจะใช้กลไก GSON ในการจัดเก็บวัตถุ

ในการบันทึกวัตถุลงใน prefs:

User user = new User();
user.setName("Felipe");
user.setAge(22); 
user.setActive(true); 

ComplexPreferences complexPreferences = ComplexPreferences.getComplexPreferences(
     this, "mypref", MODE_PRIVATE);
complexPreferences.putObject("user", user);
complexPreferences.commit();

และในการเรียกคืน:

ComplexPreferences complexPreferences = ComplexPreferences.getComplexPreferences(this, "mypref", MODE_PRIVATE);
User user = complexPreferences.getObject("user", User.class);

พัสดุไม่ใช่กลไกการทำให้เป็นลำดับตามวัตถุประสงค์ทั่วไป คลาสนี้ (และ Parcelable API ที่สอดคล้องกันสำหรับการวางวัตถุโดยพลการลงใน Parcel) ได้รับการออกแบบให้เป็นการขนส่ง IPC ที่มีประสิทธิภาพสูง ด้วยเหตุนี้จึงไม่เหมาะสมที่จะวางข้อมูลพัสดุลงในที่จัดเก็บถาวร: การเปลี่ยนแปลงในการนำข้อมูลใด ๆ ในพัสดุไปใช้งานอาจทำให้ข้อมูลเก่าไม่สามารถอ่านได้
Marcos Vasconcelos

สิ่งนี้เลิกใช้แล้ว
IgorGanapolsky

0

คุณสามารถใช้ GSON โดยใช้ Gradle Build.gradle:

implementation 'com.google.code.gson:gson:2.8.0'

จากนั้นในโค้ดของคุณตัวอย่างเช่นคู่ของสตริง / บูลีนกับ Kotlin:

        val nestedData = HashMap<String,Boolean>()
        for (i in 0..29) {
            nestedData.put(i.toString(), true)
        }
        val gson = Gson()
        val jsonFromMap = gson.toJson(nestedData)

การเพิ่ม SharedPrefs:

        val sharedPrefEditor = context.getSharedPreferences(_prefName, Context.MODE_PRIVATE).edit()
        sharedPrefEditor.putString("sig_types", jsonFromMap)
        sharedPrefEditor.apply()

ตอนนี้เพื่อดึงข้อมูล:

val gson = Gson()
val sharedPref: SharedPreferences = context.getSharedPreferences(_prefName, Context.MODE_PRIVATE)
val json = sharedPref.getString("sig_types", "false")
val type = object : TypeToken<Map<String, Boolean>>() {}.type
val map = gson.fromJson(json, type) as LinkedTreeMap<String,Boolean>
for (key in map.keys) {
     Log.i("myvalues", key.toString() + map.get(key).toString())
}

พัสดุไม่ใช่กลไกการทำให้เป็นลำดับตามวัตถุประสงค์ทั่วไป คลาสนี้ (และ Parcelable API ที่สอดคล้องกันสำหรับการวางวัตถุโดยพลการลงใน Parcel) ได้รับการออกแบบให้เป็นการขนส่ง IPC ที่มีประสิทธิภาพสูง ด้วยเหตุนี้จึงไม่เหมาะสมที่จะวางข้อมูลพัสดุลงในที่จัดเก็บถาวร: การเปลี่ยนแปลงในการนำข้อมูลใด ๆ ในพัสดุไปใช้งานอาจทำให้ข้อมูลเก่าไม่สามารถอ่านได้
Marcos Vasconcelos

0

SharedPreference ทั่วไป (CURD): เพื่อจัดเก็บข้อมูลในรูปแบบของคู่คีย์ค่าด้วยคลาส Kotlin แบบง่าย

var sp = SharedPreference(this);

การจัดเก็บข้อมูล:

ในการจัดเก็บข้อมูล String, Int และ Boolean เรามีสามวิธีที่มีชื่อเดียวกันและพารามิเตอร์ต่างกัน (Method overloading)

save("key-name1","string value")
save("key-name2",int value)
save("key-name3",boolean)

ดึงข้อมูล: ในการดึงข้อมูลที่เก็บไว้ใน SharedPreferences ใช้วิธีการต่อไปนี้

sp.getValueString("user_name")
sp.getValueInt("user_id")
sp.getValueBoolean("user_session",true)

ล้างข้อมูลทั้งหมด: หากต้องการล้าง SharedPreferences ทั้งหมดให้ใช้รหัสด้านล่าง

 sp.clearSharedPreference()

ลบข้อมูลเฉพาะ:

sp.removeValue("user_name")

คลาสการตั้งค่าที่ใช้ร่วมกันทั่วไป

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

class SharedPreference(private val context: Context) {
    private val PREFS_NAME = "coredata"
    private val sharedPref: SharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
    //********************************************************************************************** save all
    //To Store String data
    fun save(KEY_NAME: String, text: String) {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.putString(KEY_NAME, text)
        editor.apply()
    }
    //..............................................................................................
    //To Store Int data
    fun save(KEY_NAME: String, value: Int) {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.putInt(KEY_NAME, value)
        editor.apply()
    }
    //..............................................................................................
    //To Store Boolean data
    fun save(KEY_NAME: String, status: Boolean) {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.putBoolean(KEY_NAME, status)
        editor.apply()
    }
    //********************************************************************************************** retrieve selected
    //To Retrieve String
    fun getValueString(KEY_NAME: String): String? {

        return sharedPref.getString(KEY_NAME, "")
    }
    //..............................................................................................
    //To Retrieve Int
    fun getValueInt(KEY_NAME: String): Int {

        return sharedPref.getInt(KEY_NAME, 0)
    }
    //..............................................................................................
    // To Retrieve Boolean
    fun getValueBoolean(KEY_NAME: String, defaultValue: Boolean): Boolean {

        return sharedPref.getBoolean(KEY_NAME, defaultValue)
    }
    //********************************************************************************************** delete all
    // To clear all data
    fun clearSharedPreference() {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.clear()
        editor.apply()
    }
    //********************************************************************************************** delete selected
    // To remove a specific data
    fun removeValue(KEY_NAME: String) {
        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.remove(KEY_NAME)
        editor.apply()
    }
}

บล็อก: https://androidkeynotes.blogspot.com/2020/02/shared-preference.html


-2

ไม่มีวิธีการจัดเก็บอ็อบเจ็กต์ใน SharedPreferences สิ่งที่ฉันทำคือสร้างคลาสสาธารณะใส่พารามิเตอร์ทั้งหมดที่ฉันต้องการและสร้างเซ็ตเตอร์และตัวรับฉันสามารถเข้าถึงอ็อบเจ็กต์ของฉัน


-3

คุณต้องการดึงข้อมูลวัตถุแม้ว่าแอปพลิเคชันจะปิด Donw หรือในระหว่างที่กำลังทำงานอยู่?

คุณสามารถจัดเก็บลงในฐานข้อมูล
หรือเพียงแค่สร้างคลาสแอปพลิเคชันที่กำหนดเอง

public class MyApplication extends Application {

    private static Object mMyObject;
    // static getter & setter
    ...
}

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application ... android:name=".MyApplication">
        <activity ... />
        ...
    </application>
    ...
</manifest>

จากนั้นทุกกิจกรรมจะทำ:

((MyApplication) getApplication).getMyObject();

ไม่ใช่วิธีที่ดีที่สุด แต่ได้ผล


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.