Singleton Android无法访问数据

时间:2016-12-01 00:54:39

标签: java android multithreading singleton

我正在尝试从一个类中获取数据,将其放入单例中,然后继续访问另一个类中的数据。

这是我的单身人士:

public class DataTransferrer {
    private static DataTransferrer instance = null;

    private ArrayList<Transients> transientList;

    private DataTransferrer(){
        transientList = new ArrayList<>();
    }

    public static synchronized DataTransferrer getInstance(){
        if(instance == null) {instance = new DataTransferrer();}
        return instance;
    }

    public ArrayList<Transients> getTransients(){return this.transientList;}

    public void setTransients(ArrayList<Transients> t){transientList = t;}

    public void printAll(){
        for(Transients t : transientList){
            Log.d("DEBUG DA",t.getDa().toString());
        }
    }

    }

以下是我的方法,将数据添加到arrayList,然后将其设置为单例中的arrayList,然后在其他地方使用:

public class JSONParser {

    // URL to get contacts JSON
    private static String url = "http://pi.cs.oswego.edu/~lpatmore/getAllTransients.php";

    ArrayList<Transients> transientList;

    private Transients t;

    public JSONParser(){
        transientList = new ArrayList<>();
    }

    public void execute(){
        new GetTransients().execute();
    }
    /**
     * Async task class to get json by making HTTP call
     */
    private class GetTransients extends AsyncTask<Void, Void, Void> {

        protected Void doInBackground(Void... arg0) {
            HttpHandler sh = new HttpHandler();

            // Making a request to url and getting response
            String jsonStr = sh.makeServiceCall(url);

            Log.d(TAG, "Response from url: " + jsonStr);

            if (jsonStr != null) {
                try {

                    Log.d(TAG, "NOT NULL DEBUG");
                    JSONObject jsonObj = new JSONObject(jsonStr);

                    // Getting JSON Array node
                    JSONArray transients = jsonObj.getJSONArray("result");

                    // looping through All Transients
                    for (int i = 0; i < transients.length(); i++) {
                        JSONObject c = transients.getJSONObject(i);

                        String author = c.getString("author");
                        String transientId = c.getString("transientId");
                        String dateAlerted = c.getString("dateAlerted");
                        String datePublished = c.getString("datePublished");
                        float right_asencsion = (float) c.getDouble("right_asencsion");
                        float declination = (float) c.getDouble("declination");

                        t = new Transients(author, transientId, dateAlerted, datePublished, right_asencsion, declination);

                        // adding trans to trans list
                        transientList.add(t);
                    }
                    DataTransferrer.getInstance().setTransients(transientList);
                    DataTransferrer.getInstance().printAll();
                } catch (final JSONException e) {
                    Log.e(TAG, "Json parsing error: " + e.getMessage());
                }
            } else {
                Log.e(TAG, "Couldn't get json from server.");
            }
            return null;
        }

    }
}

我尝试在另一个类中访问它,如:

 for(int i = 0; i <      DataTransferrer.getInstance().getTransients().size(); i++){
        System.out.println("DEBUG ADDED TRANSIENT");
        Float ra = DataTransferrer.getInstance().getTransients().get(i).getR();
        Float dec = DataTransferrer.getInstance().getTransients().get(i).getD();
        transients.add(new Transient("Transient", names[i], GeocentricCoordinates.getInstance(ra, dec)));
    }

每当我调试它检查以查看其他类时,我正在尝试访问arraylist,但在另一个类中,它似乎从未向{{1}添加数组列表方法。

我在Eclipse中测试了这个确切的设置,但它在Android Studio中运行得很好。

1 个答案:

答案 0 :(得分:0)

  

我在Eclipse中测试了这个确切的设置,它运行得很好,但没有   Android Studio。

基本上,你有多线程问题即,你的DataTransferrer类不是线程安全导致问题,即多线程和你的单例之间存在竞争条件{{1实际上并不是单例(为instance类创建了多个对象)。

因此,当您从一个线程调用DataTransferrer时,它实际上将setTransients()存储在Transients的{​​{1}}中,然后当您尝试检索{{1}时来自不同的线程,它使用instance的不同DataTransferrer(对象)。

您可以为Transients类创建线程安全的单例实例,如下所示:

instance

另请注意,在上述代码中, DataTransferrer将在启动(初始化)时启动{<1}}和DataTransferrer将使用相同的public class DataTransferrer { private static final DataTransferrer instance = new DataTransferrer(); private ArrayList<Transients> transientList = new ArrayList<>(); //private constructor, so instantiation NOT allowed private DataTransferrer() {} public static synchronized DataTransferrer getInstance(){ return instance; } public ArrayList<Transients> getTransients(){ return this.transientList; } public void setTransients(ArrayList<Transients> t){ transientList = t; } public void printAll(){ for(Transients t : transientList){ Log.d("DEBUG DA",t.getDa().toString()); } } } (单例)。如果您需要懒惰地创建instance,而不是急切创建,您可以查看here