How to access response value outside onResponse me

2019-07-24 15:40发布

I am working on a android project. I got the response from google api and parsed the json. But i want to return the value outside of onResponse method which seems to be impossible for me now. Below is my code, I have already seen this answer here. But i want this value outside of this async method. Is it possible to access this value.

UPDATE - I have updated my code for more details. This is my full activity class. You can see what i want to achieve. Please help me how i can access value returned by Volley onResponse in method get_time_to_travel, inside method parseJson. This is really killing me now. My first android project and i am stuck here from last two days.

Any help on this would be appreciated.

public class MainActivity extends AppCompatActivity {


    private RecyclerView recyclerView;
    private LinearLayoutManager linearLayoutManager;
    private CustomAdapter adapter;
    private List<UserData> userData;
    private LocationManager locationManager;
    private LocationListener locationListener;
    String origin, mode = "driving";
    private String API = "APIKey";
    TextView textView;
    RequestQueue requestQueue;
    RequestQueue requestQueue1;
    String url = "https://url/users";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
        recyclerView.setHasFixedSize(true);


        locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
        locationListener = new LocationListener() {
            @Override
            public void onLocationChanged(Location location) {
                double lat = location.getLatitude();
                double lng = location.getLongitude();
                origin = String.valueOf(lat)+","+String.valueOf(lng);
            }

            @Override
            public void onStatusChanged(String provider, int status, Bundle extras) {

            }

            @Override
            public void onProviderEnabled(String provider) {

            }

            @Override
            public void onProviderDisabled(String provider) {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                startActivity(intent);
            }
        };
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{
                        Manifest.permission.ACCESS_FINE_LOCATION,
                        Manifest.permission.ACCESS_COARSE_LOCATION,
                        Manifest.permission.INTERNET
                }, 10);
            }
            return;
        }
        else{
            locationManager.requestLocationUpdates("gps", 5000, 0, locationListener);
        }


        getData();

        linearLayoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(linearLayoutManager);
        adapter = new CustomAdapter(this, userData);
        recyclerView.setAdapter(adapter);

    }

    private void getData(){
        userData = new ArrayList<>();
        requestQueue = Volley.newRequestQueue(this);

        JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(url,
                new Response.Listener<JSONArray>() {

                    @Override
                    public void onResponse(JSONArray response) {
                        parseJson(response);
                    }
                },

                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Log.e("VOLLEY", "ERROR");
                    }
                }
        );
        requestQueue.add(jsonArrayRequest);
    }

    private void parseJson(JSONArray response){
        try {
            for (int i = 0; i < response.length(); i++) {
                JSONObject users = response.getJSONObject(i);

                String id = ("id: "+users.getString("id"));
                String name = ("Name: "+users.getString("name"));
                String username = ("Username: "+users.getString("username"));
                String email = ("Email: "+users.getString("email"));
                String address = parseAddress(users);
                String destination = parseCoordinates(users);
                String company = parseCompany(users);
                String phone = ("Phone: "+users.getString("phone"));
                String website = ("Website: "+users.getString("website"));
                String eta = get_time_to_travel(origin, destination, API, mode);

                UserData udata = new UserData(id, name, username, email, address, phone, website, company,eta);
                userData.add(udata);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }


    private String parseAddress(JSONObject users) {
        JSONObject completeAdd = null;
        String address = null;
        try {
            completeAdd = users.getJSONObject("address");
            String street = completeAdd.getString("street");
            String suite = completeAdd.getString("suite");
            String city = completeAdd.getString("city");
            String zipcode = completeAdd.getString("zipcode");
            address = ("Address :" + street + ", " + suite + ", " + city + ", " + zipcode);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return address;
    }

    private String parseCoordinates(JSONObject users) {
        JSONObject completeAdd = null;
        String destination = null;
        try {
            completeAdd = users.getJSONObject("address");
            JSONObject coordinates = completeAdd.getJSONObject("geo");
            String latitude = coordinates.getString("lat");
            String longitude = coordinates.getString("lng");
            destination = latitude + "," + longitude;
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return destination;
    }

    private String parseCompany(JSONObject users) {
        JSONObject companyDetail = null;
        String company = null;
        try {
            companyDetail = users.getJSONObject("company");
            String company_name = companyDetail.getString("name");
            String catchPhrase = companyDetail.getString("catchPhrase");
            String bs = companyDetail.getString("bs");
            company = ("Company: " + company_name + ", " + catchPhrase + ", " + bs);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return company;
    }


    private String get_time_to_travel(String origin, String destination, String API, String mode){
        requestQueue1 = Volley.newRequestQueue(this);
        String eta = null;
        String google_api = "https://maps.googleapis.com/maps/api/distancematrix/json?origins="+origin+"&destinations="
                +destination+"s&mode="+mode+"&language=fr-FR&key="+API;
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, google_api, null,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                        eta = parseGoogleData(response);
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Log.e("VOLLEY", "ERROR");
                    }
                }

        );
        requestQueue1.add(jsonObjectRequest);
        return eta;
    }

    private String parseGoogleData(JSONObject response) {
        String estimated_time_arrival = null;
        try {
            JSONArray rows = response.getJSONArray("rows");

            JSONObject elements = rows.getJSONObject(0);
            JSONArray elementsArr = elements.getJSONArray("elements");

            JSONObject durationObj = elementsArr.getJSONObject(0);
            JSONObject durationData = durationObj.getJSONObject("duration");
            estimated_time_arrival = durationData.getString("text");

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

}

4条回答
放荡不羁爱自由
2楼-- · 2019-07-24 15:52

Async task is doing work on other thread. So if you want to access any variable out side that method, you need to wait until the task get completed. Otherwise the variable will be null. eg: on on response method

@Override
        public void onResponse(String response) {
            res=response;
            anyMethodtopassVar(DataType data);
        }
查看更多
三岁会撩人
3楼-- · 2019-07-24 15:53
public void getString(final VolleyCallback callback) {
    StringRequest req = new StringRequest(Request.Method.GET, url, new     Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            res=response;
            callback.onSuccess(res);
        }
    }...
}}

public interface VolleyCallback{
    void onSuccess(String result);
}

Now inside your mainactivity you can do like this.

public void onResume(){
super.onResume();
getString(new VolleyCallback(){
     @Override
     public void onSuccess(String res){
         ... //do something
     }
});

}

查看更多
孤傲高冷的网名
4楼-- · 2019-07-24 16:09

in OnCreate() of activity, remove these 2 lines

adapter = new CustomAdapter(this, userData);
recyclerView.setAdapter(adapter);

in getData() remove this line

userData = new ArrayList<>();

put them in parseJson() as below:

private void parseJson(JSONArray response){
    try {

        if(userData==null){
            userData = new ArrayList<>();
        }else{
            userData.clear();
        }
        for (int i = 0; i < response.length(); i++) {
            JSONObject users = response.getJSONObject(i);

            String id = ("id: "+users.getString("id"));
            String name = ("Name: "+users.getString("name"));
            String username = ("Username: "+users.getString("username"));
            String email = ("Email: "+users.getString("email"));
            String address = parseAddress(users);
            String destination = parseCoordinates(users);
            String company = parseCompany(users);
            String phone = ("Phone: "+users.getString("phone"));
            String website = ("Website: "+users.getString("website"));
            String eta = get_time_to_travel(origin, destination, API, mode);

            UserData udata = new UserData(id, name, username, email, address, phone, website, company,eta);
            userData.add(udata);
        }

        if(adapter == null){
            adapter = new CustomAdapter(this, userData);
            recyclerView.setAdapter(adapter);
        }else{
            adapter.notifyDataSetChanged();
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

this way, when json call finish, parseJson() is called. and after parsing the array into userData the adapter is initialized or notified.

EDIT:

Well, this is not the best sol. but it's just something from the top of my head little nasty/dirty. i don't know but i think it will do the job

1- you don't have to reinit the queue every time, so in get_time_to_travel() put that line out of the method:

requestQueue1 = Volley.newRequestQueue(this);

add final int index param to the method and make it void:

private void get_time_to_travel(String origin, String destination, String API, String mode, final int index){...

make onResponse() in the method like this:

public void onResponse(JSONObject response) {
    eta = parseGoogleData(response);
    userData.get(index).setEta(eta);//add this setter to your data object if not exist.
}

remove return eta;

init udata with empty string as eta for now:

UserData udata = new UserData(id, name, username, email, address, phone, website, company,"");
userData.add(udata);

modify the call to get_time_to_travel() in parseJson() as below:

get_time_to_travel(origin, destination, API, mode, i);

when get_time_to_travel() is called at onResponse() the object will be modified to hold the eta value retrieved from the API

this is nasty, sometimes the adapter might be notified before all calls to google api is completed. so this is just to show you how to make it

Edit2 a workaround for this is init userData object with label "Loading..." for eta

UserData udata = new UserData(id, name, username, email, address, phone, website, company,"Loading...");

and notify the adapter at end of onResponse() of get_time_to_travel():

public void onResponse(JSONObject response) {
    eta = parseGoogleData(response);
    userData.get(index).setEta(eta);//add this setter to your data object if not exist.
    adapter.notifyDataSetChanged();
}
查看更多
Fickle 薄情
5楼-- · 2019-07-24 16:17

Do you want to get the result of parseJson inside onResponse? Change the return type of parseJson to UserData, call return userDate; inside try block and return null; in catch block. This will help you catch the result of parseJson from where you are calling it. Let me know if I did not understand your question properly.

查看更多
登录 后发表回答