我正在开发一个Android项目。我得到了谷歌api的回复并解析了json。但我想在onResponse方法之外返回值,这对我来说似乎是不可能的。以下是我的代码,我已在此处看到此answer。但我想在这个异步方法之外的这个值。是否可以访问此值。
更新 - 我已更新了我的代码以获取更多详细信息。这是我的完整活动课程。你可以看到我想要达到的目标。请帮助我如何在方法onResponse
中的方法get_time_to_travel
中访问Volley parseJson
返回的值。这真的让我很伤心。我的第一个Android项目,我在最近两天被困在这里。
对此有任何帮助将不胜感激。
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;
}
}
答案 0 :(得分:2)
异步任务正在其他线程上工作。因此,如果您想要访问该方法的任何变量,您需要等到任务完成。否则变量将为null。 例如:on on response method
@Override
public void onResponse(String response) {
res=response;
anyMethodtopassVar(DataType data);
}
答案 1 :(得分:1)
在活动OnCreate()
中,删除这2行
adapter = new CustomAdapter(this, userData);
recyclerView.setAdapter(adapter);
在getData()
中删除此行
userData = new ArrayList<>();
将它们放在parseJson()
中,如下所示:
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();
}
}
这样,当json调用完成时,调用parseJson()
。
在将数组解析为userData
后,适配器将被初始化或通知。
修改强>
嗯,这不是最好的解决方案。但它只是我头脑中的东西 有点讨厌/肮脏。我不知道,但我认为它会完成这项工作
1-您不必每次都重新启动队列,因此在get_time_to_travel()
中将该行放在方法之外:
requestQueue1 = Volley.newRequestQueue(this);
将final int index
param添加到方法并将其设为void
:
private void get_time_to_travel(String origin, String destination, String API, String mode, final int index){...
在方法中生成onResponse()
,如下所示:
public void onResponse(JSONObject response) {
eta = parseGoogleData(response);
userData.get(index).setEta(eta);//add this setter to your data object if not exist.
}
删除 return eta;
现在使用空字符串初始化udata为eta
:
UserData udata = new UserData(id, name, username, email, address, phone, website, company,"");
userData.add(udata);
修改get_time_to_travel()
中parseJson()
的来电,如下所示:
get_time_to_travel(origin, destination, API, mode, i);
在get_time_to_travel()
调用onResponse()
时,对象将被修改为保存从API检索的eta
值
这很讨厌,有时候adapter
可能会在完成对 google api 的所有通话之前得到通知。所以这只是为了告诉你如何制作它
<强> EDIT2 强> 解决方法就是这样 init userData对象,带标签&#34;正在加载......&#34;对于eta
UserData udata = new UserData(id, name, username, email, address, phone, website, company,"Loading...");
并在onResponse()
的{{1}}结束时通知适配器:
get_time_to_travel()
答案 2 :(得分:0)
您想在parseJson
内获得onResponse
的结果吗?
将parseJson的返回类型更改为UserData
,在try块内调用return userDate;
,在catch块中调用return null;
。这将帮助您从调用它的位置捕获parseJson的结果。
如果我没有正确理解你的问题,请告诉我。
答案 3 :(得分:-1)
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);
}
现在在你的主要活动中,你可以这样做。
public void onResume(){
super.onResume();
getString(new VolleyCallback(){
@Override
public void onSuccess(String res){
... //do something
}
});
}