Android开发实战-项目学习笔记(3)

显示天气信息【补】

针对Android开发实战-项目学习笔记(2),最后部分进行代码完善

添加新的数据
1.设计布局
2.编写布局文件
3.引入到父文件
4.更改Java代码
①找到控件
②更新控件内容

第一步:

activity_weather.xml


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@color/colorPrimary"
    tools:context=".WeatherActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize">

        <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:layout_margin="16dp">

        <TextView
            android:id="@+id/degree"
            android:textColor="#fff"
            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="#fff"
            android:textSize="20sp"
            tools:text=""
            android:layout_gravity="end"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    LinearLayout>

    <LinearLayout
        android:layout_margin="16dp"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#8000">

        <TextView
            android:layout_margin="16dp"
            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开发实战-项目学习笔记(3)_第1张图片
注意:hardcoded:硬编码
解决:在res/values下,string.xml文件添加代码并点击Open Editor,如下:
Android开发实战-项目学习笔记(3)_第2张图片
若相随系统变化,改变中英文可使用如下方式:
Android开发实战-项目学习笔记(3)_第3张图片
Android开发实战-项目学习笔记(3)_第4张图片
Android开发实战-项目学习笔记(3)_第5张图片

效果图:

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

第二步:

针对屏幕太小,内容太多,显示不开
注意:可使用ScrollView包含所有想要实现滚动的布局
Android开发实战-项目学习笔记(3)_第7张图片
注意:ScrollView只能有一个孩子(一个布局或控件)


<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"
    android:background="@color/colorPrimary"
    tools:context=".WeatherActivity">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize">

                <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:layout_margin="16dp">

                <TextView
                    android:id="@+id/degree"
                    android:textColor="#fff"
                    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="#fff"
                    android:textSize="20sp"
                    tools:text=""
                    android:layout_gravity="end"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content" />

            LinearLayout>

            <LinearLayout
                android:layout_margin="16dp"
                android:orientation="vertical"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="#8000">

                <TextView
                    android:layout_margin="16dp"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@string/forecast"
                    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>

    ScrollView>

LinearLayout>

第三步:

创建api.xml
注意:垂直方向的线性布局
1.上半部分:TextView
2.下半部分【平分】:水平方向的线性布局,内含两个垂直方向线性布局【居中】
tips:具体情况再调整


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_margin="16dp"
    android:background="#8000">

    <TextView
        android:text="空气质量"
        android:textSize="20sp"
        android:textColor="#fff"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="16dp">

        <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1">
            
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:orientation="vertical">
                
                <TextView
                    tools:text="20"
                    android:id="@+id/aqi"
                    android:textSize="40sp"
                    android:textColor="#fff"
                    android:layout_gravity="center"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content" />
                
                <TextView
                    android:text="AQI指数"
                    android:textColor="#fff"
                    android:textSize="12sp"
                    android:layout_gravity="center"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content" />
            
            LinearLayout>

        RelativeLayout>

        <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:orientation="vertical">
                
                <TextView
                    tools:text="20"
                    android:id="@+id/pm25"
                    android:textSize="40sp"
                    android:textColor="#fff"
                    android:layout_gravity="center"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content" />
                
                <TextView
                    android:text="PM2.5"
                    android:textColor="#fff"
                    android:textSize="12sp"
                    android:layout_gravity="center"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content" />
            
            LinearLayout>

        RelativeLayout>

    LinearLayout>

LinearLayout>

效果图:

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

  • textColor="#fff"【ffffff】 值为3个时,默认没写透明度,透明度没有值,故不透明;background="#8000"【88000000】
    • A% 透明度 + RGB 十六进制设置颜色

第四步:

include引入其他布局文件【模块化编写】:相当于将被引入的文件(activity_weather)整体的复制到了文件当中

activity_weather.xml

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

WeatherActivity.java

Android开发实战-项目学习笔记(3)_第10张图片
找到控件:
Android开发实战-项目学习笔记(3)_第11张图片
更新控件内容:
Android开发实战-项目学习笔记(3)_第12张图片

