无法控制共享首选项中字符串集的顺序 [英] Can't Control Order of String Set in Shared Preferences

查看:91
本文介绍了无法控制共享首选项中字符串集的顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的第一个stackoverflow问题.我已经对此进行了很多搜索.在Hashsets,Treesets,LinkedHashSets,Collections,Stacks(不推荐使用Stack类吗?)上,我意识到我可以只使用SQLite,但是我暂时试图避免这种情况.

我正在使用Android Studio中的一个应用程序.该应用程序与人打交道,列出他们并以不同方式与他们联系.应用程序用户可以维护和控制三种类型的列表:最近联系过的列表,被阻止的列表和收藏夹.这些列表在共享首选项中另存为字符串集,因此它们在关闭并重新打开的应用程序中仍然有效.使用在线数据库填充列表时,各个字符串充当主键.我最关心最近联系"列表,因为此列表的顺序很重要.

问题是,据我了解,当我声明一个字符串集时,它如下:

  Set< String>faveArray = new LinkedHashSet< String> ;; 

据我了解,我只能在右侧使用HashSet,LinkedHashSet或TreeSet.

由于我使用LinkedHashset,所以我期望当我重新打开应用程序并将数据从sharedpreferences中拉回时,将从最近添加的字符串(LIFO/堆栈)开始拉出字符串,因此当我填充时列表视图,他们将在列表顶部显示最近联系"的人,依此类推...或者至少我期望我可以使用某种可预测的顺序/行为.

所以.......我为共享首选项I/O类附加了代码.

在主应用中,我会执行以下操作:

 静态SharedPrefUTIL sharedPrefUTIL;sharedPrefUTIL =新的SharedPrefUTIL(this);sharedPrefUTIL.addRecent("derp");sharedPrefUTIL.addRecent("nerp");sharedPrefUTIL.addRecent("gerp");sharedPrefUTIL.addRecent("herp"); 

