Android开发实战-项目学习笔记(3)
显示天气信息【补】
针对Android开发实战-项目学习笔记(2),最后部分进行代码完善
添加新的数据
1.设计布局
2.编写布局文件
3.引入到父文件
4.更改Java代码
①找到控件
②更新控件内容
第一步:
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" 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只能有一个孩子(一个布局或控件)
<?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" 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:具体情况再调整
<?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" 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>
效果图:
- textColor="#fff"【ffffff】 值为3个时,默认没写透明度,透明度没有值,故不透明;background="#8000"【88000000】
- A% 透明度 + RGB 十六进制设置颜色
第四步:
include引入其他布局文件【模块化编写】:相当于将被引入的文件(activity_weather)整体的复制到了文件当中
activity_weather.xml
WeatherActivity.java
找到控件:
更新控件内容:
效果图:
注意:可往下滑动
第五步:
下拉刷新
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
<?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" 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
效果图:
问题:
WeatherActivity.java
问题1:
数据获取完成后,下拉刷新加载图标不会自动消失(下拉刷新操作不会自动停止),下拉刷新不知道数据是否获取完整,需要手动停止刷新
问题2:
清空数据
第六步:
设置背景图
必应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
<?xml version="1.0" encoding="utf-8"?><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
第七步:
创建tips.xml
tips.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" 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>
效果图:
activity_weather.xml
WeatherActivity.java
代码部分:
activity_weather.xml
<?xml version="1.0" encoding="utf-8"?><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>
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:
坑:api访问多次
注意:黄色警告,红色错误
效果图:
后台更新天气
使用服务【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(安卓)之 下拉框(Spinner)的使用
- android: 静态XML和动态加载XML混合使用,以及重写Layout控件
- #菜鸟之旅#Android(安卓)Studio开发JNI工程——Native调用Java方
- Android的startActivityForResult()与onActivityResult()与setRe
- android中如何判断edittext中数据为空?
- Android3.1比2.2多了一个android…
- mybatisplus的坑 insert标签insert into select无参数问题的解决
- python起点网月票榜字体反爬案例