Volley not sending correct data. How to implement an alternative to onPostExecute()?

我只是一个虾纸丫 提交于 2019-12-12 01:55:50

问题


I'm using Volley to get some JSON data to populate a RecyclerView list. The initial JSON file returns some information like:

  • id
  • server
  • status

If I request a new JSON using "Server URL/server/id" then I can get some extra information about the server/item to display on the view like:

  • address
  • type
  • flavor

I want to display in my RecyclerView list both sets of info for each item, like:

  • server
  • status
  • address
  • type
  • flavor

However I need the id of each server to get the extra info using a secondary JSON file.

To ilustrate I need to get:

  1. server1-active-1.1.1.1-type1-flavor1
  2. server2-stopped-2.2.2.2-type2-flavor2
  3. server3-paused-3.3.3.3-type3-flavor3

but I'm getting:

  1. server1-active-1.1.1.1-type1-flavor1
  2. server2-stopped-1.1.1.1-type1-flavor1
  3. server3-paused-1.1.1.1-type1-flavor1

I put the following code in place to get the extra info for each item to request the extra data when the main JSON file is parsed however I get the exact same "address", "type", "flavor" for every single item:

Parser Class:

public class NovaParser extends Activity{

    public static final String ID = "id";
    public static final String NAME = "name";
    public static final String STATUS = "status";
    public static final String FLAVOR = "flavor";
    public static final String NETID = "netid";
    public static final String ADDR = "addr";
    public static final String HOST = "host";

    public String authToken;
    public String novaURL;

    public SharedPreferences shPref;

    public ArrayList<HashMap<String, String>> flavorList;

    public static NovaParser parser = null;

