如何从void方法onLocationChanged传递URL至jsonParse调用天气API
解决方案与新手开发建议
首先,你的核心需求很清晰:在获取到设备位置后,生成天气API请求URL,然后调用jsonParse()方法发起网络请求并解析数据。咱们一步步来调整代码,同时给你一些新手友好的开发提示。
一、修改代码实现需求
1. 调整变量作用域与核心逻辑
首先要确保URL能被jsonParse()正确获取到,更规范的方式是把URL作为参数传给jsonParse()(避免依赖成员变量,代码更健壮)。同时,在onLocationChanged()中生成URL后,直接调用jsonParse()即可。
下面是修改后的完整代码示例:
// 定义成员变量:Volley请求队列(记得在onCreate中初始化) private RequestQueue mQueue; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.your_layout); // 初始化Volley请求队列 mQueue = Volley.newRequestQueue(this); // 这里初始化你的TextView控件:TV_temp_max、TV_temp_min等 TV_temp_max = findViewById(R.id.tv_temp_max); TV_temp_min = findViewById(R.id.tv_temp_min); TV_temp = findViewById(R.id.tv_temp); TV_humidity = findViewById(R.id.tv_humidity); TV_country = findViewById(R.id.tv_country); TV_city = findViewById(R.id.tv_city); } @Override public void onLocationChanged(Location location) { // 先判断location是否为空,避免空指针异常 if (location == null) { Log.e("LocationError", "获取到的位置为空"); return; } // 生成天气API请求URL,添加units参数返回摄氏度(默认是开尔文) String weatherUrl = "https://api.openweathermap.org/data/2.5/weather?lat=" + location.getLatitude() + "&lon=" + location.getLongitude() + "&appid=5d8fea5f1c9cdfe8af473504e5f9002a" + "&units=metric"; Log.i("api", weatherUrl); // 调用jsonParse方法,把生成的URL传进去 jsonParse(weatherUrl); } // 修改jsonParse方法,接收URL参数 private void jsonParse(String requestUrl) { JsonObjectRequest request = new JsonObjectRequest( Request.Method.GET, requestUrl, null, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { try { JSONObject weatherData = response.getJSONObject("main"); double temp = weatherData.getDouble("temp"); double tempHigh = weatherData.getDouble("temp_max"); double tempLow = weatherData.getDouble("temp_min"); double humidity = weatherData.getDouble("humidity"); Log.i("JSONWork", weatherData.toString()); // 用setText替换append,避免多次更新时文本累加 TV_temp_max.setText("Highest Temperature: " + tempHigh + "°C"); TV_temp_min.setText("Lowest Temperature: " + tempLow + "°C"); TV_temp.setText("Current Temperature: " + temp + "°C"); TV_humidity.setText("Humidity: %" + humidity); // 注意:城市名称在response根节点的"name"字段,不是sys里的 String city = response.getString("name"); JSONObject locationData = response.getJSONObject("sys"); String country = locationData.getString("country"); TV_country.setText(country); TV_city.setText(city); } catch (JSONException e) { Log.e("JSONError", "解析JSON失败", e); // 给用户显示友好的错误提示 Toast.makeText(getApplicationContext(), "数据解析失败", Toast.LENGTH_SHORT).show(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e("VolleyError", "网络请求失败", error); Toast.makeText(getApplicationContext(), "网络请求失败,请检查网络", Toast.LENGTH_SHORT).show(); error.printStackTrace(); } }); mQueue.add(request); } // 其他位置回调方法保持不变 @Override public void onStatusChanged(String s, int i, Bundle bundle) { } @Override public void onProviderEnabled(String s) { } @Override public void onProviderDisabled(String s) { }
二、新手开发关键建议
- 变量作用域问题:避免使用局部变量传递跨方法的数据,要么用成员变量,要么像示例中那样把数据作为参数传递(更推荐,减少代码耦合)。
- 空指针防护:永远要判断
location是否为空,比如设备位置服务异常时可能返回null,直接调用location.getLatitude()会导致崩溃。 - Volley队列初始化:必须在
onCreate()中初始化RequestQueue,不要每次请求都新建,否则会浪费系统资源。 - 权限申请:别忘了在
AndroidManifest.xml中添加必要权限:
同时在代码中动态申请位置权限(Android 6.0+系统要求)。<!-- 网络权限 --> <uses-permission android:name="android.permission.INTERNET" /> <!-- 位置权限 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> - API参数优化:添加
&units=metric参数可以返回摄氏度(默认是开尔文,普通用户看不懂),如果需要华氏度可以替换为units=imperial。 - UI更新注意:
append()会不断累加文本,多次获取位置后会重复显示内容,建议用setText()替换。另外Volley的回调是在主线程执行的,所以可以直接更新UI,不用手动切换线程。 - 异常处理:不要只打印日志,给用户显示友好的错误提示(比如Toast),提升App的使用体验。
内容的提问来源于stack exchange,提问作者P.Pascarella
相关产品推荐
相关产品推荐

