import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.example.jnsyq.data.Sheng;
import com.example.jnsyq.data.Shi;
import com.example.jnsyq.data.Xian;
import org.jetbrains.annotations.NotNull;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity {
//定义3个级别
private static final int level_sheng = 0;
private static final int level_shi = 1;
private static final int level_xian = 2;
private int level = 0; //变化
//声明ListView
private ListView listView;
//声明省市县对应的列表
private List<Sheng> ShengList = new ArrayList<>();
private List<Shi> ShiList = new ArrayList<>();
private List<Xian> XianList = new ArrayList<>();
//声明省市县名称列表:数据源
private List<String> nameList = new ArrayList<>();
//创建适配器
private ArrayAdapter<String> adapter;
//全局的选中的省市县城市
private Sheng s;
private Shi shi;
//消息处理
//【内存泄漏】
Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what)
{
case 0:
//通知ListView数据更改
adapter.notifyDataSetChanged();
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//调用初始化方法
initListView();
//联网初始化省信息
getSheng();
}
/**
* 新建初始化ListView方法
*/
private void initListView() {
//初始化ListView
//在布局文件中找到该ListView
listView = (ListView) findViewById(R.id.listview);
//数据源、ListView、适配器实现绑定,数据和显示实时更新
//初始化适配器,将适配器和数据源绑定在一起
//this:上下文
//simple_list_item_1:简单的布局
//nameList:设置数据源
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, nameList);
//绑定ListView和适配器,ListView设置适配器
listView.setAdapter(adapter);
//设置点击操作
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//通过点击的位置获取到点击的对象
//如果当前级别是省级,那么获取省级对象,获取市级对象
if (level == level_sheng) {
level = 1;
s = ShengList.get(position);
Log.d("MainActivity", "onItemClick: " + s.getName());
getShi();
} else if (level == level_shi) {
shi = ShiList.get(position);
Log.d("MainActivity", "onItemClick: " + shi.getName());
}
}
});
}
/**
* 获取省一级的城市列表
*/
private void getSheng() {
//定义url,接口
String url = "http://guolin.tech/api/china";
//1.创建okhttp客户端
OkHttpClient client = new OkHttpClient();
//2.创建请求,构建请求参数
Request request = new Request.Builder().url(url).build();
//3.进行网络访问
//new Callback():回调接口(线程)
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
// e.printStackTrace();
//如果访问失败,输出失败信息
Log.d("MainActivity", "onFailure: 网络访问失败");
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
//将网络相应信息转换成字符串型
//该操作只能执行一次
String data = response.body().string();
// String data1 = response.body().string(); //错误
//输出日志信息
Log.d("MainActivity", "onResponse: " + data);
//解析数据,并生成数据类
try {
//将json字符串转换为json数组
JSONArray shengs = new JSONArray(data); //需处理JSONException,未处理异常【用try/catch包括起来】
//遍历json数字,读取所有的json对象
for (int i = 0; i < shengs.length(); i++) {
//从json数组中读取json对象
JSONObject shengObject = shengs.getJSONObject(i);
//创建省一级城市对象
Sheng s = new Sheng();
//设置对应的值
s.setId(shengObject.getInt("id"));
s.setName(shengObject.getString("name"));
//将省对象添加到列表中
ShengList.add(s);
//将省名称添加到名称列表
nameList.add(s.getName());
//发送消息到Loop
//通过handleMessage进行消息处理
Message msg = new Message();
msg.what = 0; //消息id号
handler.sendMessage(msg);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
/**
* 获取市级的城市列表
* 法1:方法中缺少变量,可以直接传递进来
*/
// private void getShi(int shengid) {
// //url中省级id号是变量,url不完整
// String url = "http://guolin.tech/api/china/" + shengid;
// }
/**
* 获取市级的城市列表
* 法2:①将被选中的省级城市定义为全部变量
* ②在getShi方法中进行读取
*/
private void getShi() {
//定义url,接口
String url = "http://guolin.tech/api/china/" + s.getId();
//1.创建okhttp客户端
OkHttpClient client = new OkHttpClient();
//2.创建请求,构建请求参数
Request request = new Request.Builder().url(url).build();
//3.进行网络访问
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
String data = response.body().string();
try {
//清空nameList,准备存放数据
nameList.clear();
JSONArray jsonArray = new JSONArray(data);
for (int i = 0; i < jsonArray.length(); i++) {
//获取第i个位置的json对象
JSONObject jsonObject = jsonArray.getJSONObject(i);
Shi shi = new Shi();
shi.setId(jsonObject.getInt("id"));
shi.setName(jsonObject.getString("name"));
ShiList.add(shi);
nameList.add(shi.getName());
Message msg = new Message();
msg.what = 0;
handler.sendMessage(msg);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
}
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.example.jnsyq.data.Sheng;
import com.example.jnsyq.data.Shi;
import com.example.jnsyq.data.Xian;
import org.jetbrains.annotations.NotNull;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity {
//定义3个级别
private static final int level_sheng = 0;
private static final int level_shi = 1;
private static final int level_xian = 2;
private int level = 0; //变化
//声明ListView
private ListView listView;
//声明省市县对应的列表
private List<Sheng> ShengList = new ArrayList<>();
private List<Shi> ShiList = new ArrayList<>();
private List<Xian> XianList = new ArrayList<>();
//声明省市县名称列表:数据源
private List<String> nameList = new ArrayList<>();
//创建适配器
private ArrayAdapter<String> adapter;
//全局的选中的省市县城市
private Sheng s;
private Shi shi;
private Xian xian;
//消息处理
//【内存泄漏】
Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what)
{
case 0:
//通知ListView数据更改
adapter.notifyDataSetChanged();
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//调用初始化方法
initListView();
//联网初始化省信息
getSheng();
}
/**
* 新建初始化ListView方法
*/
private void initListView() {
//初始化ListView
//在布局文件中找到该ListView
listView = (ListView) findViewById(R.id.listview);
//数据源、ListView、适配器实现绑定,数据和显示实时更新
//初始化适配器,将适配器和数据源绑定在一起
//this:上下文
//simple_list_item_1:简单的布局
//nameList:设置数据源
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, nameList);
//绑定ListView和适配器,ListView设置适配器
listView.setAdapter(adapter);
//设置点击操作
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//通过点击的位置获取到点击的对象
//如果当前级别是省级,那么获取省级对象,获取市级对象
if (level == level_sheng) {
level = level_shi;
s = ShengList.get(position);
Log.d("MainActivity", "onItemClick: " + s.getName());
getShi();
} else if (level == level_shi) {
level = level_xian;
shi = ShiList.get(position);
Log.d("MainActivity", "onItemClick: " + shi.getName());
getXian();
} else if (level == level_xian) {
xian = XianList.get(position);
Log.d("MainActivity", "onItemClick: " + xian.getName());
}
}
});
}
/**
* 获取省一级的城市列表
*/
private void getSheng() {
//定义url,接口
String url = "http://guolin.tech/api/china";
//1.创建okhttp客户端
OkHttpClient client = new OkHttpClient();
//2.创建请求,构建请求参数
Request request = new Request.Builder().url(url).build();
//3.进行网络访问
//new Callback():回调接口(线程)
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
// e.printStackTrace();
//如果访问失败,输出失败信息
Log.d("MainActivity", "onFailure: 网络访问失败");
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
//将网络相应信息转换成字符串型
//该操作只能执行一次
String data = response.body().string();
// String data1 = response.body().string(); //错误
//输出日志信息
Log.d("MainActivity", "onResponse: " + data);
//解析数据,并生成数据类
try {
//将json字符串转换为json数组
JSONArray shengs = new JSONArray(data); //需处理JSONException,未处理异常【用try/catch包括起来】
//遍历json数字,读取所有的json对象
for (int i = 0; i < shengs.length(); i++) {
//从json数组中读取json对象
JSONObject shengObject = shengs.getJSONObject(i);
//创建省一级城市对象
Sheng s = new Sheng();
//设置对应的值
s.setId(shengObject.getInt("id"));
s.setName(shengObject.getString("name"));
//将省对象添加到列表中
ShengList.add(s);
//将省名称添加到名称列表
nameList.add(s.getName());
//发送消息到Loop
//通过handleMessage进行消息处理
Message msg = new Message();
msg.what = 0; //消息id号
handler.sendMessage(msg);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
/**
* 获取市级的城市列表
* 法1:方法中缺少变量,可以直接传递进来
*/
// private void getShi(int shengid) {
// //url中省级id号是变量,url不完整
// String url = "http://guolin.tech/api/china/" + shengid;
// }
/**
* 获取市级的城市列表
* 法2:①将被选中的省级城市定义为全部变量
* ②在getShi方法中进行读取
*/
private void getShi() {
//定义url,接口
String url = "http://guolin.tech/api/china/" + s.getId();
//1.创建okhttp客户端
OkHttpClient client = new OkHttpClient();
//2.创建请求,构建请求参数
Request request = new Request.Builder().url(url).build();
//3.进行网络访问
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
String data = response.body().string();
try {
//清空nameList,准备存放数据
nameList.clear();
JSONArray jsonArray = new JSONArray(data);
for (int i = 0; i < jsonArray.length(); i++) {
//获取第i个位置的json对象
JSONObject jsonObject = jsonArray.getJSONObject(i);
Shi shi = new Shi();
shi.setId(jsonObject.getInt("id"));
shi.setName(jsonObject.getString("name"));
ShiList.add(shi);
nameList.add(shi.getName());
Message msg = new Message();
msg.what = 0;
handler.sendMessage(msg);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
/**
* 获取县级的城市列表
*/
private void getXian() {
//定义url,接口
String url = "http://guolin.tech/api/china/" + s.getId() + "/" + shi.getId();
//1.创建okhttp客户端
OkHttpClient client = new OkHttpClient();
//2.创建请求,构建请求参数
Request request = new Request.Builder().url(url).build();
//3.进行网络访问
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
String data = response.body().string();
try {
//清空nameList,准备存放数据
nameList.clear();
JSONArray jsonArray = new JSONArray(data);
for (int i = 0; i < jsonArray.length(); i++) {
//获取第i个位置的json对象
JSONObject jsonObject = jsonArray.getJSONObject(i);
Xian xian = new Xian();
xian.setId(jsonObject.getInt("id"));
xian.setName(jsonObject.getString("name"));
xian.setWeather_id(jsonObject.getString("weather_id"));
XianList.add(xian);
nameList.add(xian.getName());
Message msg = new Message();
msg.what = 0;
handler.sendMessage(msg);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
}
选错了省市县以后退回上一级别选择
注:通过重写actionbar实现返回的功能
在res/values
中,修改styles.xml
代码,效果如下:
在res/drawable
中图片,插入修改xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary">
<Button
android:id="@+id/back"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:background="@drawable/ic_back"
android:layout_alignParentStart="true" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textSize="20sp"
android:textColor="#fff"
tools:text="山东"/>
RelativeLayout>
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
LinearLayout>
声明控件
省级 -> 市级 -> 网络访问 需要
市级 -> 省级 -> 网络访问 不需要
修改代码,截图:
注:清空
MainActivity.java中网络访问省市县三步走相同,故可以提取出来,新建工具类,方法调用
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import com.example.jnsyq.data.Sheng;
import com.example.jnsyq.data.Shi;
import com.example.jnsyq.data.Xian;
import org.jetbrains.annotations.NotNull;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity {
//定义3个级别
private static final int level_sheng = 0;
private static final int level_shi = 1;
private static final int level_xian = 2;
private int level = 0; //变化
//声明控件
private ListView listView; //ListView
private Button buttonBack; //Button
private TextView title; //TextView
//声明省市县对应的列表
private List<Sheng> ShengList = new ArrayList<>();
private List<Shi> ShiList = new ArrayList<>();
private List<Xian> XianList = new ArrayList<>();
//声明省市县名称列表:数据源
private List<String> nameList = new ArrayList<>();
//创建适配器
private ArrayAdapter<String> adapter;
//全局的选中的省市县城市
private Sheng s;
private Shi shi;
private Xian xian;
//消息处理
//【内存泄漏】
Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what)
{
case 0:
//通知ListView数据更改
adapter.notifyDataSetChanged();
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonBack = findViewById(R.id.back);
//button添加点击操作
buttonBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//点击操作,首先判断当前级别
//如果当前处于县级,返回市级
if (level == level_xian) {
level = level_shi;
//显示上一级省名称
title.setText(s.getName());
//法1:重新获取一次市级列表
// getShi();
//法2:直接遍历市级列表
//将所有的市级名称填到homelist中
nameList.clear();
//ShiList.for回车,自动出
for (Shi shi1 : ShiList) {
nameList.add(shi1.getName());
adapter.notifyDataSetChanged();
}
} else if (level == level_shi) {
level = level_sheng;
title.setText("中国");
for (Sheng sheng1 : ShengList) {
nameList.add(sheng1.getName());
adapter.notifyDataSetChanged();
}
}
}
});
title = findViewById(R.id.title);
title.setText("中国");
//调用初始化方法
initListView();
//联网初始化省信息
getSheng();
}
/**
* 新建初始化ListView方法
*/
private void initListView() {
//初始化ListView
//在布局文件中找到该ListView
listView = (ListView) findViewById(R.id.listview);
//数据源、ListView、适配器实现绑定,数据和显示实时更新
//初始化适配器,将适配器和数据源绑定在一起
//this:上下文
//simple_list_item_1:简单的布局
//nameList:设置数据源
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, nameList);
//绑定ListView和适配器,ListView设置适配器
listView.setAdapter(adapter);
//设置点击操作
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//通过点击的位置获取到点击的对象
//如果当前级别是省级,那么获取省级对象,获取市级对象
if (level == level_sheng) {
level = level_shi;
s = ShengList.get(position);
//点击的哪个省,那么title显示该省名称
title.setText(s.getName());
Log.d("MainActivity", "onItemClick: " + s.getName());
getShi();
} else if (level == level_shi) {
level = level_xian;
shi = ShiList.get(position);
//点击的哪个市,那么title显示该市名称
title.setText(shi.getName());
Log.d("MainActivity", "onItemClick: " + shi.getName());
getXian();
} else if (level == level_xian) {
xian = XianList.get(position);
Log.d("MainActivity", "onItemClick: " + xian.getName());
}
}
});
}
/**
* 获取省一级的城市列表
*/
private void getSheng() {
//定义url,接口
String url = "http://guolin.tech/api/china";
//1.创建okhttp客户端
OkHttpClient client = new OkHttpClient();
//2.创建请求,构建请求参数
Request request = new Request.Builder().url(url).build();
//3.进行网络访问
//new Callback():回调接口(线程)
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
// e.printStackTrace();
//如果访问失败,输出失败信息
Log.d("MainActivity", "onFailure: 网络访问失败");
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
//将网络相应信息转换成字符串型
//该操作只能执行一次
String data = response.body().string();
// String data1 = response.body().string(); //错误
//输出日志信息
Log.d("MainActivity", "onResponse: " + data);
//解析数据,并生成数据类
try {
nameList.clear();
ShengList.clear();
//将json字符串转换为json数组
JSONArray shengs = new JSONArray(data); //需处理JSONException,未处理异常【用try/catch包括起来】
//遍历json数字,读取所有的json对象
for (int i = 0; i < shengs.length(); i++) {
//从json数组中读取json对象
JSONObject shengObject = shengs.getJSONObject(i);
//创建省一级城市对象
Sheng s = new Sheng();
//设置对应的值
s.setId(shengObject.getInt("id"));
s.setName(shengObject.getString("name"));
//将省对象添加到列表中
ShengList.add(s);
//将省名称添加到名称列表
nameList.add(s.getName());
//发送消息到Loop
//通过handleMessage进行消息处理
Message msg = new Message();
msg.what = 0; //消息id号
handler.sendMessage(msg);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
/**
* 获取市级的城市列表
* 法1:方法中缺少变量,可以直接传递进来
*/
// private void getShi(int shengid) {
// //url中省级id号是变量,url不完整
// String url = "http://guolin.tech/api/china/" + shengid;
// }
/**
* 获取市级的城市列表
* 法2:①将被选中的省级城市定义为全部变量
* ②在getShi方法中进行读取
*/
private void getShi() {
//定义url,接口
String url = "http://guolin.tech/api/china/" + s.getId();
//1.创建okhttp客户端
OkHttpClient client = new OkHttpClient();
//2.创建请求,构建请求参数
Request request = new Request.Builder().url(url).build();
//3.进行网络访问
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
String data = response.body().string();
try {
//清空nameList,准备存放数据
nameList.clear();
ShiList.clear();
JSONArray jsonArray = new JSONArray(data);
for (int i = 0; i < jsonArray.length(); i++) {
//获取第i个位置的json对象
JSONObject jsonObject = jsonArray.getJSONObject(i);
Shi shi = new Shi();
shi.setId(jsonObject.getInt("id"));
shi.setName(jsonObject.getString("name"));
ShiList.add(shi);
nameList.add(shi.getName());
Message msg = new Message();
msg.what = 0;
handler.sendMessage(msg);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
/**
* 获取县级的城市列表
*/
private void getXian() {
//定义url,接口
String url = "http://guolin.tech/api/china/" + s.getId() + "/" + shi.getId();
//1.创建okhttp客户端
OkHttpClient client = new OkHttpClient();
//2.创建请求,构建请求参数
Request request = new Request.Builder().url(url).build();
//3.进行网络访问
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
String data = response.body().string();
try {
//清空nameList,准备存放数据
nameList.clear();
XianList.clear();
JSONArray jsonArray = new JSONArray(data);
for (int i = 0; i < jsonArray.length(); i++) {
//获取第i个位置的json对象
JSONObject jsonObject = jsonArray.getJSONObject(i);
Xian xian = new Xian();
xian.setId(jsonObject.getInt("id"));
xian.setName(jsonObject.getString("name"));
xian.setWeather_id(jsonObject.getString("weather_id"));
XianList.add(xian);
nameList.add(xian.getName());
Message msg = new Message();
msg.what = 0;
handler.sendMessage(msg);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
}
import okhttp3.OkHttpClient;
import okhttp3.Request;
/**
* 工具类
*/
public class HttpUtils {
/**
* 网络访问三步走
* #注意:static 静态方法,只和类有关系,和对象无关
* @param url 要访问的网络地址
* @param callback 回调
*/
public static void sendOkhttpRequest(String url, okhttp3.Callback callback) {
//1.创建okhttp客户端
OkHttpClient client = new OkHttpClient();
//2.创建请求,拼接请求参数
Request request = new Request.Builder().url(url).build();
//3.进行网络访问
//new Callback():回调接口(线程)
client.newCall(request).enqueue(callback);
}
}
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import com.example.jnsyq.data.Sheng;
import com.example.jnsyq.data.Shi;
import com.example.jnsyq.data.Xian;
import com.example.jnsyq.utils.HttpUtils;
import org.jetbrains.annotations.NotNull;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity {
//定义3个级别
/* static:静态;final:常量 */
private static final int level_sheng = 0;
private static final int level_shi = 1;
private static final int level_xian = 2;
private int level = 0; //变化
//声明控件
private ListView listView; //ListView
private Button buttonBack; //Button
private TextView title; //TextView
//声明省市县对应的列表
private List<Sheng> ShengList = new ArrayList<>();
private List<Shi> ShiList = new ArrayList<>();
private List<Xian> XianList = new ArrayList<>();
//声明省市县名称列表:数据源
private List<String> nameList = new ArrayList<>();
//创建适配器
private ArrayAdapter<String> adapter;
//全局的选中的省市县城市
private Sheng s;
private Shi shi;
private Xian xian;
//消息处理loop
//【内存泄漏】
Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what)
{
case 0:
//通知ListView数据更改
adapter.notifyDataSetChanged();
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonBack = findViewById(R.id.back);
//button添加点击操作
buttonBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//点击操作,首先判断当前级别
//如果当前处于县级,返回市级
if (level == level_xian) {
level = level_shi;
//显示上一级省名称
title.setText(s.getName());
//法1:重新获取一次市级列表
// getShi();
//法2:直接遍历市级列表
//将所有的市级名称填到homelist中
nameList.clear();
//ShiList.for回车,自动出
for (Shi shi1 : ShiList) {
nameList.add(shi1.getName());
adapter.notifyDataSetChanged();
}
} else if (level == level_shi) {
level = level_sheng;
title.setText("中国");
nameList.clear();
for (Sheng sheng1 : ShengList) {
nameList.add(sheng1.getName());
adapter.notifyDataSetChanged();
}
}
}
});
title = findViewById(R.id.title);
title.setText("中国");
//调用初始化方法
initListView();
//联网初始化省信息
getSheng();
}
/**
* 新建初始化ListView方法
*/
private void initListView() {
//初始化ListView
//在布局文件中找到该ListView
listView = (ListView) findViewById(R.id.listview);
//数据源、ListView、适配器实现绑定,数据和显示实时更新
//初始化适配器,将适配器和数据源绑定在一起
//this:上下文
//simple_list_item_1:简单的布局
//nameList:设置数据源
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, nameList);
//绑定ListView和适配器,ListView设置适配器
listView.setAdapter(adapter);
//设置点击操作
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//通过点击的位置获取到点击的对象
//如果当前级别是省级,那么获取省级对象,获取市级对象
if (level == level_sheng) {
level = level_shi;
s = ShengList.get(position);
//点击的哪个省,那么title显示该省名称
title.setText(s.getName());
Log.d("MainActivity", "onItemClick: " + s.getName());
getShi();
} else if (level == level_shi) {
level = level_xian;
shi = ShiList.get(position);
//点击的哪个市,那么title显示该市名称
title.setText(shi.getName());
Log.d("MainActivity", "onItemClick: " + shi.getName());
getXian();
} else if (level == level_xian) {
xian = XianList.get(position);
Log.d("MainActivity", "onItemClick: " + xian.getName());
//TODO:跳转到天气显示界面
}
}
});
}
/**
* 获取省一级的城市列表
*/
private void getSheng() {
//定义url,接口
String url = "http://guolin.tech/api/china";
//#注意:正常情况下,先创建对象,再调用方法
// HttpUtil httpUtil = new HttpUtils();
// httpUtil.sendOkhttpRequest();
//每次网络访问时,直接调用sendOkhttpRequest即可
HttpUtils.sendOkhttpRequest(url, new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
// e.printStackTrace();
//如果访问失败,输出失败信息
Log.d("MainActivity", "onFailure: 网络访问失败");
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
//将网络相应信息转换成字符串型
//该操作只能执行一次
String data = response.body().string();
// String data1 = response.body().string(); //错误
//输出日志信息
Log.d("MainActivity", "onResponse: " + data);
//解析数据,并生成数据类
try {
nameList.clear();
ShengList.clear();
//将json字符串转换为json数组
JSONArray shengs = new JSONArray(data); //需处理JSONException,未处理异常【用try/catch包括起来】
//遍历json数字,读取所有的json对象
for (int i = 0; i < shengs.length(); i++) {
//从json数组中读取json对象
JSONObject shengObject = shengs.getJSONObject(i);
//创建省一级城市对象
Sheng s = new Sheng();
//设置对应的值
s.setId(shengObject.getInt("id"));
s.setName(shengObject.getString("name"));
//将省对象添加到列表中
ShengList.add(s);
//将省名称添加到名称列表
nameList.add(s.getName());
//发送消息到Loop
//通过handleMessage进行消息处理
Message msg = new Message();
msg.what = 0; //消息id号
handler.sendMessage(msg);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
/**
* 获取市级的城市列表
* 法1:方法中缺少变量,可以直接传递进来
*/
// private void getShi(int shengid) {
// //url中省级id号是变量,url不完整
// String url = "http://guolin.tech/api/china/" + shengid;
// }
/**
* 获取市级的城市列表
* 法2:①将被选中的省级城市定义为全部变量
* ②在getShi方法中进行读取
*/
private void getShi() {
//定义url,接口
String url = "http://guolin.tech/api/china/" + s.getId();
HttpUtils.sendOkhttpRequest(url, new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
String data = response.body().string();
try {
//清空nameList,准备存放数据
nameList.clear();
ShiList.clear();
JSONArray jsonArray = new JSONArray(data);
for (int i = 0; i < jsonArray.length(); i++) {
//获取第i个位置的json对象
JSONObject jsonObject = jsonArray.getJSONObject(i);
Shi shi = new Shi();
shi.setId(jsonObject.getInt("id"));
shi.setName(jsonObject.getString("name"));
ShiList.add(shi);
nameList.add(shi.getName());
Message msg = new Message();
msg.what = 0;
handler.sendMessage(msg);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
/**
* 获取县级的城市列表
*/
private void getXian() {
//定义url,接口
String url = "http://guolin.tech/api/china/" + s.getId() + "/" + shi.getId();
HttpUtils.sendOkhttpRequest(url, new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
String data = response.body().string();
try {
//清空nameList,准备存放数据
nameList.clear();
XianList.clear();
JSONArray jsonArray = new JSONArray(data);
for (int i = 0; i < jsonArray.length(); i++) {
//获取第i个位置的json对象
JSONObject jsonObject = jsonArray.getJSONObject(i);
Xian xian = new Xian();
xian.setId(jsonObject.getInt("id"));
xian.setName(jsonObject.getString("name"));
xian.setWeather_id(jsonObject.getString("weather_id"));
XianList.add(xian);
nameList.add(xian.getName());
Message msg = new Message();
msg.what = 0;
handler.sendMessage(msg);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
}
api:http://guolin.tech/api/weather?cityid=CN101190401
创建数据类:使用gsonformat创建实时天气的数据类
Generate...
GsonFormat
https://www.tianqiapi.com/api?version=v6&appid=55233412&appsecret=2Mm5xcPA&cityid=CN101121101
,复制该网址数据,点击Format
OK
package com.example.jnsyq.data;
/**
* 实时天气数据类
*/
public class inTimeWeather {
/**
* cityid : 101250101
* date : 2020-08-14
* week : 星期五
* update_time : 2020-08-14 19:23:53
* city : 长沙
* cityEn : changsha
* country : 中国
* countryEn : China
* wea : 晴
* wea_img : qing
* tem : 33
* tem1 : 34
* tem2 : 27
* win : 南风
* win_speed : 2级
* win_meter : 小于12km/h
* humidity : 54%
* visibility : 35km
* pressure : 1000
* air : 30
* air_pm25 : 30
* air_level : 优
* air_tips : 空气很好,可以外出活动,呼吸新鲜空气,拥抱大自然!
* alarm : {"alarm_type":"","alarm_level":"","alarm_content":""}
*/
private String cityid;
private String date;
private String week;
private String update_time;
private String city;
private String cityEn;
private String country;
private String countryEn;
private String wea;
private String wea_img;
private String tem;
private String tem1;
private String tem2;
private String win;
private String win_speed;
private String win_meter;
private String humidity;
private String visibility;
private String pressure;
private String air;
private String air_pm25;
private String air_level;
private String air_tips;
private AlarmBean alarm;
public String getCityid() {
return cityid;
}
public void setCityid(String cityid) {
this.cityid = cityid;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getWeek() {
return week;
}
public void setWeek(String week) {
this.week = week;
}
public String getUpdate_time() {
return update_time;
}
public void setUpdate_time(String update_time) {
this.update_time = update_time;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCityEn() {
return cityEn;
}
public void setCityEn(String cityEn) {
this.cityEn = cityEn;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getCountryEn() {
return countryEn;
}
public void setCountryEn(String countryEn) {
this.countryEn = countryEn;
}
public String getWea() {
return wea;
}
public void setWea(String wea) {
this.wea = wea;
}
public String getWea_img() {
return wea_img;
}
public void setWea_img(String wea_img) {
this.wea_img = wea_img;
}
public String getTem() {
return tem;
}
public void setTem(String tem) {
this.tem = tem;
}
public String getTem1() {
return tem1;
}
public void setTem1(String tem1) {
this.tem1 = tem1;
}
public String getTem2() {
return tem2;
}
public void setTem2(String tem2) {
this.tem2 = tem2;
}
public String getWin() {
return win;
}
public void setWin(String win) {
this.win = win;
}
public String getWin_speed() {
return win_speed;
}
public void setWin_speed(String win_speed) {
this.win_speed = win_speed;
}
public String getWin_meter() {
return win_meter;
}
public void setWin_meter(String win_meter) {
this.win_meter = win_meter;
}
public String getHumidity() {
return humidity;
}
public void setHumidity(String humidity) {
this.humidity = humidity;
}
public String getVisibility() {
return visibility;
}
public void setVisibility(String visibility) {
this.visibility = visibility;
}
public String getPressure() {
return pressure;
}
public void setPressure(String pressure) {
this.pressure = pressure;
}
public String getAir() {
return air;
}
public void setAir(String air) {
this.air = air;
}
public String getAir_pm25() {
return air_pm25;
}
public void setAir_pm25(String air_pm25) {
this.air_pm25 = air_pm25;
}
public String getAir_level() {
return air_level;
}
public void setAir_level(String air_level) {
this.air_level = air_level;
}
public String getAir_tips() {
return air_tips;
}
public void setAir_tips(String air_tips) {
this.air_tips = air_tips;
}
public AlarmBean getAlarm() {
return alarm;
}
public void setAlarm(AlarmBean alarm) {
this.alarm = alarm;
}
public static class AlarmBean {
/**
* alarm_type :
* alarm_level :
* alarm_content :
*/
private String alarm_type;
private String alarm_level;
private String alarm_content;
public String getAlarm_type() {
return alarm_type;
}
public void setAlarm_type(String alarm_type) {
this.alarm_type = alarm_type;
}
public String getAlarm_level() {
return alarm_level;
}
public void setAlarm_level(String alarm_level) {
this.alarm_level = alarm_level;
}
public String getAlarm_content() {
return alarm_content;
}
public void setAlarm_content(String alarm_content) {
this.alarm_content = alarm_content;
}
}
}
注:{}表示json对象(Object)对应java里面的类,当使用AlarmBean的时候,set和get给的是AlarmBean
创建天气显示Activity
new Empty Activity
,修改名称,效果如下:
MainActivity.java中添加代码,如下:
添加gson包,在build.gradle
中添加代码,如下:
implementation "com.google.code.gson:gson:2.8.6"
注意:点击Sync Now
在WeatherActivity.java中,使用gson获取数据,代码如下:
activity_weather.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".WeatherActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary">
<TextView
android:id="@+id/title_city"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textSize="20sp"
android:textColor="#fff"
tools:text="济南"/>
<TextView
android:id="@+id/title_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:textSize="16sp"
android:textColor="#fff"
android:layout_marginRight="12dp"
android:layout_marginEnd="12dp"
tools:text="15:00" />
RelativeLayout>
LinearLayout>
注意:textSize设置大小时,尽量使用4的倍数
完善MainActivity.java【修改省级中变量的名称,jsonArray】和WeatherActivity.java,启动WeatherAcitivity的方法有两种
MainActivity.java
WeatherActivity.java
注意:该方法的作用为避免传输数据类型排错
MainActivity.java
WeatherActivity.java
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import com.example.jnsyq.data.Sheng;
import com.example.jnsyq.data.Shi;
import com.example.jnsyq.data.Xian;
import com.example.jnsyq.utils.HttpUtils;
import org.jetbrains.annotations.NotNull;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity {
//定义3个级别
/* static:静态;final:常量 */
private static final int level_sheng = 0;
private static final int level_shi = 1;
private static final int level_xian = 2;
private int level = 0; //变化
//声明控件
private ListView listView; //ListView
private Button buttonBack; //Button
private TextView title; //TextView
//声明省市县对应的列表
private List<Sheng> ShengList = new ArrayList<>();
private List<Shi> ShiList = new ArrayList<>();
private List<Xian> XianList = new ArrayList<>();
//声明省市县名称列表:数据源
private List<String> nameList = new ArrayList<>();
//创建适配器
private ArrayAdapter<String> adapter;
//全局的选中的省市县城市
private Sheng s;
private Shi shi;
private Xian xian;
//消息处理loop
//【内存泄漏】
Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what)
{
case 0:
//通知ListView数据更改
adapter.notifyDataSetChanged();
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonBack = findViewById(R.id.back);
//button添加点击操作
buttonBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//点击操作,首先判断当前级别
//如果当前处于县级,返回市级
if (level == level_xian) {
level = level_shi;
//显示上一级省名称
title.setText(s.getName());
//法1:重新获取一次市级列表
// getShi();
//法2:直接遍历市级列表
//将所有的市级名称填到homelist中
nameList.clear();
//ShiList.for回车,自动出
for (Shi shi1 : ShiList) {
nameList.add(shi1.getName());
adapter.notifyDataSetChanged();
}
} else if (level == level_shi) {
level = level_sheng;
title.setText("中国");
nameList.clear();
for (Sheng sheng1 : ShengList) {
nameList.add(sheng1.getName());
adapter.notifyDataSetChanged();
}
}
}
});
title = findViewById(R.id.title);
title.setText("中国");
//调用初始化方法
initListView();
//联网初始化省信息
getSheng();
}
/**
* 新建初始化ListView方法
*/
private void initListView() {
//初始化ListView
//在布局文件中找到该ListView
listView = (ListView) findViewById(R.id.listview);
//数据源、ListView、适配器实现绑定,数据和显示实时更新
//初始化适配器,将适配器和数据源绑定在一起
//this:上下文
//simple_list_item_1:简单的布局
//nameList:设置数据源
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, nameList);
//绑定ListView和适配器,ListView设置适配器
listView.setAdapter(adapter);
//设置点击操作
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//通过点击的位置获取到点击的对象
//如果当前级别是省级,那么获取省级对象,获取市级对象
if (level == level_sheng) {
level = level_shi;
s = ShengList.get(position);
//点击的哪个省,那么title显示该省名称
title.setText(s.getName());
Log.d("MainActivity", "onItemClick: " + s.getName());
getShi();
} else if (level == level_shi) {
level = level_xian;
shi = ShiList.get(position);
//点击的哪个市,那么title显示该市名称
title.setText(shi.getName());
Log.d("MainActivity", "onItemClick: " + shi.getName());
getXian();
} else if (level == level_xian) {
xian = XianList.get(position);
Log.d("MainActivity", "onItemClick: " + xian.getName());
//跳转到天气显示界面
//法1:
// Intent intent = new Intent(MainActivity.this, WeatherActivity.class);
// //传递cityid到下一个活动
// //将weatherid传递到下一个活动,作为cityid参数
// intent.putExtra("cityid", xian.getWeather_id());
// startActivity(intent);
//法2:启动活动的方法
WeatherActivity.actionStart(MainActivity.this, xian.getWeather_id());
}
}
});
}
/**
* 获取省一级的城市列表
*/
private void getSheng() {
//定义url,接口
String url = "http://guolin.tech/api/china";
//#注意:正常情况下,先创建对象,再调用方法
// HttpUtil httpUtil = new HttpUtils();
// httpUtil.sendOkhttpRequest();
//每次网络访问时,直接调用sendOkhttpRequest即可
HttpUtils.sendOkhttpRequest(url, new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
// e.printStackTrace();
//如果访问失败,输出失败信息
Log.d("MainActivity", "onFailure: 网络访问失败");
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
//将网络相应信息转换成字符串型
//该操作只能执行一次
String data = response.body().string();
// String data1 = response.body().string(); //错误
//输出日志信息
Log.d("MainActivity", "onResponse: " + data);
//解析数据,并生成数据类
try {
nameList.clear();
ShengList.clear();
//将json字符串转换为json数组
JSONArray jsonArray = new JSONArray(data); //需处理JSONException,未处理异常【用try/catch包括起来】
//遍历json数字,读取所有的json对象
for (int i = 0; i < jsonArray.length(); i++) {
//从json数组中读取json对象
JSONObject shengObject = jsonArray.getJSONObject(i);
//创建省一级城市对象
Sheng s = new Sheng();
//设置对应的值
s.setId(shengObject.getInt("id"));
s.setName(shengObject.getString("name"));
//将省对象添加到列表中
ShengList.add(s);
//将省名称添加到名称列表
nameList.add(s.getName());
//发送消息到Loop
//通过handleMessage进行消息处理
Message msg = new Message();
msg.what = 0; //消息id号
handler.sendMessage(msg);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
/**
* 获取市级的城市列表
* 法1:方法中缺少变量,可以直接传递进来
*/
// private void getShi(int shengid) {
// //url中省级id号是变量,url不完整
// String url = "http://guolin.tech/api/china/" + shengid;
// }
/**
* 获取市级的城市列表
* 法2:①将被选中的省级城市定义为全部变量
* ②在getShi方法中进行读取
*/
private void getShi() {
//定义url,接口
String url = "http://guolin.tech/api/china/" + s.getId();
HttpUtils.sendOkhttpRequest(url, new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
String data = response.body().string();
try {
//清空nameList,准备存放数据
nameList.clear();
ShiList.clear();
JSONArray jsonArray = new JSONArray(data);
for (int i = 0; i < jsonArray.length(); i++) {
//获取第i个位置的json对象
JSONObject jsonObject = jsonArray.getJSONObject(i);
Shi shi = new Shi();
shi.setId(jsonObject.getInt("id"));
shi.setName(jsonObject.getString("name"));
ShiList.add(shi);
nameList.add(shi.getName());
Message msg = new Message();
msg.what = 0;
handler.sendMessage(msg);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
/**
* 获取县级的城市列表
*/
private void getXian() {
//定义url,接口
String url = "http://guolin.tech/api/china/" + s.getId() + "/" + shi.getId();
HttpUtils.sendOkhttpRequest(url, new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
String data = response.body().string();
try {
//清空nameList,准备存放数据
nameList.clear();
XianList.clear();
JSONArray jsonArray = new JSONArray(data);
for (int i = 0; i < jsonArray.length(); i++) {
//获取第i个位置的json对象
JSONObject jsonObject = jsonArray.getJSONObject(i);
Xian xian = new Xian();
xian.setId(jsonObject.getInt("id"));
xian.setName(jsonObject.getString("name"));
xian.setWeather_id(jsonObject.getString("weather_id"));
XianList.add(xian);
nameList.add(xian.getName());
Message msg = new Message();
msg.what = 0;
handler.sendMessage(msg);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
}
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;
import com.example.jnsyq.data.InTimeWeather;
import com.example.jnsyq.utils.HttpUtils;
import com.google.gson.Gson;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
public class WeatherActivity extends AppCompatActivity {
private InTimeWeather inTimeWeather;
//声明控件
private TextView titleCity;
private TextView titleTime;
private String cityid; //private protected public(默认:protected)
Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what)
{
case 0:
//调用更新ui方法
updateUi();
break;
default:
break;
}
}
};
public static void actionStart(Context context, String cityid) {
Intent intent = new Intent(context, WeatherActivity.class);
intent.putExtra("cityid", cityid);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_weather);
//从布局中找到控件
titleCity = findViewById(R.id.title_city);
titleTime = findViewById(R.id.title_time);
//获取意图
Intent intent = getIntent();
//获取上一个活动传递劲来的数据
//初始化cityid的值
cityid = intent.getStringExtra("cityid");
//调用该方法获取数据
getWeatherInfo();
}
private void updateUi() {
//设置对应值
titleCity.setText(inTimeWeather.getCity());
titleTime.setText(inTimeWeather.getUpdate_time().split(" ")[1]);
}
/**
* 创建获取天气信息的方法
*/
private void getWeatherInfo() {
//通过调用api获取天气信息
//直接通过ip地址进行天气信息获取
//cityid:变量,由上一个活动传递进来
String url = "https://www.tianqiapi.com/api?version=v6&appid=55233412&appsecret=2Mm5xcPA&cityid=" + cityid.replace("CN", "");
//获取网络信息
//网络访问需要新开线程进行执行,不影响主线程
HttpUtils.sendOkhttpRequest(url, new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
//读取返回的数据
String data = response.body().string();
//新建gson对象
Gson gson = new Gson();
//解析json数据,初始化inTimeWeather
inTimeWeather = gson.fromJson(data, InTimeWeather.class); //json格式化
//初始化天气以后,发送消息,更新ui界面
Message msg = new Message();
msg.what = 0;
handler.sendMessage(msg);
}
});
}
}
cityid:101120901
注意:使用sharedpreferences,使得每次打开app的时候查看上次是否选择城市,如果选择了,无需再选
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import com.example.jnsyq.data.Sheng;
import com.example.jnsyq.data.Shi;
import com.example.jnsyq.data.Xian;
import com.example.jnsyq.utils.HttpUtils;
import org.jetbrains.annotations.NotNull;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity {
//定义3个级别
/* static:静态;final:常量 */
private static final int level_sheng = 0;
private static final int level_shi = 1;
private static final int level_xian = 2;
private int level = 0; //变化
//声明控件
private ListView listView; //ListView
private Button buttonBack; //Button
private TextView title; //TextView
//声明省市县对应的列表
private List<Sheng> ShengList = new ArrayList<>();
private List<Shi> ShiList = new ArrayList<>();
private List<Xian> XianList = new ArrayList<>();
//声明省市县名称列表:数据源
private List<String> nameList = new ArrayList<>();
//创建适配器
private ArrayAdapter<String> adapter;
//全局的选中的省市县城市
private Sheng s;
private Shi shi;
private Xian xian;
//消息处理loop
//【内存泄漏】
Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what)
{
case 0:
//通知ListView数据更改
adapter.notifyDataSetChanged();
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建sharedPreferences对象
SharedPreferences sharedPreferences = getSharedPreferences("data", MODE_PRIVATE);
String cityid = sharedPreferences.getString("cityid", "");
//如果读取到了cityid,cityid长度大于0
if (cityid.length() > 0) {
WeatherActivity.actionStart(MainActivity.this, cityid);
}
buttonBack = findViewById(R.id.back);
//button添加点击操作
buttonBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//点击操作,首先判断当前级别
//如果当前处于县级,返回市级
if (level == level_xian) {
level = level_shi;
//显示上一级省名称
title.setText(s.getName());
//法1:重新获取一次市级列表
// getShi();
//法2:直接遍历市级列表
//将所有的市级名称填到homelist中
nameList.clear();
//ShiList.for回车,自动出
for (Shi shi1 : ShiList) {
nameList.add(shi1.getName());
adapter.notifyDataSetChanged();
}
} else if (level == level_shi) {
level = level_sheng;
title.setText("中国");
nameList.clear();
for (Sheng sheng1 : ShengList) {
nameList.add(sheng1.getName());
adapter.notifyDataSetChanged();
}
}
}
});
title = findViewById(R.id.title);
title.setText("中国");
//调用初始化方法
initListView();
//联网初始化省信息
getSheng();
}
/**
* 新建初始化ListView方法
*/
private void initListView() {
//初始化ListView
//在布局文件中找到该ListView
listView = (ListView) findViewById(R.id.listview);
//数据源、ListView、适配器实现绑定,数据和显示实时更新
//初始化适配器,将适配器和数据源绑定在一起
//this:上下文
//simple_list_item_1:简单的布局
//nameList:设置数据源
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, nameList);
//绑定ListView和适配器,ListView设置适配器
listView.setAdapter(adapter);
//设置点击操作
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//通过点击的位置获取到点击的对象
//如果当前级别是省级,那么获取省级对象,获取市级对象
if (level == level_sheng) {
level = level_shi;
s = ShengList.get(position);
//点击的哪个省,那么title显示该省名称
title.setText(s.getName());
Log.d("MainActivity", "onItemClick: " + s.getName());
getShi();
} else if (level == level_shi) {
level = level_xian;
shi = ShiList.get(position);
//点击的哪个市,那么title显示该市名称
title.setText(shi.getName());
Log.d("MainActivity", "onItemClick: " + shi.getName());
getXian();
} else if (level == level_xian) {
xian = XianList.get(position);
Log.d("MainActivity", "onItemClick: " + xian.getName());
//选择city以后,在跳转到天气活动之前进行cityid存储
//获取edit对象,编辑sharedpreferences文件
SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
//将cityid存储到文件中
editor.putString("cityid", xian.getWeather_id());
//进行确定,应用,保存
editor.apply();
//跳转到天气显示界面
//法1:
// Intent intent = new Intent(MainActivity.this, WeatherActivity.class);
// //传递cityid到下一个活动
// //将weatherid传递到下一个活动,作为cityid参数
// intent.putExtra("cityid", xian.getWeather_id());
// startActivity(intent);
//法2:启动活动的方法
WeatherActivity.actionStart(MainActivity.this, xian.getWeather_id());
}
}
});
}
/**
* 获取省一级的城市列表
*/
private void getSheng() {
//定义url,接口
String url = "http://guolin.tech/api/china";
//#注意:正常情况下,先创建对象,再调用方法
// HttpUtil httpUtil = new HttpUtils();
// httpUtil.sendOkhttpRequest();
//每次网络访问时,直接调用sendOkhttpRequest即可
HttpUtils.sendOkhttpRequest(url, new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
// e.printStackTrace();
//如果访问失败,输出失败信息
Log.d("MainActivity", "onFailure: 网络访问失败");
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
//将网络相应信息转换成字符串型
//该操作只能执行一次
String data = response.body().string();
// String data1 = response.body().string(); //错误
//输出日志信息
Log.d("MainActivity", "onResponse: " + data);
//解析数据,并生成数据类
try {
nameList.clear();
ShengList.clear();
//将json字符串转换为json数组
JSONArray jsonArray = new JSONArray(data); //需处理JSONException,未处理异常【用try/catch包括起来】
//遍历json数字,读取所有的json对象
for (int i = 0; i < jsonArray.length(); i++) {
//从json数组中读取json对象
JSONObject shengObject = jsonArray.getJSONObject(i);
//创建省一级城市对象
Sheng s = new Sheng();
//设置对应的值
s.setId(shengObject.getInt("id"));
s.setName(shengObject.getString("name"));
//将省对象添加到列表中
ShengList.add(s);
//将省名称添加到名称列表
nameList.add(s.getName());
//发送消息到Loop
//通过handleMessage进行消息处理
Message msg = new Message();
msg.what = 0; //消息id号
handler.sendMessage(msg);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
/**
* 获取市级的城市列表
* 法1:方法中缺少变量,可以直接传递进来
*/
// private void getShi(int shengid) {
// //url中省级id号是变量,url不完整
// String url = "http://guolin.tech/api/china/" + shengid;
// }
/**
* 获取市级的城市列表
* 法2:①将被选中的省级城市定义为全部变量
* ②在getShi方法中进行读取
*/
private void getShi() {
//定义url,接口
String url = "http://guolin.tech/api/china/" + s.getId();
HttpUtils.sendOkhttpRequest(url, new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
String data = response.body().string();
try {
//清空nameList,准备存放数据
nameList.clear();
ShiList.clear();
JSONArray jsonArray = new JSONArray(data);
for (int i = 0; i < jsonArray.length(); i++) {
//获取第i个位置的json对象
JSONObject jsonObject = jsonArray.getJSONObject(i);
Shi shi = new Shi();
shi.setId(jsonObject.getInt("id"));
shi.setName(jsonObject.getString("name"));
ShiList.add(shi);
nameList.add(shi.getName());
Message msg = new Message();
msg.what = 0;
handler.sendMessage(msg);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
/**
* 获取县级的城市列表
*/
private void getXian() {
//定义url,接口
String url = "http://guolin.tech/api/china/" + s.getId() + "/" + shi.getId();
HttpUtils.sendOkhttpRequest(url, new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
String data = response.body().string();
try {
//清空nameList,准备存放数据
nameList.clear();
XianList.clear();
JSONArray jsonArray = new JSONArray(data);
for (int i = 0; i < jsonArray.length(); i++) {
//获取第i个位置的json对象
JSONObject jsonObject = jsonArray.getJSONObject(i);
Xian xian = new Xian();
xian.setId(jsonObject.getInt("id"));
xian.setName(jsonObject.getString("name"));
xian.setWeather_id(jsonObject.getString("weather_id"));
XianList.add(xian);
nameList.add(xian.getName());
Message msg = new Message();
msg.what = 0;
handler.sendMessage(msg);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
}
activity_weather.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".WeatherActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary">
<TextView
android:id="@+id/title_city"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textSize="20sp"
android:textColor="#fff"
tools:text="济南"/>
<TextView
android:id="@+id/title_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:textSize="16sp"
android:textColor="#fff"
android:layout_marginRight="12dp"
android:layout_marginEnd="12dp"
tools:text="15:00" />
RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="32dp">
<TextView
android:id="@+id/degree"
android:textColor="#000"
android:textSize="60sp"
tools:text="20℃"
android:layout_gravity="end"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/weather_info"
android:textColor="#000"
android:textSize="20sp"
tools:text="晴"
android:layout_gravity="end"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
LinearLayout>
LinearLayout>
api:http://www.tianqiapi.com/api?version=v1&appid=72458447&appsecret=E2P8xV9n
新建七日天气数据类Forecast.java,代码如下:
import java.util.List;
/**
*七日天气数据类
*/
public class Forecast {
/**
* cityid : 101250101
* update_time : 2020-08-15 06:52:20
* city : 长沙
* cityEn : changsha
* country : 中国
* countryEn : China
* data : [{"day":"15日(今天)","date":"2020-08-15","week":"星期六","wea":"晴","wea_img":"qing","air":22,"humidity":76,"air_level":"优","air_tips":"空气很好,可以外出活动,呼吸新鲜空气,拥抱大自然!","alarm":{"alarm_type":"","alarm_level":"","alarm_content":""},"tem1":"36℃","tem2":"27℃","tem":"29℃","win":["南风","南风"],"win_speed":"3-4级转<3级","hours":[{"day":"15日08时","wea":"多云","tem":"29℃","win":"南风","win_speed":"3-4级"},{"day":"15日11时","wea":"晴","tem":"32℃","win":"南风","win_speed":"3-4级"},{"day":"15日14时","wea":"晴","tem":"34℃","win":"南风","win_speed":"3-4级"},{"day":"15日17时","wea":"晴","tem":"35℃","win":"南风","win_speed":"<3级"},{"day":"15日20时","wea":"晴","tem":"30℃","win":"南风","win_speed":"<3级"},{"day":"15日23时","wea":"晴","tem":"29℃","win":"南风","win_speed":"<3级"},{"day":"16日02时","wea":"晴","tem":"28℃","win":"南风","win_speed":"<3级"},{"day":"16日05时","wea":"晴","tem":"27℃","win":"南风","win_speed":"<3级"}],"index":[{"title":"中国人民保险
中暑指数","level":"较易中暑","desc":"长时间户外工作的你要适当调整作业时间,备好遮阳设施,及时补充盐分。"},{"title":"<\/em><\/em><\/em>","level":null,"desc":"天热风大,可选择低强度运动。"},{"title":"健臻·血糖指数","level":"易波动","desc":"气温高,血糖易波动,注意防暑降温。"},{"title":"穿衣指数","level":"炎热","desc":"建议穿短衫、短裤等清凉夏季服装。"},{"title":"洗车指数","level":"较不宜","desc":"风力较大,洗车后会蒙上灰尘。"},{"title":"紫外线指数","level":"很强","desc":"涂擦SPF20以上,PA++护肤品,避强光。"}]},{"day":"16日(明天)","date":"2020-08-16","week":"星期日","wea":"晴","wea_img":"qing","tem1":"36℃","tem2":"27℃","tem":"30℃","win":["南风","南风"],"win_speed":"<3级","hours":[{"day":"16日08时","wea":"晴","tem":"30℃","win":"南风","win_speed":"<3级"},{"day":"16日11时","wea":"晴","tem":"33℃","win":"南风","win_speed":"<3级"},{"day":"16日14时","wea":"晴","tem":"35℃","win":"南风","win_speed":"<3级"},{"day":"16日17时","wea":"晴","tem":"35℃","win":"南风","win_speed":"<3级"},{"day":"16日20时","wea":"晴","tem":"30℃","win":"南风","win_speed":"<3级"},{"day":"16日23时","wea":"晴","tem":"28℃","win":"南风","win_speed":"<3级"},{"day":"17日02时","wea":"晴","tem":"27℃","win":"南风","win_speed":"<3级"},{"day":"17日05时","wea":"晴","tem":"27℃","win":"南风","win_speed":"<3级"}],"index":[{"title":"中国人民保险
中暑指数","level":"较易中暑","desc":"炎炎夏日里,出行尽量穿浅色或素色服装。"},{"title":"<\/em><\/em><\/em>","level":null,"desc":"天气有点热,运动多补水。"},{"title":"健臻·血糖指数","level":"易波动","desc":"气温高,血糖易波动,注意防暑降温。"},{"title":"穿衣指数","level":"炎热","desc":"建议穿短衫、短裤等清凉夏季服装。"},{"title":"洗车指数","level":"适宜","desc":"天气较好,适合擦洗汽车。"},{"title":"紫外线指数","level":"很强","desc":"涂擦SPF20以上,PA++护肤品,避强光。"}]},{"day":"17日(后天)","date":"2020-08-17","week":"星期一","wea":"晴","wea_img":"qing","tem1":"36℃","tem2":"27℃","tem":"29℃","win":["南风","南风"],"win_speed":"<3级","hours":[{"day":"17日08时","wea":"晴","tem":"29℃","win":"南风","win_speed":"<3级"},{"day":"17日11时","wea":"晴","tem":"33℃","win":"南风","win_speed":"<3级"},{"day":"17日14时","wea":"晴","tem":"35℃","win":"南风","win_speed":"<3级"},{"day":"17日17时","wea":"晴","tem":"35℃","win":"南风","win_speed":"<3级"},{"day":"17日20时","wea":"晴","tem":"30℃","win":"南风","win_speed":"<3级"},{"day":"17日23时","wea":"晴","tem":"29℃","win":"南风","win_speed":"<3级"},{"day":"18日02时","wea":"晴","tem":"28℃","win":"南风","win_speed":"<3级"},{"day":"18日05时","wea":"晴","tem":"27℃","win":"南风","win_speed":"<3级"}],"index":[{"title":"中国人民保险
中暑指数","level":"易中暑","desc":"酷暑炎炎,尽量避免在上午10点至下午2点外出。"},{"title":"<\/em><\/em><\/em>","level":null,"desc":"天气有点热,运动多补水。"},{"title":"健臻·血糖指数","level":"易波动","desc":"气温高,血糖易波动,注意防暑降温。"},{"title":"穿衣指数","level":"炎热","desc":"建议穿短衫、短裤等清凉夏季服装。"},{"title":"洗车指数","level":"适宜","desc":"天气较好,适合擦洗汽车。"},{"title":"紫外线指数","level":"很强","desc":"涂擦SPF20以上,PA++护肤品,避强光。"}]},{"day":"18日(周二)","date":"2020-08-18","week":"星期二","wea":"晴","wea_img":"qing","tem1":"36℃","tem2":"28℃","tem":"30℃","win":["南风","南风"],"win_speed":"<3级","hours":[{"day":"18日08时","wea":"晴","tem":"30℃","win":"南风","win_speed":"<3级"},{"day":"18日14时","wea":"晴","tem":"36℃","win":"南风","win_speed":"<3级"},{"day":"18日20时","wea":"晴","tem":"30℃","win":"南风","win_speed":"<3级"},{"day":"19日02时","wea":"晴","tem":"28℃","win":"南风","win_speed":"<3级"}],"index":[{"title":"中国人民保险
中暑指数","level":"较易中暑","desc":"酷热难耐,外出尽量不要打赤膊,通风的棉衫和赤膊相比更有消暑的作用。"},{"title":"<\/em><\/em><\/em>","level":null,"desc":"天气有点热,运动多补水。"},{"title":"健臻·血糖指数","level":"易波动","desc":"气温高,血糖易波动,注意防暑降温。"},{"title":"穿衣指数","level":"炎热","desc":"建议穿短衫、短裤等清凉夏季服装。"},{"title":"洗车指数","level":"适宜","desc":"天气较好,适合擦洗汽车。"},{"title":"紫外线指数","level":"很强","desc":"涂擦SPF20以上,PA++护肤品,避强光。"}]},{"day":"19日(周三)","date":"2020-08-19","week":"星期三","wea":"晴","wea_img":"qing","tem1":"36℃","tem2":"28℃","tem":"30℃","win":["南风","南风"],"win_speed":"<3级","hours":[{"day":"19日08时","wea":"晴","tem":"30℃","win":"南风","win_speed":"<3级"},{"day":"19日14时","wea":"晴","tem":"35℃","win":"南风","win_speed":"<3级"},{"day":"19日20时","wea":"晴","tem":"30℃","win":"南风","win_speed":"<3级"},{"day":"20日02时","wea":"晴","tem":"28℃","win":"南风","win_speed":"<3级"}],"index":[{"title":"中国人民保险
中暑指数","level":"易中暑","desc":"又是蒸桑拿的一天,记得多喝盐开水,随身携带防暑药物。"},{"title":"<\/em><\/em><\/em>","level":null,"desc":"天气有点热,运动多补水。"},{"title":"健臻·血糖指数","level":"易波动","desc":"气温高,血糖易波动,注意防暑降温。"},{"title":"穿衣指数","level":"炎热","desc":"建议穿短衫、短裤等清凉夏季服装。"},{"title":"洗车指数","level":"适宜","desc":"天气较好,适合擦洗汽车。"},{"title":"紫外线指数","level":"很强","desc":"涂擦SPF20以上,PA++护肤品,避强光。"}]},{"day":"20日(周四)","date":"2020-08-20","week":"星期四","wea":"晴","wea_img":"qing","tem1":"37℃","tem2":"29℃","tem":"30℃","win":["南风","南风"],"win_speed":"<3级","hours":[{"day":"20日08时","wea":"晴","tem":"30℃","win":"南风","win_speed":"<3级"},{"day":"20日14时","wea":"晴","tem":"37℃","win":"南风","win_speed":"<3级"},{"day":"20日20时","wea":"晴","tem":"32℃","win":"南风","win_speed":"<3级"},{"day":"21日02时","wea":"晴","tem":"29℃","win":"南风","win_speed":"<3级"}],"index":[{"title":"中国人民保险
中暑指数","level":"易中暑","desc":"夏日炎炎,到户外要配搭帽子和遮阳伞。"},{"title":"<\/em><\/em><\/em>","level":null,"desc":"天气有点热,运动多补水。"},{"title":"健臻·血糖指数","level":"易波动","desc":"气温高,血糖易波动,注意防暑降温。"},{"title":"穿衣指数","level":"炎热","desc":"建议穿短衫、短裤等清凉夏季服装。"},{"title":"洗车指数","level":"适宜","desc":"天气较好,适合擦洗汽车。"},{"title":"紫外线指数","level":"很强","desc":"涂擦SPF20以上,PA++护肤品,避强光。"}]},{"day":"21日(周五)","date":"2020-08-21","week":"星期五","wea":"晴","wea_img":"qing","tem1":"37℃","tem2":"29℃","tem":"31℃","win":["南风","南风"],"win_speed":"<3级","hours":[{"day":"21日08时","wea":"晴","tem":"31℃","win":"南风","win_speed":"<3级"},{"day":"21日14时","wea":"晴","tem":"36℃","win":"南风","win_speed":"<3级"},{"day":"21日20时","wea":"晴","tem":"32℃","win":"南风","win_speed":"<3级"},{"day":"22日02时","wea":"晴","tem":"29℃","win":"南风","win_speed":"<3级"}],"index":[{"title":"中国人民保险
中暑指数","level":"较易中暑","desc":"夏日炎炎,到户外要配搭帽子和遮阳伞。"},{"title":"<\/em><\/em><\/em>","level":null,"desc":"天气有点热,运动多补水。"},{"title":"健臻·血糖指数","level":"易波动","desc":"气温高,血糖易波动,注意防暑降温。"},{"title":"穿衣指数","level":"炎热","desc":"建议穿短衫、短裤等清凉夏季服装。"},{"title":"洗车指数","level":"适宜","desc":"天气较好,适合擦洗汽车。"},{"title":"紫外线指数","level":"很强","desc":"涂擦SPF20以上,PA++护肤品,避强光。"}]}]
*/
private String cityid;
private String update_time;
private String city;
private String cityEn;
private String country;
private String countryEn;
private List<DataBean> data;
public String getCityid() {
return cityid;
}
public void setCityid(String cityid) {
this.cityid = cityid;
}
public String getUpdate_time() {
return update_time;
}
public void setUpdate_time(String update_time) {
this.update_time = update_time;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCityEn() {
return cityEn;
}
public void setCityEn(String cityEn) {
this.cityEn = cityEn;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getCountryEn() {
return countryEn;
}
public void setCountryEn(String countryEn) {
this.countryEn = countryEn;
}
public List<DataBean> getData() {
return data;
}
public void setData(List<DataBean> data) {
this.data = data;
}
public static class DataBean {
/**
* day : 15日(今天)
* date : 2020-08-15
* week : 星期六
* wea : 晴
* wea_img : qing
* air : 22
* humidity : 76
* air_level : 优
* air_tips : 空气很好,可以外出活动,呼吸新鲜空气,拥抱大自然!
* alarm : {"alarm_type":"","alarm_level":"","alarm_content":""}
* tem1 : 36℃
* tem2 : 27℃
* tem : 29℃
* win : ["南风","南风"]
* win_speed : 3-4级转<3级
* hours : [{"day":"15日08时","wea":"多云","tem":"29℃","win":"南风","win_speed":"3-4级"},{"day":"15日11时","wea":"晴","tem":"32℃","win":"南风","win_speed":"3-4级"},{"day":"15日14时","wea":"晴","tem":"34℃","win":"南风","win_speed":"3-4级"},{"day":"15日17时","wea":"晴","tem":"35℃","win":"南风","win_speed":"<3级"},{"day":"15日20时","wea":"晴","tem":"30℃","win":"南风","win_speed":"<3级"},{"day":"15日23时","wea":"晴","tem":"29℃","win":"南风","win_speed":"<3级"},{"day":"16日02时","wea":"晴","tem":"28℃","win":"南风","win_speed":"<3级"},{"day":"16日05时","wea":"晴","tem":"27℃","win":"南风","win_speed":"<3级"}]
* index : [{"title":"中国人民保险
中暑指数","level":"较易中暑","desc":"长时间户外工作的你要适当调整作业时间,备好遮阳设施,及时补充盐分。"},{"title":"<\/em><\/em><\/em>","level":null,"desc":"天热风大,可选择低强度运动。"},{"title":"健臻·血糖指数","level":"易波动","desc":"气温高,血糖易波动,注意防暑降温。"},{"title":"穿衣指数","level":"炎热","desc":"建议穿短衫、短裤等清凉夏季服装。"},{"title":"洗车指数","level":"较不宜","desc":"风力较大,洗车后会蒙上灰尘。"},{"title":"紫外线指数","level":"很强","desc":"涂擦SPF20以上,PA++护肤品,避强光。"}]
*/
private String day;
private String date;
private String week;
private String wea;
private String wea_img;
private int air;
private int humidity;
private String air_level;
private String air_tips;
private AlarmBean alarm;
private String tem1;
private String tem2;
private String tem;
private String win_speed;
private List<String> win;
private List<HoursBean> hours;
private List<IndexBean> index;
public String getDay() {
return day;
}
public void setDay(String day) {
this.day = day;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getWeek() {
return week;
}
public void setWeek(String week) {
this.week = week;
}
public String getWea() {
return wea;
}
public void setWea(String wea) {
this.wea = wea;
}
public String getWea_img() {
return wea_img;
}
public void setWea_img(String wea_img) {
this.wea_img = wea_img;
}
public int getAir() {
return air;
}
public void setAir(int air) {
this.air = air;
}
public int getHumidity() {
return humidity;
}
public void setHumidity(int humidity) {
this.humidity = humidity;
}
public String getAir_level() {
return air_level;
}
public void setAir_level(String air_level) {
this.air_level = air_level;
}
public String getAir_tips() {
return air_tips;
}
public void setAir_tips(String air_tips) {
this.air_tips = air_tips;
}
public AlarmBean getAlarm() {
return alarm;
}
public void setAlarm(AlarmBean alarm) {
this.alarm = alarm;
}
public String getTem1() {
return tem1;
}
public void setTem1(String tem1) {
this.tem1 = tem1;
}
public String getTem2() {
return tem2;
}
public void setTem2(String tem2) {
this.tem2 = tem2;
}
public String getTem() {
return tem;
}
public void setTem(String tem) {
this.tem = tem;
}
public String getWin_speed() {
return win_speed;
}
public void setWin_speed(String win_speed) {
this.win_speed = win_speed;
}
public List<String> getWin() {
return win;
}
public void setWin(List<String> win) {
this.win = win;
}
public List<HoursBean> getHours() {
return hours;
}
public void setHours(List<HoursBean> hours) {
this.hours = hours;
}
public List<IndexBean> getIndex() {
return index;
}
public void setIndex(List<IndexBean> index) {
this.index = index;
}
public static class AlarmBean {
/**
* alarm_type :
* alarm_level :
* alarm_content :
*/
private String alarm_type;
private String alarm_level;
private String alarm_content;
public String getAlarm_type() {
return alarm_type;
}
public void setAlarm_type(String alarm_type) {
this.alarm_type = alarm_type;
}
public String getAlarm_level() {
return alarm_level;
}
public void setAlarm_level(String alarm_level) {
this.alarm_level = alarm_level;
}
public String getAlarm_content() {
return alarm_content;
}
public void setAlarm_content(String alarm_content) {
this.alarm_content = alarm_content;
}
}
public static class HoursBean {
/**
* day : 15日08时
* wea : 多云
* tem : 29℃
* win : 南风
* win_speed : 3-4级
*/
private String day;
private String wea;
private String tem;
private String win;
private String win_speed;
public String getDay() {
return day;
}
public void setDay(String day) {
this.day = day;
}
public String getWea() {
return wea;
}
public void setWea(String wea) {
this.wea = wea;
}
public String getTem() {
return tem;
}
public void setTem(String tem) {
this.tem = tem;
}
public String getWin() {
return win;
}
public void setWin(String win) {
this.win = win;
}
public String getWin_speed() {
return win_speed;
}
public void setWin_speed(String win_speed) {
this.win_speed = win_speed;
}
}
public static class IndexBean {
/**
* title : 中国人民保险
中暑指数
* level : 较易中暑
* desc : 长时间户外工作的你要适当调整作业时间,备好遮阳设施,及时补充盐分。
*/
private String title;
private String level;
private String desc;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".WeatherActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary">
<TextView
android:id="@+id/title_city"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textSize="20sp"
android:textColor="#fff"
tools:text="济南"/>
<TextView
android:id="@+id/title_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:textSize="16sp"
android:textColor="#fff"
android:layout_marginRight="12dp"
android:layout_marginEnd="12dp"
tools:text="15:00" />
RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="32dp">
<TextView
android:id="@+id/degree"
android:textColor="#000"
android:textSize="60sp"
tools:text="20℃"
android:layout_gravity="end"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/weather_info"
android:textColor="#000"
android:textSize="20sp"
tools:text="晴"
android:layout_gravity="end"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
LinearLayout>
<LinearLayout
android:padding="32dp"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#8000">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="预报"
android:textColor="#fff"
android:textSize="20sp"/>
<LinearLayout
android:id="@+id/forecast_layout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
LinearLayout>
LinearLayout>
LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp">
<TextView
android:id="@+id/date"
android:textSize="16sp"
android:text="2020-8-12"
android:textColor="#fff"
android:gravity="center"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<TextView
android:id="@+id/wea_info"
android:textSize="16sp"
android:text="晴"
android:textColor="#fff"
android:gravity="center"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<TextView
android:id="@+id/h_degree"
android:textSize="16sp"
android:text="30"
android:textColor="#fff"
android:gravity="center"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<TextView
android:id="@+id/l_degree"
android:textSize="16sp"
android:text="27"
android:textColor="#fff"
android:gravity="center"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
LinearLayout>
layout_weight=“1” 设置权重
package com.example.jnsyq;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.example.jnsyq.data.Forecast;
import com.example.jnsyq.data.InTimeWeather;
import com.example.jnsyq.utils.HttpUtils;
import com.google.gson.Gson;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
public class WeatherActivity extends AppCompatActivity {
private InTimeWeather inTimeWeather;
private Forecast forecast;
//声明控件
private TextView titleCity;
private TextView titleTime;
private TextView degree;
private TextView weatherInfo;
private LinearLayout foreLayout;
private String cityid; //private protected public(默认:protected)
Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what)
{
case 0:
//调用更新ui方法
updateUi();
break;
case 1:
//调用7天预报更新方法
updateForecast();
break;
default:
break;
}
}
};
public static void actionStart(Context context, String cityid) {
Intent intent = new Intent(context, WeatherActivity.class);
intent.putExtra("cityid", cityid);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_weather);
//从布局中找到控件
titleCity = findViewById(R.id.title_city);
titleTime = findViewById(R.id.title_time);
degree = findViewById(R.id.degree);
weatherInfo = findViewById(R.id.weather_info);
foreLayout = findViewById(R.id.forecast_layout);
//获取意图
Intent intent = getIntent();
//获取上一个活动传递劲来的数据
//初始化cityid的值
cityid = intent.getStringExtra("cityid");
//调用该方法获取数据
getWeatherInfo();
getForecaseInfo();
}
private void updateUi() {
//设置对应值
titleCity.setText(inTimeWeather.getCity());
titleTime.setText(inTimeWeather.getUpdate_time().split(" ")[1]);
degree.setText(inTimeWeather.getTem() + "℃");
weatherInfo.setText(inTimeWeather.getWea());
}
private void updateForecast() {
//遍历7天数据
//forecast.getData().for 自动出
for (Forecast.DataBean dataBean : forecast.getData()) {
//通过布局文件创建view
View view = LayoutInflater.from(this).inflate(R.layout.forecast_item, foreLayout, false);
//获取布局文件的控件
TextView date = view.findViewById(R.id.date);
TextView wea = view.findViewById(R.id.wea_info);
TextView hDegree = view.findViewById(R.id.h_degree);
TextView lDegree = view.findViewById(R.id.l_degree);
//设置值
date.setText(dataBean.getWeek());
wea.setText(dataBean.getWea());
hDegree.setText(dataBean.getTem1());
lDegree.setText(dataBean.getTem2());
//添加布局view
foreLayout.addView(view);
}
}
/**
* 创建获取实时天气的方法
*/
private void getWeatherInfo() {
//通过调用api获取天气信息
//直接通过ip地址进行天气信息获取
//cityid:变量,由上一个活动传递进来
String url = "http://www.tianqiapi.com/api?version=v6&appid=72458447&appsecret=E2P8xV9n&cityid=" + cityid.replace("CN", "");
//获取网络信息
//网络访问需要新开线程进行执行,不影响主线程
HttpUtils.sendOkhttpRequest(url, new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
//读取返回的数据
String data = response.body().string();
//新建gson对象
Gson gson = new Gson();
//解析json数据,初始化inTimeWeather
inTimeWeather = gson.fromJson(data, InTimeWeather.class); //json格式化
//初始化天气以后,发送消息,更新ui界面
Message msg = new Message();
msg.what = 0;
handler.sendMessage(msg);
}
});
}
/**
* 创建获取七日天气数据的方法
*/
private void getForecaseInfo() {
String url = "http://www.tianqiapi.com/api?version=v1&appid=72458447&appsecret=E2P8xV9n&cityid="
+ cityid.replace("CN", "");
HttpUtils.sendOkhttpRequest(url, new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
String data = response.body().string();
Gson gson = new Gson();
forecast = gson.fromJson(data, Forecast.class);
Message msg = new Message();
msg.what = 1;
handler.sendMessage(msg);
}
});
}
}