    public static NovaParser shared(){
        if (parser  == null){
            parser  = new NovaParser();
        }
        return parser ;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    public void setFlavorList(ArrayList<HashMap<String, String>> flavorList) {
        this.flavorList = flavorList;
    }

    public ArrayList<HashMap<String, String>> getFlavorList(){
        return flavorList;
    }

    public static ArrayList<HashMap<String, String>> parseJSON(String novaJSON){
        ArrayList<HashMap<String, String>> jsonList = new ArrayList<HashMap<String, String>>();
        ArrayList<HashMap<String, String>> tempList = new ArrayList<HashMap<String, String>>();
        try {
            NovaInstances novaInstance = new NovaInstances();
            JSONObject nova = new JSONObject(novaJSON);
            JSONArray servers = nova.getJSONArray("servers");

            for (int i = 0; i < servers.length(); i++) {
                JSONObject objsrv = servers.getJSONObject(i);
                novaInstance.setName(objsrv.getString("name"));
                novaInstance.setId(objsrv.getString("id"));
                novaInstance.setStatus(objsrv.getString("OS-EXT-STS:vm_state"));
                novaInstance.setHost(objsrv.getString("OS-EXT-SRV-ATTR:host"));
                String id = novaInstance.getId();
                String instanceDetail = NovaJSON.shared().receiveDetail(id);
                if (instanceDetail != null) {
                    novaInstance.setFlavor(parseFlavor(instanceDetail));
                }
                String netDetail = NovaJSON.shared().receiveIP(id);
                if (netDetail != null) {
                    tempList = parseNet(netDetail);
                }
                for (int j = 0; j < tempList.size(); j++) {
                    novaInstance.setNetid(tempList.get(j).get(NETID));
                    novaInstance.setAddr(tempList.get(j).get(ADDR));
                }
                HashMap<String, String> map = new HashMap<String, String>();
                map.put(NAME, novaInstance.getName());
                map.put(ID, novaInstance.getId());
                map.put(STATUS, novaInstance.getStatus());
                map.put(FLAVOR, novaInstance.getFlavor());
                map.put(HOST, novaInstance.getHost());
                map.put(NETID, novaInstance.getNetid());
                map.put(ADDR, novaInstance.getAddr());
                jsonList.add(map);
            }
        } catch (JSONException e) {
            Log.d("ErrorInitJSON", e.toString());
            e.printStackTrace();
        }

        Collections.sort(jsonList, new Comparator<HashMap<String, String>>() {
        @Override
        public int compare(HashMap<String, String> lhs, HashMap<String, String> rhs) {
                return (lhs.get("name")).compareToIgnoreCase(rhs.get("name"));
            }
        });


        return jsonList;
    }

    public static String parseFlavor(String instanceDetail){
        ArrayList<HashMap<String, String>> flavorList = NovaParser.shared().getFlavorList();
        String temp = null;
        JSONObject novaDetail = null;
        try {
            novaDetail = new JSONObject(instanceDetail);
            JSONObject server = novaDetail.getJSONObject("server");
            JSONObject flavor = server.getJSONObject("flavor");
            if (flavorList !=null){
            temp = flavor.getString("id");
            for (Map<String,String> map : flavorList) {
                if (map.containsValue(temp)) {
                    temp = map.get(NAME);
                }
            }
            }
            /*JSONObject addresses = server.getJSONObject("addresses");
            Iterator<String> keys=addresses.keys();
            while(keys.hasNext())
            {
                String key=keys.next();
                String value=addresses.getString(key);
                novaInstance.setNet(value);
            }
            JSONObject security_groups = server.getJSONObject("security_groups");*/

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

        return temp;
    }

    public static ArrayList<HashMap<String, String>> parseNet(String netDetail){
        ArrayList<HashMap<String, String>> netList = new ArrayList<HashMap<String, String>>();
        String netId = null, addr = null;
        JSONObject net = null;
        try {
            net = new JSONObject(netDetail);
            JSONObject addresses = net.getJSONObject("addresses");
            Iterator<String> keys=addresses.keys();
            while(keys.hasNext())
            {
                String key=keys.next();
                String value=addresses.getString(key);
                netId = key;

            JSONArray network = addresses.getJSONArray(key);
            for (int i = 0; i < network.length(); i++) {
                JSONObject objnet = network.getJSONObject(i);
                addr = objnet.getString("addr");
                HashMap<String, String> map = new HashMap<String, String>();
                map.put(NETID, netId);
                map.put(ADDR, addr);
                netList.add(map);
            }
            }


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

        return netList;
    }

}

Volley class to get JSON data:

public class NovaJSON extends Activity {

    String novaJSON;
    String nova;
    String auth;
    String novaJSONdetail;
    String novaJSONip;
    String id;
    RequestQueue queue = null;

    public static NovaJSON parser = null;

    public static NovaJSON shared(){
        if (parser  == null){
            parser  = new NovaJSON();
        }
        return parser ;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getNovaJSON() {
        return novaJSON;
    }

    public void setNovaJSON(String novaJSON) {
        this.novaJSON = novaJSON;
    }

    public String getNova() {
        return nova;
    }

    public void setNova(String nova) {
        this.nova = nova;
    }

    public String getAuth() {
        return auth;
    }

    public void setAuth(String auth) {
        this.auth = auth;
    }

    public String getNovaJSONdetail() {
        return novaJSONdetail;
    }

    public void setNovaJSONdetail(String novaJSONdetail) {
        this.novaJSONdetail = novaJSONdetail;
    }

    public String getNovaJSONip() {
        return novaJSONip;
    }

    public void setNovaJSONip(String novaJSONip) {
        this.novaJSONip = novaJSONip;
    }

    public String receiveData (String novaURL, String authToken){
        setNova(novaURL);
        setAuth(authToken);
        getJSON();
        getNovaJSON();
        return novaJSON;
    }

    public String receiveDetail (String id){
        setId(id);
        getJSONdetail();
        getNovaJSONdetail();
        return novaJSONdetail;
    }

    public String receiveIP (String id){
        setId(id);
        getJSONip();
        getNovaJSONip();
        return novaJSONip;
    }

    public void getJSON() {
        final String authToken = getAuth();
        String novaURL = getNova();
        novaURL = novaURL+"/servers/detail";


        JsonObjectRequest getRequest = new JsonObjectRequest(Request.Method.GET, novaURL, null,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                        Log.d("Nova on Response", response.toString());
                        setNovaJSON(response.toString());
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        VolleyLog.d("Nova on Error", "Error: " + error.getMessage());
                        setNovaJSON(error.toString());
                    }
                }
        ) {
            public Map<String, String> getHeaders() throws AuthFailureError {
                Map<String, String> params = new HashMap<String, String>();
                params.put("X-Auth-Token", authToken);
                params.put("User-Agent", "stackerz");
                params.put("Accept", "application/json");
                params.put("Content-Type", "application/json; charset=utf-8");
                return params;
            }

        };


        queue = VolleySingleton.getInstance(this).getRequestQueue();
        //VolleySingleton.getInstance(this).addToRequestQueue(getRequest);
        queue.add(getRequest);
    }

    public void getJSONdetail() {
        final String authToken = getAuth();
        String novaURL = getNova();
        novaURL = novaURL+"/servers/"+id;


        JsonObjectRequest getRequest = new JsonObjectRequest(Request.Method.GET, novaURL, null,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                        Log.d("Nova on Response", response.toString());
                        setNovaJSONdetail(response.toString());
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        VolleyLog.d("Nova on Error", "Error: " + error.getMessage());
                        setNovaJSONdetail(error.toString());
                    }
                }
        ) {
            public Map<String, String> getHeaders() throws AuthFailureError {
                Map<String, String> params = new HashMap<String, String>();
                params.put("X-Auth-Token", authToken);
                params.put("User-Agent", "stackerz");
                params.put("Accept", "application/json");
                params.put("Content-Type", "application/json; charset=utf-8");
                return params;
            }

        };


        queue = VolleySingleton.getInstance(this).getRequestQueue();
        //VolleySingleton.getInstance(this).addToRequestQueue(getRequest);
        queue.add(getRequest);
    }