效果图:

注意:可往下滑动
Android开发实战-项目学习笔记(3)_第13张图片
Android开发实战-项目学习笔记(3)_第14张图片

第五步:

下拉刷新

android.support.v4:扩展库,添加了swiperefreshlayout布局
android.support.v7:materal design,质感设计
Androidx:代替v4和v7,合并结果androidx

在build.gradle中导入,代码如下:

implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'

注意:点击Sync Now

tips:下拉时,下拉布局文件

activity_weather.xml

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


<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"
    android:background="@color/colorPrimary"
    tools:context=".WeatherActivity">

    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:id="@+id/refresh"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <LinearLayout
                android:orientation="vertical"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <RelativeLayout
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize">

                    <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:layout_margin="16dp">

                    <TextView
                        android:id="@+id/degree"
                        android:textColor="#fff"
                        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="#fff"
                        android:textSize="20sp"
                        tools:text=""
                        android:layout_gravity="end"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content" />

                LinearLayout>

                <LinearLayout
                    android:layout_margin="16dp"
                    android:orientation="vertical"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="#8000">

                    <TextView
                        android:layout_margin="16dp"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="@string/forecast"
                        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>

                <include layout="@layout/aqi"/>

            LinearLayout>

        ScrollView>

    androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

LinearLayout>

效果图:

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

WeatherActivity.java

在这里插入图片描述
Android开发实战-项目学习笔记(3)_第17张图片

效果图:

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

问题:

WeatherActivity.java

问题1:

数据获取完成后,下拉刷新加载图标不会自动消失(下拉刷新操作不会自动停止),下拉刷新不知道数据是否获取完整,需要手动停止刷新
Android开发实战-项目学习笔记(3)_第19张图片
Android开发实战-项目学习笔记(3)_第20张图片

问题2:

清空数据
Android开发实战-项目学习笔记(3)_第21张图片

第六步:

设置背景图

必应bing:每日一图

在build.gradle中导入,代码如下:

implementation 'com.github.bumptech.glide:glide:4.11.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'

注意:点击Sync Now

activity_weather.xml


<FrameLayout 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"
    android:background="@color/colorPrimary"
    tools:context=".WeatherActivity">

    <ImageView
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"/>
    
    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:id="@+id/refresh"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <LinearLayout
                android:orientation="vertical"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <RelativeLayout
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize">

                    <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:layout_margin="16dp">

                    <TextView
                        android:id="@+id/degree"
                        android:textColor="#fff"
                        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="#fff"
                        android:textSize="20sp"
                        tools:text=""
                        android:layout_gravity="end"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content" />

                LinearLayout>

                <LinearLayout
                    android:layout_margin="16dp"
                    android:orientation="vertical"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="#8000">

                    <TextView
                        android:layout_margin="16dp"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="@string/forecast"
                        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>

                <include layout="@layout/aqi"/>

            LinearLayout>

        ScrollView>

    androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

FrameLayout>
  • FrameLayout:特点为所有的控件默认都在左上角,控件和控件重叠
  • ImageView:作为背景图与天气信息显示界面重叠,在下边
  • scaleType=“centerCrop” :居中裁剪

WeatherActivity.java

Android开发实战-项目学习笔记(3)_第22张图片
Android开发实战-项目学习笔记(3)_第23张图片
Android开发实战-项目学习笔记(3)_第24张图片
Android开发实战-项目学习笔记(3)_第25张图片
Android开发实战-项目学习笔记(3)_第26张图片

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

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

第七步:

创建tips.xml

tips.xml


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_margin="16dp"
    android:background="#8000">

    <TextView
        android:layout_marginTop="16dp"
        android:layout_marginStart="16dp"
        android:textColor="#fff"
        android:textSize="20sp"
        android:text="生活建议"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp" />
    
    <TextView
        android:id="@+id/tips"
        tools:text="gasnb;lsaglaskjng;lanflgnal;sfdjbngarln"
        android:textSize="12sp"
        android:textColor="#fff"
        android:layout_margin="16dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

