针对Android开发实战-项目学习笔记(2),最后部分进行代码完善
添加新的数据
1.设计布局
2.编写布局文件
3.引入到父文件
4.更改Java代码
①找到控件
②更新控件内容
<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>
其中,黄色部分为警告,如下:
注意:hardcoded:硬编码
解决:在res/values下,string.xml文件添加代码并点击Open Editor
,如下:
若相随系统变化,改变中英文可使用如下方式:
针对屏幕太小,内容太多,显示不开
注意:可使用ScrollView包含所有想要实现滚动的布局
注意: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>
include引入其他布局文件【模块化编写】:相当于将被引入的文件(activity_weather)整体的复制到了文件当中
下拉刷新
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:下拉时,下拉布局文件
<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>
WeatherActivity.java
数据获取完成后,下拉刷新加载图标不会自动消失(下拉刷新操作不会自动停止),下拉刷新不知道数据是否获取完整,需要手动停止刷新
设置背景图
必应bing:每日一图
在build.gradle中导入,代码如下:
implementation 'com.github.bumptech.glide:glide:4.11.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
注意:点击Sync Now
<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>
创建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>
<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>
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);
}
});
}
}
注意:黄色警告,红色错误
使用服务【Service】,作用:后台保活
注意:创建Service
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);
}
});
}
}
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();
}
});
}
}