获取市信息

代码部分:

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();                }            }        });    }}

效果图:

Android开发实战-项目学习笔记(2)_第1张图片

获取省级信息

代码部分:

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();                }            }        });    }}

效果图:

Android开发实战-项目学习笔记(2)_第2张图片

省市县返回问题

选错了省市县以后退回上一级别选择
注:通过重写actionbar实现返回的功能
在这里插入图片描述

第一步:

res/values中,修改styles.xml代码,效果如下:
Android开发实战-项目学习笔记(2)_第3张图片
Android开发实战-项目学习笔记(2)_第4张图片
Android开发实战-项目学习笔记(2)_第5张图片

第二步:

res/drawable中图片,插入修改xml

ic_back.png在这里插入图片描述

ic_home.png

在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?><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>
  • layout_centerVertical:上下居中,垂直居中
  • layout_alignParentLeft:左边,居左
  • layout_alignParentStart:开始,根据设置不同读取文字方向,其作用不同
    • 从左向右,start代表左边
    • 从右往左,start代表右边
  • layout_marginLeft:左边间隔
  • layout_marginStart:开始间隔
  • layout_centerInParent:在父组件布局中居中
  • tools:占位,程序运行时不会显示出来

效果图:

Android开发实战-项目学习笔记(2)_第6张图片

第三步:

声明控件

标题自定义

主要代码,截图:
Android开发实战-项目学习笔记(2)_第7张图片

Button返回

主要代码,截图:
Android开发实战-项目学习笔记(2)_第8张图片

问题:

网络访问

省级 -> 市级 -> 网络访问 需要
市级 -> 省级 -> 网络访问 不需要
修改代码,截图:
Android开发实战-项目学习笔记(2)_第9张图片
Android开发实战-项目学习笔记(2)_第10张图片
注:清空

反复重写

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();                }            }        });    }}

修改后:

新建Uitils工具类,截图和代码部分如下:
Android开发实战-项目学习笔记(2)_第11张图片

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();                }            }        });    }}

其中,TODO表示对未完成情况做标记
Android开发实战-项目学习笔记(2)_第12张图片

效果图:

省级:

Android开发实战-项目学习笔记(2)_第13张图片

市级:

Android开发实战-项目学习笔记(2)_第14张图片

县级:

Android开发实战-项目学习笔记(2)_第15张图片

控制台

在这里插入图片描述

显示地名和时间

第一步:

api:http://guolin.tech/api/weather?cityid=CN101190401
创建数据类:使用gsonformat创建实时天气的数据类

  • 右键单击,选择Generate...

Android开发实战-项目学习笔记(2)_第16张图片

  • 选择GsonFormat

Android开发实战-项目学习笔记(2)_第17张图片效果图如下:
Android开发实战-项目学习笔记(2)_第18张图片

  • https://www.tianqiapi.com/api?version=v6&appid=55233412&appsecret=2Mm5xcPA&cityid=CN101121101,复制该网址数据,点击Format

Android开发实战-项目学习笔记(2)_第19张图片
效果图如下:
Android开发实战-项目学习笔记(2)_第20张图片

  • 效果如图,点击OK

Android开发实战-项目学习笔记(2)_第21张图片

代码部分:

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,修改名称,效果如下:
Android开发实战-项目学习笔记(2)_第22张图片
Android开发实战-项目学习笔记(2)_第23张图片
MainActivity.java中添加代码,如下:
在这里插入图片描述

第三步:

添加gson包,在build.gradle中添加代码,如下:

implementation "com.google.code.gson:gson:2.8.6"

注意:点击Sync Now
在WeatherActivity.java中,使用gson获取数据,代码如下:
Android开发实战-项目学习笔记(2)_第24张图片

第四步:

activity_weather.xml

<?xml version="1.0" encoding="utf-8"?><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的倍数

效果图:

Android开发实战-项目学习笔记(2)_第25张图片

第四步:

完善MainActivity.java【修改省级中变量的名称,jsonArray】和WeatherActivity.java,启动WeatherAcitivity的方法有两种

法1:

MainActivity.java
Android开发实战-项目学习笔记(2)_第26张图片
WeatherActivity.java
Android开发实战-项目学习笔记(2)_第27张图片

法2:

注意:该方法的作用为避免传输数据类型排错
MainActivity.java
在这里插入图片描述
WeatherActivity.java
Android开发实战-项目学习笔记(2)_第28张图片

问题:

NullPointerException

变量被声明,没有初始化,内存中不存在被调用导致空指针异常
Android开发实战-项目学习笔记(2)_第29张图片
Android开发实战-项目学习笔记(2)_第30张图片
Android开发实战-项目学习笔记(2)_第31张图片

代码部分:

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);        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();                }            }        });    }}

WeatherActivity.java

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);            }        });    }}

效果图:

在县级下选择桦南,效果如下:
Android开发实战-项目学习笔记(2)_第32张图片

城市id存储

  • sharedpreferences
  • sqlite(数据库)

cityid:101120901

注意:使用sharedpreferences,使得每次打开app的时候查看上次是否选择城市,如果选择了,无需再选
MainActivity.java
Android开发实战-项目学习笔记(2)_第33张图片
Android开发实战-项目学习笔记(2)_第34张图片

代码部分:

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();                }            }        });    }}

获取并显示实时天气【7天天气】

第一步:

activity_weather.xml

<?xml version="1.0" encoding="utf-8"?><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开发实战-项目学习笔记(2)_第35张图片

第二步:

WeatherActivity.java
Android开发实战-项目学习笔记(2)_第36张图片
Android开发实战-项目学习笔记(2)_第37张图片
Android开发实战-项目学习笔记(2)_第38张图片

效果图:

Android开发实战-项目学习笔记(2)_第39张图片

第三步:

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; } } }}

第四步:

activity_weather.xml

<?xml version="1.0" encoding="utf-8"?><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>

效果图:

Android开发实战-项目学习笔记(2)_第40张图片

forecast_item.xml

<?xml version="1.0" encoding="utf-8"?><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);             }         });    }}

效果图:

Android开发实战-项目学习笔记(2)_第41张图片

更多相关文章

  1. Android 对象序列化之 Parcelable 取代 Serializable ?
  2. Android 对象序列化之追求完美的 Serial
  3. Android中的适配器(Adapter)
  4. 带你了解CLR是如何创建运行时对象?
  5. lambda表达式进行对象结合操作的实例详解
  6. 值类型对象的两种表示形式
  7. 克隆对象的方法实例教程
  8. c#中关于多线程创建对象的示例分享
  9. asp如何解析json字符串并转化为asp对象

随机推荐

  1. Android中对话框的工具类
  2. android百度地图 SDK v3.5.0
  3. Android 设置全屏显示的方法
  4. Phone Gap开发一:整合jQuery Mobile开发An
  5. 银联手机支付 手机客户端有几个?
  6. android 单击 切换图片 --- 注意图片大小
  7. 使用android 隐藏命令
  8. 深入解析RxJava源码(一)Observable对象的构
  9. 【Android自学笔记】为Android应用程序添
  10. Android RecyclerView网格布局的学习