LinearLayout>

效果图:

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

activity_weather.xml

在这里插入图片描述

WeatherActivity.java

Android开发实战-项目学习笔记(3)_第31张图片
Android开发实战-项目学习笔记(3)_第32张图片
Android开发实战-项目学习笔记(3)_第33张图片

代码部分:

activity_weather.xml


<FrameLayout 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"
    android:background="@color/colorPrimary"
    tools:context=".WeatherActivity">

    <ImageView
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"/>
    
    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:id="@+id/refresh"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <LinearLayout
                android:orientation="vertical"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:fitsSystemWindows="true">

                <RelativeLayout
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize">

                    <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:layout_margin="16dp">

                    <TextView
                        android:id="@+id/degree"
                        android:textColor="#fff"
                        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="#fff"
                        android:textSize="20sp"
                        tools:text=""
                        android:layout_gravity="end"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content" />

                LinearLayout>

                <LinearLayout
                    android:layout_margin="16dp"
                    android:orientation="vertical"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="#8000">

                    <TextView
                        android:layout_margin="16dp"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="@string/forecast"
                        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>

                <include layout="@layout/aqi"/>
                <include layout="@layout/tips"/>

            LinearLayout>

        ScrollView>

    androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

FrameLayout>

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

WeatherActivity.java

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.bumptech.glide.Glide;
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 TextView aqi;
    private TextView pm25;
    private TextView tips;
    private SwipeRefreshLayout swipeRefreshLayout; //下拉刷新
    private ImageView imageView; //背景图imageview

    private String cityid; //private protected public(默认:protected)

    //图片url
    private String picurl;

    Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what)
            {
                case 0:
                    //调用更新ui方法
                    updateUi();
                    break;
                case 1:
                    //调用7天预报更新方法
                    updateForecast();
                    break;
                case 2:
                    loadPic();
                    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);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @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);
        aqi = findViewById(R.id.aqi);
        pm25 = findViewById(R.id.pm25);
        tips = findViewById(R.id.tips);
        imageView = findViewById(R.id.image);

        //找到下拉刷新的控件
        swipeRefreshLayout = findViewById(R.id.refresh);
        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                getForecaseInfo();
                getForecaseInfo();
                getPic();
            }
        });

        //获取意图
        Intent intent = getIntent();
        //获取上一个活动传递劲来的数据
        //初始化cityid的值
        cityid = intent.getStringExtra("cityid");

        //设置标题栏透明度
        View view = getWindow().getDecorView();
        view.setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
        //设置透明
        getWindow().setStatusBarColor(Color.TRANSPARENT);

        //调用该方法获取数据
        getWeatherInfo();
        getForecaseInfo();
        getPic();
    }

    //InTimeWeather里面的数据
    private void updateUi() {
        //设置对应值
        titleCity.setText(inTimeWeather.getCity());
        titleTime.setText(inTimeWeather.getUpdate_time().split(" ")[1]);
        degree.setText(inTimeWeather.getTem() + "℃");
        weatherInfo.setText(inTimeWeather.getWea());
        //空气质量模块
        aqi.setText(inTimeWeather.getAir());
        pm25.setText(inTimeWeather.getAir_pm25());
        tips.setText(inTimeWeather.getAir_tips());
    }

    //Forecast里面的数据
    private void updateForecast() {
        //清空线性布局
        foreLayout.removeAllViews();

        //遍历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 loadPic() {
        //this:上下文
        //url:图片链接
        //imageView:图片显示控件
        Glide.with(this).load(picurl).into(imageView);
    }

    /**
     * 创建获取实时天气的方法
     */
    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();
                //输出网络访问信息日志
                Log.d("weather", "onResponse: " + data);
                //新建gson对象
                Gson gson = new Gson();
                //解析json数据,初始化inTimeWeather
                inTimeWeather = gson.fromJson(data, InTimeWeather.class); //json格式化
                //将刷新状态改成false,停止刷新
                swipeRefreshLayout.setRefreshing(false);

                //初始化天气以后,发送消息,更新ui界面
                if (inTimeWeather.getCityid() != null) {
                    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);
                 swipeRefreshLayout.setRefreshing(false);
                 if (forecast.getCityid() != null) {
                     Message msg = new Message();
                     msg.what = 1;
                     handler.sendMessage(msg);
                 }
             }
         });
    }

    //调用每日一图api
    private void getPic() {
        String url = "http://guolin.tech/api/bing_pic";

        HttpUtils.sendOkhttpRequest(url, new Callback() {
            //错误
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                e.printStackTrace();
            }

            //tips:404,500,502,没有获取到数据或者获取到错误数据,有响应信息
            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                //获取数据
                picurl = response.body().string();
                //发送图片url获取成功的消息
                Message message = new Message();
                message.what = 2;
                handler.sendMessage(message);
            }
        });
    }

}