    public void getJSONip() {
        final String authToken = getAuth();
        String novaURL = getNova();
        novaURL = novaURL+"/servers/"+id+"/ips";


        JsonObjectRequest getRequest = new JsonObjectRequest(Request.Method.GET, novaURL, null,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                        Log.d("Nova on Response", response.toString());
                        setNovaJSONip(response.toString());
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        VolleyLog.d("Nova on Error", "Error: " + error.getMessage());
                        setNovaJSONip(error.toString());
                    }
                }
        ) {
            public Map<String, String> getHeaders() throws AuthFailureError {
                Map<String, String> params = new HashMap<String, String>();
                params.put("X-Auth-Token", authToken);
                params.put("User-Agent", "stackerz");
                params.put("Accept", "application/json");
                params.put("Content-Type", "application/json; charset=utf-8");
                return params;
            }

        };


        queue = VolleySingleton.getInstance(this).getRequestQueue();
        //VolleySingleton.getInstance(this).addToRequestQueue(getRequest);
        queue.add(getRequest);
    }
}

After some debugging I found out Volley is too slow on the following methods:

public String receiveDetail (String id){
    setId(id);
    getJSONdetail();
    getNovaJSONdetail();
    return novaJSONdetail;
}

public String receiveIP (String id){
    setId(id);
    getJSONip();
    getNovaJSONip();
    return novaJSONip;
}

getJSONxxx() works fine and sets the novaJSONxxx string fine with the JSON data for each single item however the getter getNovaxxx() always returns the value for the very first item. It seems the getter is too fast for Volley. With AsyncTask it's possible to run onPostExecute() when the data is ready however Volley doesn't have this option.

Is there a way to get it working or implement an alternative so each JSON data is returned to the correct item?


回答1:


I solved my problem by dumping Volley altogether and moving to Retrofit. I setup all the calls to be sync/blocking, worked out the exceptions/errors using try/catches and setup a short timeout on the OkHTTP client. Now it's working as I wanted.



来源:https://stackoverflow.com/questions/27393502/volley-not-sending-correct-data-how-to-implement-an-alternative-to-onpostexecut

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!