activity_main.xml文件
android:background="@drawable/rainy"
tools:context=".MainActivity">
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.042" />
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView2"
app:layout_constraintVertical_bias="0.0" />
MainActivity.java文件
这段代码是一个Android应用程序的主活动(MainActivity)。在这个活动中,我们可以看到有一些成员变量被声明和初始化,这些变量主要用于表示应用界面上的不同组件,例如按钮(Button)、编辑文本(EditText)和文本视图(TextView)。
onCreate()
方法是活动生命周期中的一个关键部分,当活动首次被创建时,这个方法会被调用。在这个方法中,首先调用了 setContentView(R.layout.activity_main);
来加载应用的用户界面。然后,通过 findViewById
方法获取到了界面上各个组件的引用。
接下来,进行了和和风天气API(QWeather)的初始化,并设置了搜索按钮的点击事件监听器。在这个监听器中,首先获取到了用户输入的城市名称,然后在新的线程中执行了天气查询的操作。查询操作主要分为四步:获取城市信息、获取天气预报、获取当前天气、获取湿度信息。在每一步查询中,都会使用相应的API方法,并提供一个监听器来处理查询结果。
查询结果会被储存在一些变量中,然后在所有查询结束后,检查这些变量是否都已经有值。如果都有值,那么就创建一个消息,将这些值放入消息的数据包中,然后发送这个消息。
消息会被 mHandler
成员变量处理,这是一个 Handler
对象,它的 handleMessage
方法被覆盖以处理消息。在 handleMessage
方法中,首先检查消息的 what
字段是否为1,如果是,那么就从消息的数据包中获取出天气信息,并将这些信息显示在界面上的相应位置。
应用的功能就是通过用户输入的城市名称,查询并显示这个城市的天气信息。
// 导入必要的包
import com.qweather.sdk.bean.base.Lang;
import com.qweather.sdk.bean.base.Unit;
import com.qweather.sdk.bean.weather.WeatherNowBean;
import com.qweather.sdk.view.HeConfig;
import com.qweather.sdk.view.QWeather;
...
// 初始化 HeConfig。必须首先执行这一步以设置你的公共 ID 和私人密钥。
// 你可以在 QWeather 的网站上获取这些信息。
HeConfig.init("PublicId", "PrivateKey");
// 设置订阅。默认订阅是标准订阅。
// 如果你想要使用免费订阅,可以通过调用 HeConfig.switchToDevService() 切换。
// 如果你想要使用标准订阅,可以通过调用 HeConfig.switchToBizService() 切换。
// 这一步只需要执行一次【20†source】。
HeConfig.switchToBizService();
...
// 获取当前天气信息。
// 第一个参数是一个 Context 对象。
// 第二个参数是你想要获取天气信息的地点。这个值应该是 QWeather 能够识别的地点代码。
// 第三个参数是一个监听器对象,这个对象需要实现 QWeather.OnResultWeatherNowListener 接口。
// 当天气信息获取成功时,onSuccess 方法会被调用;当天气信息获取失败时,onError 方法会被调用【13†source】。
QWeather.getWeatherNow(MainActivity.this, "101010100", new QWeather.OnResultWeatherNowListener() {
@Override
public void onError(Throwable e) {
// 这个方法会在获取天气信息失败时被调用。
// 参数 e 是一个 Throwable 对象,它包含了错误的详细信息。
}
@Override
public void onSuccess(WeatherNowBean weatherBean) {
// 这个方法会在获取天气信息成功时被调用。
// 参数 weatherBean 是一个 WeatherNowBean 对象,它包含了天气的详细信息。
// 你可以通过调用 weatherBean 的各种 getter 方法来获取你需要的信息【14†source】。
String status = weatherBean.getCode();
if ("200".equals(status)) {
String updateTime = weatherBean.getBasic().getUpdateTime();
String temp = weatherBean.getNow().getTemp();
String text = weatherBean.getNow().getText();
// 在这里,你可以更新你的界面,显示天气信息。
} else {
// 在这里,你可以处理错误。比如,你可以显示一个错误消息给用户。
}
}
});
上述代码的核心部分是调用 QWeather.getWeatherNow
方法来获取实时天气信息。你需要向该方法提供一个地点代码和一个监听器。监听器的 onSuccess
方法会在天气信息成功获取后被调用,onError
方法会在获取天气信息失败时被调用。在 onSuccess
方法中,你可以获取并显示天气信息。
package com.example.weather;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
// 导入必要的包
import com.qweather.sdk.bean.geo.GeoBean;
import com.qweather.sdk.bean.weather.WeatherDailyBean;
import com.qweather.sdk.bean.weather.WeatherNowBean;
import com.qweather.sdk.view.HeConfig;
import com.qweather.sdk.view.QWeather;
import java.util.List;
public class MainActivity extends AppCompatActivity {
// 声明UI元素,声明用户界面控件和变量
Button btnsearch;
EditText etCityName;
TextView tqshow, tqcn, tqwd, tqrq, tqyq;
TextView tqHumidity;
// 声明天气信息变量
String cityname, cityid, citytq, cityrq, citywd, citycs, cityhd, cityyq;
// 创建一个Handler,用于在子线程中更新UI,声明处理器,用于在子线程获取到天气数据后更新用户界面
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
// 处理从子线程发送过来的消息
if (msg.what == 1) {
// 更新UI元素显示天气信息,接收子线程发送的消息,更新用户界面
tqshow.setText("实时天气:" + msg.getData().getString("tq"));
tqcn.setText("城市名称:" + msg.getData().getString("cs"));
tqwd.setText("城市温度:" + msg.getData().getString("wd"));
tqrq.setText("现在日期:" + msg.getData().getString("rq"));
tqHumidity.setText("今日湿度:" + msg.getData().getString("hd"));
tqyq.setText("天气压强" + msg.getData().getString("yq"));
}
}
};
// 定义Activity的onCreate方法,Activity的onCreate方法,在Activity创建时会被调用
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 设置Activity的布局
setContentView(R.layout.activity_main);
// 通过id查找UI元素,通过ID找到用户界面控件
btnsearch = (Button) findViewById(R.id.btn_search);
etCityName = (EditText) findViewById(R.id.ed_CityName);
tqshow = (TextView) findViewById(R.id.tq_weather);
tqcn = (TextView) findViewById(R.id.tq_cityname);
tqwd = (TextView) findViewById(R.id.tq_tem);
tqrq = (TextView) findViewById(R.id.tq_date);
tqHumidity = (TextView) findViewById(R.id.tq_humidity);
tqyq = (TextView) findViewById(R.id.tq_yq);
// 初始化HeConfig,初始化和风天气的配置
HeConfig.init("HE2305080849521023", "465e004f3c45458a8f749ba0c801cd40");
// 切换到开发者服务
HeConfig.switchToDevService();
// 为搜索按钮设置点击事件监听器,设置搜索按钮的点击事件
btnsearch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 从EditText中获取城市名
cityname = etCityName.getText().toString().trim();
// 在新线程中获取天气信息
new Thread(new Runnable() {
@Override
public void run() {
// 通过城市名获取城市ID
QWeather.getGeoCityLookup(MainActivity.this, cityname, new QWeather.OnResultGeoListener() {
@Override
public void onError(Throwable throwable) {
// 处理错误
}
@Override
public void onSuccess(GeoBean geoBean) {
// 获取城```java
// 城市信息并保存
List lb =geoBean.getLocationBean();
citycs=lb.get(0).getName();
cityid=lb.get(0).getId();
}
});
try{
// 线程休眠一秒,确保获取到城市ID
Thread.sleep(1000);
} catch (InterruptedException e){
// 处理异常
throw new RuntimeException(e);
}
// 通过城市ID获取未来三天的天气预报
QWeather.getWeather3D(MainActivity.this, cityid, new QWeather.OnResultWeatherDailyListener() {
@Override
public void onError(Throwable throwable) {
// 处理错误
}
@Override
public void onSuccess(WeatherDailyBean weatherDailyBean) {
// 获取并保存预报日期
List db =weatherDailyBean.getDaily();
cityrq=db.get(0).getFxDate();
}
});
// 通过城市ID获取实时天气信息
QWeather.getWeatherNow(MainActivity.this, cityid, new QWeather.OnResultWeatherNowListener() {
@Override
public void onError(Throwable throwable) {
// 处理错误
}
@Override
public void onSuccess(WeatherNowBean weatherNowBean) {
// 获取并保存实时天气信息
WeatherNowBean.NowBaseBean nbb=weatherNowBean.getNow();
citytq = nbb.getText();
citywd = nbb.getTemp();
cityyq = nbb.getPressure(); // 获取大气压强
}
});
// 再次获取实时天气信息,此次获取的是湿度
QWeather.getWeatherNow(MainActivity.this, cityid, new QWeather.OnResultWeatherNowListener() {
@Override
public void onError(Throwable throwable) {
// 处理错误
}
@Override
public void onSuccess(WeatherNowBean weatherNowBean) {
// 获取并保存湿度信息
WeatherNowBean.NowBaseBean nbb=weatherNowBean.getNow();
cityhd=nbb.getHumidity();
}
});
try {
// 线程休眠一秒,确保获取到所有天气信息
Thread.sleep(1000);
} catch (InterruptedException e){
// 处理异常
throw new RuntimeException(e);
}
// 如果所有信息都获取到了,将信息发送给Handler,更新UI
if (cityname !=null&& citycs!= null && citytq!=null && citywd !=null){
Message message =Message.obtain();
message.what =1;
Bundle bundle =new Bundle();
bundle.putString("rq",cityrq);
bundle.putString("cs",citycs);
bundle.putString("tq",citytq);
bundle.putString("wd",citywd);
bundle.putString("hd",cityhd);
bundle.putString("yq",cityyq);
message.setData(bundle);
mHandler.sendMessage(message);
// 清空所有信息,为下一次查询做准备
cityrq=null;
citywd=null;
citycs=null;
citytq=null;
cityname=null;
cityhd=null;
cityyq=null;
}
}
}).start();
}
});
}
}
package com.example.weather;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.qweather.sdk.bean.geo.GeoBean;
import com.qweather.sdk.bean.weather.WeatherDailyBean;
import com.qweather.sdk.bean.weather.WeatherNowBean;
import com.qweather.sdk.view.HeConfig;
import com.qweather.sdk.view.QWeather;
import java.util.List;
这是Java编程的基本格式,首先定义包名,然后导入需要的类。在这个例子中,我们引入了安卓开发所需的类,以及QWeather提供的SDK。
public class MainActivity extends AppCompatActivity {
定义了一个名为MainActivity的类,这个类继承自AppCompatActivity,这是安卓应用中常见的Activity基类。
Button btnsearch;
EditText etCityName;
TextView tqshow,tqcn,tqwd,tqrq,tqyq;
TextView tqHumidity;
String cityname,cityid,citytq,cityrq,citywd,citycs,cityhd,cityyq;
定义了界面上的一些控件和变量。btnsearch是搜索按钮,etCityName是输入城市名的输入框,其余的都是显示信息的文本视图。然后定义了一些字符串变量,用于存储城市名、城市id、天气等信息。
private Handler mHandler= new Handler(){
public void handleMessage(Message msg){
super.handleMessage(msg);
if(msg.what==1){
tqshow.setText("实时天气:"+msg.getData().getString("tq"));
tqcn.setText("城市名称:"+msg.getData().getString("cs"));
tqwd.setText("城市温度:"+msg.getData().getString("wd"));
tqrq.setText("现在日期:"+msg.getData().getString("rq"));
tqHumidity.setText("今日湿度:"+msg.getData().getString("hd"));
tqyq.setText("天气压强"+msg.getData().getString("yq"));
}
}
};
这里定义了一个Handler,用于在后台线程获取到数据后,将数据发送回主线程并更新UI。在安卓中,不能在后台线程直接更新UI,需要通过Handler来实现。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
这是Activity的onCreate方法,是安卓生命周期中的一个阶段。在这个阶段,我们设置了Activity的布局,并初始化了一些控件。
btnsearch=(Button)findViewById(R.id.btn_search);
etCityName=(EditText)findViewById(R.id.ed_CityName);
tqshow=(TextView)findViewById(R.id.tq_weather);
tqcn=(TextView)findViewById(R.id.tq_cityname);
tqwd=(TextView)findViewById(R.id.tq_tem);
tqrq=(TextView)findViewById(R.id.tq_date);
tqHumidity=(TextView)findViewById(R.id.tq_humidity);
tqyq=(TextView)findViewById(R.id.tq_yq);
这里通过findViewById方法获取布局中的控件。
这里初始化了和风天气的SDK,其中的参数应该是你自己在和风天气网站上申请的公钥和私钥。然后切换到开发者服务,这是和风天气为开发者提供的免费服务。
```java
btnsearch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
cityname=etCityName.getText().toString().trim();
new Thread(new Runnable() {
@Override
public void run() {
设置搜索按钮的点击事件。当用户点击搜索按钮时,会获取输入框中的城市名,并启动一个新的线程来获取天气信息。因为网络请求是耗时操作,需要在后台线程中进行。
QWeather.getGeoCityLookup(MainActivity.this, cityname, new QWeather.OnResultGeoListener() {
@Override
public void onError(Throwable throwable) {
}
@Override
public void onSuccess(GeoBean geoBean) {
List lb =geoBean.getLocationBean();
citycs=lb.get(0).getName();
cityid=lb.get(0).getId();
}
});
这里调用了QWeather的getGeoCityLookup方法,根据城市名获取城市的id。因为和风天气的API需要通过城市id来获取天气信息。
try{
Thread.sleep(1000);
} catch (InterruptedException e){
throw new RuntimeException(e);
}
这里让线程休眠一秒,是为了等待网络请求返回结果。在实际开发中,这种方式不是很好,应该使用异步回调的方式来处理。
QWeather.getWeather3D(MainActivity.this, cityid, new QWeather.OnResultWeatherDailyListener() {
@Override
public void onError(Throwable throwable) {
}
@Override
public void onSuccess(WeatherDailyBean weatherDailyBean) {
List db =weatherDailyBean.getDaily();
cityrq=db.get(0).getFxDate();
}
});
这里调用了QWeather的getWeather3D方法,获取城市的每日天气预报。我们只取了预报日期。
QWeather.getWeatherNow(MainActivity.this, cityid, new QWeather.OnResultWeatherNowListener() {
@Override
public void onError(Throwable throwable) {
}
@Override
public void onSuccess(WeatherNowBean weatherNowBean) {
WeatherNowBean.NowBaseBean nbb=weatherNowBean.getNow();
citytq = nbb.getText();
citywd = nbb.getTemp();
cityyq = nbb.getPressure(); // 获取大气压强
}
});
这里调用了QWeather的getWeatherNow方法,获取城市的实时天气。我们取了天气文本、温度和大气压强。
QWeather.getWeatherNow(MainActivity.this, cityid, new QWeather.OnResultWeatherNowListener() {
@Override
public void onError(Throwable throwable) {
}
@Override
public void onSuccess(WeatherNowBean weatherNowBean) {
WeatherNowBean.NowBaseBean nbb=weatherNowBean.getNow();
cityhd = nbb.getHumidity(); // 获取湿度
}
});
再次调用QWeather的getWeatherNow方法,这次我们获取的是湿度。
try{
Thread.sleep(1000);
} catch (InterruptedException e){
throw new RuntimeException(e);
}
和之前一样,这里让线程休眠一秒,等待网络请求返回结果。
Message msg=new Message();
msg.what=1;
Bundle bundle=new Bundle();
bundle.putString("tq",citytq);
bundle.putString("cs",citycs);
bundle.putString("wd",citywd);
bundle.putString("rq",cityrq);
bundle.putString("hd",cityhd);
bundle.putString("yq",cityyq);
msg.setData(bundle);
mHandler.sendMessage(msg);
}
}).start();
}
});
}
}
最后,创建一个Message对象,将获取到的天气信息放入Message中,并通过Handler发送到主线程,更新UI。