tips:
Android开发实战-项目学习笔记(3)_第35张图片
坑:api访问多次

注意:黄色警告,红色错误

效果图:

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

后台更新天气

使用服务【Service】,作用:后台保活
注意:创建Service

WeatherActivity.java

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.bumptech.glide.Glide;
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 TextView aqi;
    private TextView pm25;
    private TextView tips;
    private SwipeRefreshLayout swipeRefreshLayout; //下拉刷新
    private ImageView imageView; //背景图imageview

    private String cityid; //private protected public(默认:protected)

    //图片url
    private String picurl;

    Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what)
            {
                case 0:
                    //调用更新ui方法
                    updateUi();
                    break;
                case 1:
                    //调用7天预报更新方法
                    updateForecast();
                    break;
                case 2:
                    loadPic();
                    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);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @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);
        aqi = findViewById(R.id.aqi);
        pm25 = findViewById(R.id.pm25);
        tips = findViewById(R.id.tips);
        imageView = findViewById(R.id.image);

        //找到下拉刷新的控件
        swipeRefreshLayout = findViewById(R.id.refresh);
        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                getForecaseInfo();
                getForecaseInfo();
                getPic();
            }
        });

        //获取意图
        Intent intent = getIntent();
        //获取上一个活动传递劲来的数据
        //初始化cityid的值
        cityid = intent.getStringExtra("cityid");

        //设置标题栏透明度
        View view = getWindow().getDecorView();
        view.setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
        //设置透明
        getWindow().setStatusBarColor(Color.TRANSPARENT);

        //由于服务更新了各种信息并保存到了data文件中
        //所以当启动该活动时,可以先读取文件中数据
        //如果没读到数据,则进行网络访问进行读取
        if (!readData()) {
            //调用该方法获取数据
            getWeatherInfo();
            getForecaseInfo();
            getPic();
        }
    }

    private boolean readData() {
        SharedPreferences sharedPreferences = getSharedPreferences("data", MODE_PRIVATE);
        String weaInfo = sharedPreferences.getString("weatherinfo", null);
        String foreInfo = sharedPreferences.getString("forecastinfo", null);
        String pic = sharedPreferences.getString("pic", null);
        //当三个信息都不是null的时候,返回true,不进行网络访问获取信息
        if (weaInfo != null && foreInfo != null && pic != null) {
            //解析读取的数据
            Gson gson = new Gson();
            inTimeWeather = gson.fromJson(weaInfo, InTimeWeather.class);
            forecast = gson.fromJson(foreInfo, Forecast.class);
            picurl = pic;
            //更新界面
            updateUi();
            updateForecast();
            loadPic();
            return true;
        }

        //默认读取失败,需要网络访问加载数据
        return false;
    }

    /**
     * 显示实时天气数据
     */
    //InTimeWeather里面的数据
    private void updateUi() {
        //设置对应值
        titleCity.setText(inTimeWeather.getCity());
        titleTime.setText(inTimeWeather.getUpdate_time().split(" ")[1]);
        degree.setText(inTimeWeather.getTem() + "℃");
        weatherInfo.setText(inTimeWeather.getWea());
        //空气质量模块
        aqi.setText(inTimeWeather.getAir());
        pm25.setText(inTimeWeather.getAir_pm25());
        tips.setText(inTimeWeather.getAir_tips());
    }

    /**
     * 显示7天预测天气数据
     */
    //Forecast里面的数据
    private void updateForecast() {
        //清空线性布局
        foreLayout.removeAllViews();

        //遍历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 loadPic() {
        //this:上下文
        //url:图片链接
        //imageView:图片显示控件
        Glide.with(this).load(picurl).into(imageView);
    }

    /**
     * 创建获取实时天气的方法
     */
    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();
                //输出网络访问信息日志
                Log.d("weather", "onResponse: " + data);
                //新建gson对象
                Gson gson = new Gson();
                //解析json数据,初始化inTimeWeather
                inTimeWeather = gson.fromJson(data, InTimeWeather.class); //json格式化
                //将刷新状态改成false,停止刷新
                swipeRefreshLayout.setRefreshing(false);

                //初始化天气以后,发送消息,更新ui界面
                if (inTimeWeather.getCityid() != null) {
                    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);
                 swipeRefreshLayout.setRefreshing(false);
                 if (forecast.getCityid() != null) {
                     Message msg = new Message();
                     msg.what = 1;
                     handler.sendMessage(msg);
                 }
             }
         });
    }

    //调用每日一图api
    private void getPic() {
        String url = "http://guolin.tech/api/bing_pic";

        HttpUtils.sendOkhttpRequest(url, new Callback() {
            //错误
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                e.printStackTrace();
            }

            //tips:404,500,502,没有获取到数据或者获取到错误数据,有响应信息
            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                //获取数据
                picurl = response.body().string();
                //发送图片url获取成功的消息
                Message message = new Message();
                message.what = 2;
                handler.sendMessage(message);
            }
        });
    }

}