此时,代码

  Log.i(TAG,set +提交给" +键); 

SharedPrefUTIL类的commit()方法中的日志:

"[derp,nerp,gerp,herp]提交到lasterArray"

关闭并重新打开应用后,执行以下操作:

  sharedPrefUTIL.toastContents("R"); 

结果看似随机.<<<<那是我的问题.

任何帮助都将不胜感激.

 程序包com.secretsoft.booberbunz;导入android.content.Context;导入android.content.SharedPreferences;导入android.util.Log;导入android.widget.Toast;导入java.util.Arrays;导入java.util.HashSet;导入java.util.LinkedHashSet;导入java.util.Queue;导入java.util.Set;导入java.util.TreeSet;/***通过2/22/2016编程创建.*/公共类SharedPrefUTIL {受保护的静态最终字符串TAG ="CXX SharedPrefUTIL";上下文上下文;SharedPreferences sharedPreferences;设置< String>faveArray;设置< String>blockArray;设置< String>最近的数组;公共静态最终Set< String>默认值=新的HashSet< String>(Arrays.asList("empty"));公共SharedPrefUTIL(上下文上下文){this.context =上下文;//将共享的首选项加载到静态数组中(新对象可防止出现问题)sharedPreferences = context.getSharedPreferences("prefs",Context.MODE_PRIVATE);最近的数组=新的LinkedHashSet< String>(sharedPreferences.getStringSet("recentArray",DEFAULT));blockArray = new LinkedHashSet< String>(sharedPreferences.getStringSet("blockArray",DEFAULT));faveArray =新的LinkedHashSet< String>(sharedPreferences.getStringSet("faveArray",DEFAULT));Log.i(TAG,已创建SharedPrefUTIL实例");如果(recentArray.contains("empty")){最近的数组.clear();Log.i(TAG,"recentArray包含字符串-empty-并已清除");}如果(blockArray.contains("empty")){blockArray.clear();Log.i(TAG,"blockArray包含字符串-empty-并已清除");}如果(faveArray.contains("empty")){faveArray.clear();Log.i(TAG,"faveArray包含字符串-empty-并已清除");}}公共无效toastLength(字符串类型){如果(类型=="R"){字符串temp =类型+数组这么长:" +最近的数组.size();Toast.makeText(context,temp,Toast.LENGTH_LONG).show();Log.i(TAG,临时);}否则(类型=="B"){字符串temp = type +"array这么长:" + blockArray.size();Toast.makeText(context,temp,Toast.LENGTH_LONG).show();Log.i(TAG,临时);}否则,如果(type =="F"){字符串temp = type +"array这么长:" + faveArray.size();Toast.makeText(context,temp,Toast.LENGTH_LONG).show();Log.i(TAG,临时);}别的 {Log.i(TAG,赋予toastLength()的类型参数无效");}}公共无效toastContents(字符串类型){如果(类型=="R"){对于(String temp:最近的数组){Toast.makeText(context,temp,Toast.LENGTH_LONG).show();Log.i(TAG,"recentArray contains:" + temp);}}否则(类型=="B"){对于(String temp:blockArray){Toast.makeText(context,temp,Toast.LENGTH_LONG).show();Log.i(TAG,"blockArray contains:" + temp);}}否则,如果(type =="F"){对于(String temp:faveArray){Toast.makeText(context,temp,Toast.LENGTH_LONG).show();Log.i(TAG,"faveArray包含:" + temp);}}别的 {Log.i(TAG,给toastContents()的类型参数无效");}}公共无效clearList(String类型){如果(类型=="R"){最近的数组.clear();commit("recentArray",最近的数组);Toast.makeText(context,最近列表已被清除.",Toast.LENGTH_LONG);}否则(类型=="B"){blockArray.clear();commit("blockArray",blockArray);Toast.makeText(context,黑名单已被清除.",Toast.LENGTH_LONG);}否则,如果(type =="F"){faveArray.clear();commit("faveArray",faveArray);Toast.makeText(context,收藏夹已被清除.",Toast.LENGTH_LONG);}别的 {Log.i(TAG,给clearList()无效的类型参数");}}公共无效addRecent(String newRecent){lastArray.add(newRecent);commit("recentArray",最近的数组);Log.i(TAG,newRecent +已添加到最近的数组");}公共无效addBlocked(String newBlocked,字符串昵称){blockArray.add(newBlocked);commit("blockArray",blockArray);Toast.makeText(context,nick +已被列入黑名单!",Toast.LENGTH_SHORT);}公共无效remBlocked(字符串remBlocked,字符串昵称){blockArray.remove(remBlocked);commit("blockArray",blockArray);Toast.makeText(context,nick +已被解除阻止.",Toast.LENGTH_SHORT);}public void addFave(String newFave,String nick){faveArray.add(newFave);commit("faveArray",faveArray);Toast.makeText(context,nick +已添加到收藏夹!",Toast.LENGTH_SHORT);}公共无效remFave(字符串remFave,字符串昵称){faveArray.remove(remFave);commit("faveArray",faveArray);Toast.makeText(context,nick +从收藏夹中删除.",Toast.LENGTH_SHORT);}公共无效提交(String key,Set< String> set){SharedPreferences.Editor编辑器= sharedPreferences.edit();editor.putStringSet(key,set);editor.commit();Log.i(TAG,设置+提交给" +键);}} 

解决方案

不幸的是,但是您只是发现了 SharedPreferences 的局限性.

虽然您使用的是有序哈希,但是当您调用 getStringSet 时,它不会按顺序加载它们.

我发现执行此操作最快,最简单的方法是将数组转换为有序的文本,然后将其保存到SharedPreferences中.Android随附了可以执行此操作的对象 JSONArray .

http://developer.android.com/reference/org/json/JSONArray.html

这里有一些伪代码可以满足您的要求:

  public void saveOrderedCollection(Collection collection,String key){JSONArray jsonArray =新的JSONArray(collection);SharedPreferences.Editor编辑器= sharedPreferences.edit();editor.putString(key,jsonArray.toString());editor.commit();}公共集合loadOrderedCollection(String key){ArrayList arrayList =新的ArrayList;SharedPreferences.Editor编辑器= sharedPreferences.edit();JSONArray jsonArray =新的JSONArray(editor.getString(key,"[]"));for(int i = 0; i< jsonArray.length(); i ++){arrayList.put(jsonArray.get(i));}返回arrayList;} 

以下是我用来撰写此文章的其他帖子:

是否可能将数组或对象添加到Android上的SharedPreferences

在共享首选项中如何存储字符串android应用程序中的数组

This is my first stackoverflow question. I have done lot of googling on this. On Hashsets, Treesets, LinkedHashSets, Collections, Stacks (Stack class is deprecated?)... I realize I could just use SQLite but I'm trying to avoid that for the time being.

I'm working on an app in Android Studio. The app deals with people, listing them and contacting them in different ways. App users can maintain and control three types of lists: recently contacted, blocked, and favorites. These lists are saved as string sets in shared preferences so they survive the app being closed and reopened. The individual strings act as primary keys when the lists are populated using an online database. I am most concerned with the "recently contacted" list because the order of this list matters.

The problem is that as far as I understand, when I declare a string set it is as follows:

Set<String> faveArray = new LinkedHashSet<String>;

As I understand I can only use HashSet, LinkedHashSet, or TreeSet on the right hand side.

Since I used LinkedHashset, I was expecting that when I reopen the app and pull the data back out of sharedpreferences, that the strings would be pulled out starting with the most recently added (LIFO / stack), and therefore when I populate a listview, they will show with the "most recently contacted" person at the top of the list and so on... or at least I was expecting to have some kind of predictable order/behavior that I can work with.

So....... I've attached my code for my shared preferences I/O class.

From my main app, I do something like:

static SharedPrefUTIL sharedPrefUTIL;

sharedPrefUTIL = new SharedPrefUTIL(this);

sharedPrefUTIL.addRecent("derp");
sharedPrefUTIL.addRecent("nerp");
sharedPrefUTIL.addRecent("gerp");
sharedPrefUTIL.addRecent("herp");

At this point, the code

Log.i(TAG, set + " committed to " + key);

in the commit() method of class SharedPrefUTIL Logs:

" [derp, nerp, gerp, herp] committed to recentArray "

Bur after closing and reopening the app, if we perform:

sharedPrefUTIL.toastContents("R");

The result is seemingly random order. <<<< that is my problem.

Any help greatly appreciated.

package com.secretsoft.booberbunz;

import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import android.widget.Toast;

import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Queue;
import java.util.Set;
import java.util.TreeSet;

/**
* Created by Programming on 2/22/2016.
*/
public class SharedPrefUTIL {

protected static final String TAG = "CXX SharedPrefUTIL";

Context context;

SharedPreferences sharedPreferences;

Set<String> faveArray;
Set<String> blockArray;
Set<String> recentArray;

public static final Set<String> DEFAULT = new HashSet<String>(Arrays.asList("empty"));


public SharedPrefUTIL(Context context){

    this.context = context;

    // load shared prefs into static arrays (new objects to prevent problems)

    sharedPreferences = context.getSharedPreferences("prefs", Context.MODE_PRIVATE);

    recentArray = new LinkedHashSet<String>(sharedPreferences.getStringSet("recentArray",DEFAULT));
    blockArray = new LinkedHashSet<String>(sharedPreferences.getStringSet("blockArray",DEFAULT));
    faveArray = new LinkedHashSet<String>(sharedPreferences.getStringSet("faveArray",DEFAULT));

    Log.i(TAG, "SharedPrefUTIL instance created");


    if (recentArray.contains("empty")) {
        recentArray.clear();

        Log.i(TAG, "recentArray contains the string -empty- and was cleared");
    }

    if (blockArray.contains("empty")) {
        blockArray.clear();

        Log.i(TAG, "blockArray contains the string -empty- and was cleared");
    }

    if (faveArray.contains("empty")) {
        faveArray.clear();

        Log.i(TAG, "faveArray contains the string -empty- and was cleared");
    }

}

public void toastLength(String type){

    if (type == "R"){

        String temp = type + " array is this long: " + recentArray.size();

        Toast.makeText(context, temp,
                Toast.LENGTH_LONG).show();

        Log.i(TAG, temp);


    }

    else if (type == "B"){

        String temp = type + " array is this long: " + blockArray.size();

        Toast.makeText(context, temp,
                Toast.LENGTH_LONG).show();

        Log.i(TAG, temp);

    }

    else if (type == "F"){

        String temp = type + " array is this long: " + faveArray.size();

        Toast.makeText(context, temp,
                Toast.LENGTH_LONG).show();

        Log.i(TAG, temp);

    }

    else {
        Log.i(TAG, "invalid type param given to toastLength()");
    }

}


public void toastContents(String type){

    if (type == "R"){

        for (String temp : recentArray) {

        Toast.makeText(context, temp,
                Toast.LENGTH_LONG).show();

        Log.i(TAG, "recentArray contains: " + temp);

    }

    }

    else if (type == "B"){

        for (String temp : blockArray) {

            Toast.makeText(context, temp,
                    Toast.LENGTH_LONG).show();

            Log.i(TAG, "blockArray contains: " + temp);

        }

    }

    else if (type == "F"){

        for (String temp : faveArray) {

            Toast.makeText(context, temp,
                    Toast.LENGTH_LONG).show();

            Log.i(TAG, "faveArray contains: " + temp);

        }
    }

    else {
        Log.i(TAG, "invalid type param given to toastContents()");
    }



}

public void clearList(String type){
    if (type == "R"){
        recentArray.clear();

        commit("recentArray", recentArray);

        Toast.makeText(context,"recent list has been cleared.", Toast.LENGTH_LONG);
    }

    else if (type == "B"){

        blockArray.clear();

        commit("blockArray", blockArray);

        Toast.makeText(context,"blacklist has been cleared.", Toast.LENGTH_LONG);

    }

    else if (type == "F"){

        faveArray.clear();

        commit("faveArray", faveArray);

        Toast.makeText(context,"favorites have been cleared.", Toast.LENGTH_LONG);

    }

    else {
        Log.i(TAG, "invalid type param given to clearList()");
    }

}

public void addRecent(String newRecent){
    recentArray.add(newRecent);
    commit("recentArray", recentArray);
    Log.i(TAG, newRecent + " added to recentArray");
}

public void addBlocked(String newBlocked, String  nick){
    blockArray.add(newBlocked);
    commit("blockArray", blockArray);
    Toast.makeText(context, nick + " has been blacklisted!", Toast.LENGTH_SHORT);
}

public void remBlocked(String remBlocked, String nick){
    blockArray.remove(remBlocked);
    commit("blockArray", blockArray);
    Toast.makeText(context, nick + " has been unblocked.", Toast.LENGTH_SHORT);
}

public void addFave(String newFave, String nick){
    faveArray.add(newFave);
    commit("faveArray", faveArray);
    Toast.makeText(context, nick + " added to favorites!", Toast.LENGTH_SHORT);

}

public void remFave(String remFave, String nick){
    faveArray.remove(remFave);
    commit("faveArray", faveArray);
    Toast.makeText(context, nick + " removed from favorites.", Toast.LENGTH_SHORT);
}

public void commit(String key, Set<String> set){
    SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.putStringSet(key,set);
    editor.commit();
    Log.i(TAG, set + " committed to " + key);
}




}

解决方案

It is unfortunate, but you have simply found a limitation of SharedPreferences.

While you are using an orderd hash, it does not load them ordered when you call getStringSet.

The quickest simplest way I have found of doing this is to convert your array into text, ordered, and then save that into the SharedPreferences. Android comes with an object JSONArray that can do this.

http://developer.android.com/reference/org/json/JSONArray.html

Here is some pseudo code that will do what you want:

public void saveOrderedCollection(Collection collection, String key){
    JSONArray jsonArray = new JSONArray(collection);
    SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.putString(key, jsonArray.toString());
    editor.commit();
}

public Collection loadOrderedCollection(String key){
    ArrayList arrayList = new ArrayList;
    SharedPreferences.Editor editor = sharedPreferences.edit();
    JSONArray jsonArray = new JSONArray(editor.getString(key, "[]"));
    for (int i = 0; i < jsonArray.length(); i++) {
        arrayList.put(jsonArray.get(i));
    }
    return arrayList;
}

Here are some other posts that I used to make this:

Is it possible to add an array or object to SharedPreferences on Android

In shared preferences how to store string array in android application

这篇关于无法控制共享首选项中字符串集的顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