AutoUpdateService.java

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.IBinder;
import android.os.SystemClock;
import android.util.Log;
import com.example.jnsyq.utils.HttpUtils;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
public class AutoUpdateService extends Service {

    private String cityid;

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("Service", "onStartCommand: 服务正在运行");
        getCityid();
        getWeatherInfo();
        getForecastInfo();
        getPic();
        //获取闹钟服务
        AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
        //1分钟ms数
        int anHour = 60000;
        //计算更新时间点,从当前时间点+1分钟
        long attime = SystemClock.elapsedRealtime() + anHour;
        //创建意图
        Intent i = new Intent(this, AutoUpdateService.class);
        PendingIntent pendingIntent = PendingIntent.getService(this, 0,i,0);
        manager.cancel(pendingIntent);
        //设置闹钟任务
        manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, attime, pendingIntent);
        return super.onStartCommand(intent, flags,startId);
    }

    private void getCityid() {
        //读取cityid
        SharedPreferences sharedPreferences = getSharedPreferences("data", MODE_PRIVATE);
        cityid = sharedPreferences.getString("cityid", "");
    }

    //需要更新的内容
    private void getWeatherInfo() {
        //拼接url
        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();
                //判断数据是否获取成功,法1:
//                InTimeWeather inTimeWeather;
//                Gson gson = new Gson();
//                inTimeWeather = gson.fromJson(data, InTimeWeather.class);
//                if (inTimeWeather.getCity() != null){
//                    //说明数据获取成功
//                }
                //法2:
                //判断是否包含cityid关键字
                if(data.contains("cityid")){
                    //说明数据获取成功
                    SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
                    editor.putString("weatherinfo", data);
                    editor.apply();
                }
            }
        });
    }

    private void getForecastInfo() {
        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();
                if(data.contains("cityid")){
                    //说明数据获取成功
                    SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
                    editor.putString("forecastinfo", data);
                    editor.apply();
                }
            }
        });

    }
    private void getPic() {
        String url = "http://guolin.tech/api/bing_pic";
        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();
                SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
                editor.putString("pic", data);
                editor.apply();
            }
        });
    }

}

你可能感兴趣的:(Android,android,移动开发)