Android简单版天气预报,显示天气预报(第二步)
Android简单版天气预报,显示天气预报(第二步)
接着上一步的:[https://blog.csdn.net/weixin_44889138/article/details/102748057]
上一步的链接
ListView的改进,因为每次在getView()方法中还是会调用View的findViewById()方法来获取一次控件的实例,写一个内部类,利用**view.setTag()**存储,getTag()取。其实实现的机制跟RecycleView差不多
package com.example.xhhweather;import android.content.Intent;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;import android.widget.Toast;import java.util.List;public class CityAdapter extends BaseAdapter { // class ViewHolder{ TextView TVcityName; //删除城市 ImageView ivDelCity; //选择城市后返回天气界面 ImageView ivQuyCity; } private List<CityItem> list; public CityAdapter(List<CityItem> list){ this.list=list; } @Override public View getView(final int position, View covertView, final ViewGroup viewGroup) { View view; ViewHolder viewHolder; if(covertView==null){ view= LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.city_item,viewGroup,false); viewHolder=new ViewHolder(); viewHolder.TVcityName=view.findViewById(R.id.tv_city_name); viewHolder.ivQuyCity=view.findViewById(R.id.btn_move); viewHolder.ivDelCity=view.findViewById(R.id.iv_del_city); //将viewHolder存入在view中 view.setTag(viewHolder); }else{ view=covertView; viewHolder= (ViewHolder) view.getTag(); } CityItem cityItem= list.get(position); viewHolder.TVcityName.setText(cityItem.getCityName()); //删除城市 viewHolder.ivDelCity.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { list.remove(position); notifyDataSetChanged();//本身就是adapter } }); //移动城市 viewHolder.ivQuyCity.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { CityItem city=list.get(position); Toast.makeText(viewGroup.getContext(),city.getCityPinYin(),Toast.LENGTH_SHORT).show(); } }); return view; } @Override public int getCount() { return list.size(); } @Override public Object getItem(int i) { return list.get(i); } @Override public long getItemId(int i) { return i; }}
package com.example.xhhweather;import androidx.annotation.Nullable;import androidx.appcompat.app.AppCompatActivity;import android.content.Intent;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.TextView;import android.widget.Toast;import com.bumptech.glide.Glide;import com.example.xhhweather.gson.Weather;import com.example.xhhweather.gson.WeatherResDaily;import com.example.xhhweather.gson.WeatherResults;import com.google.gson.Gson;import com.google.gson.reflect.TypeToken;import java.io.IOException;import java.util.ArrayList;import java.util.List;import okhttp3.Call;import okhttp3.Callback;import okhttp3.Response;public class MainActivity extends AppCompatActivity{ private Button btnSelectCity; private TextView weatherTitleCityname; private TextView tvFirstDayDate; private TextView tvFirstDayPhe; private TextView tvFirstDayHigh; private TextView tvFirstDayLow; private TextView tvSecondDayDate; private TextView tvSecondDayPhe; private TextView tvSecondDayHigh; private TextView tvSecondDayLow; private TextView tvThirdDayDate; private TextView tvThirdDayPhe; private TextView tvThirdDayHigh; private TextView tvThirdDayLow; private TextView temperatureText; private TextView caseText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initfindViewById(); btnSelectCity.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent=new Intent(MainActivity.this,SelectCity.class); startActivityForResult(intent,1001); } }); } /** * 初始化 */ private void initfindViewById(){ btnSelectCity=findViewById(R.id.manage_city_btn); weatherTitleCityname=findViewById(R.id.weather_title_cityname); temperatureText=findViewById(R.id.temperature_text); caseText=findViewById(R.id.case_text); tvFirstDayDate=findViewById(R.id.tv_firstday_date); tvFirstDayPhe=findViewById(R.id.tv_firstday_phe); tvFirstDayHigh=findViewById(R.id.tv_firstday_high); tvFirstDayLow=findViewById(R.id.tv_firstday_low); tvSecondDayDate=findViewById(R.id.tv_secondday_date); tvSecondDayPhe=findViewById(R.id.tv_secondday_phe); tvSecondDayHigh=findViewById(R.id.tv_secondday_high); tvSecondDayLow=findViewById(R.id.tv_secondday_low); tvThirdDayDate=findViewById(R.id.tv_thirdday_date); tvThirdDayPhe=findViewById(R.id.tv_thirdday_phe); tvThirdDayHigh=findViewById(R.id.tv_thirdday_high); tvThirdDayLow=findViewById(R.id.tv_thirdday_low); } /** * 得到 * @param requestCode * @param resultCode * @param data */ @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if(requestCode==1001 && resultCode==1002){ String cityPinYin=data.getStringExtra("CITYPINYIN"); //Log.e("MainActivity","返回城市的拼音"+cityPinYin); //心知天气的api String url="https://api.seniverse.com/v3/weather/daily.json?key=SojsF4VNkV_cTQexq&location=" + cityPinYin + "&language=zh-Hans&unit=c&start=0&days=5"; HttpUtil.sendOkHttpRequest(url, new Callback() { @Override public void onFailure(Call call, IOException e) { e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { final String weatherData=response.body().string(); runOnUiThread(new Runnable() { @Override public void run() { Log.e("MainActivity","得到的数据"+weatherData); Gson gson =new Gson(); Weather weatherInfo=gson.fromJson(weatherData,Weather.class); WeatherResults results=weatherInfo.getResults().get(0); String cityName=results.getLocation().getName();//城市名称 weatherTitleCityname.setText(cityName); //将3天内的天气数据获得后存入二维数组 String [] [] resultDaily=new String[3][5]; for(int i=0;i<3;i++){ for(int j=0;j<4;){ resultDaily[i][j]=results.getDaily().get(i).getDate();j++; resultDaily[i][j]=results.getDaily().get(i).getText_day();j++; resultDaily[i][j]=results.getDaily().get(i).getHigh();j++; resultDaily[i][j]=results.getDaily().get(i).getLow();j++; } } temperatureText.setText(resultDaily[0][2]+"℃"); caseText.setText(resultDaily[0][1]); for(int j=0;j<4;){ //Log.e("resultDaily",resultDaily[0][j]); tvFirstDayDate.setText(resultDaily[0][j]);j++; tvFirstDayPhe.setText(resultDaily[0][j]);j++; tvFirstDayHigh.setText(resultDaily[0][j]);j++; tvFirstDayLow.setText(resultDaily[0][j]);j++; } for(int j=0;j<4;){ tvSecondDayDate.setText(resultDaily[1][j]);j++; tvSecondDayPhe.setText(resultDaily[1][j]);j++; tvSecondDayHigh.setText(resultDaily[1][j]);j++; tvSecondDayLow.setText(resultDaily[1][j]);j++; } for(int j=0;j<4;){ tvThirdDayDate.setText(resultDaily[2][j]);j++; tvThirdDayPhe.setText(resultDaily[2][j]);j++; tvThirdDayHigh.setText(resultDaily[2][j]);j++; tvThirdDayLow.setText(resultDaily[2][j]);j++; } } }); } }); } }}
package com.example.xhhweather;import okhttp3.OkHttpClient;import okhttp3.Request;public class HttpUtil { public static void sendOkHttpRequest(String url,okhttp3.Callback callback){ OkHttpClient client=new OkHttpClient(); Request request=new Request.Builder() .url(url) .build(); client.newCall(request).enqueue(callback); }}
接下来,分析重点
首先看一下心知天气文档,得知需要城市拼音,才能利用api得到不同城市的接口,返回的数据是json格式
访问api需要使用HTTP协议访问网络,那么应该得先想到要用到网络的权限
uses-permission android:name=“android.permission.INTERNET”
这里我用的是OkHttp代替HttpURLConnecion,需要导入依赖
implementation ‘com.squareup.okhttp3:okhttp:3.4.1’
如果不熟悉用法,那就从简单的做起,我介绍怎么简单获得必应图片的每日一图,与本项目有间接的关系(后期用到)
导入这个依赖 implementation ‘com.github.bumptech.glide:glide:4.10.0’,简单快捷可以将图片加载,而且容易理解
建一个HttpUtil类的原因
一个应用程序很可能会在许多地方都使用到网络功能,而发送HTTP请求的代码基本相同,如果每次都去编写,这显然很差劲,将这些通用的网络操作提取到一个公共的类里,并提供一个静态方法
package com.example.atuogetpic;import okhttp3.OkHttpClient;import okhttp3.Request;public class HttpUtil { public static void sendOkHttpRequest(String address,okhttp3.Callback callback){ OkHttpClient client=new OkHttpClient(); Request request=new Request.Builder() .url(address) .build(); client.newCall(request).enqueue(callback); }}
package com.example.atuogetpic;import androidx.appcompat.app.AppCompatActivity;import android.content.SharedPreferences;import android.os.Bundle;import android.preference.PreferenceManager;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.ImageView;import com.bumptech.glide.Glide;import java.io.IOException;import okhttp3.Call;import okhttp3.Callback;import okhttp3.HttpUrl;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.Response;import static android.preference.PreferenceManager.getDefaultSharedPreferences;public class MainActivity extends AppCompatActivity { private ImageView bingPicImg; private Button btnQ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bingPicImg=findViewById(R.id.bing_pic_img); btnQ=findViewById(R.id.btn); btnQ.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { loadBingPic(); } }); } /** * 加载必应每日一图 */ private void loadBingPic(){ final String requestBingPic="http://guolin.tech/api/bing_pic"; HttpUtil.sendOkHttpRequest(requestBingPic, new Callback() { @Override public void onResponse(Call call, Response response) throws IOException { final String bingPic=response.body().string(); SharedPreferences.Editor editor= getSharedPreferences("bing_pic",MODE_PRIVATE).edit(); editor.putString("bing_pic",bingPic); editor.apply(); runOnUiThread(new Runnable() { @Override public void run() { Glide.with(MainActivity.this).load(bingPic).into(bingPicImg);//加载图片 } }); } @Override public void onFailure(Call call, IOException e) { e.printStackTrace(); } }); }}
<?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" tools:context=".MainActivity" android:orientation="vertical"> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/btn" android:text="换图"/> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/bing_pic_img" android:src="@drawable/bg"/></LinearLayout>
好了,网络请求应该都会了吧
接下来才是重头戏,需要解析json里的数据,但是返回的数据太过复杂(可以看心知天气文档)
可以用gson解析 ,需要导入依赖
implementation ‘com.google.code.gson:gson:2.8.5’
它主要可以将一段json格式的字符串自动映射成一个对象,不用我们去编写代码解析
{
“results”:[
{
“location”:{“id”:“WTW3SJ5ZBJUY”,“name”:“上海”,“country”:“CN”,“path”:“上海,上海,中国”,“timezone”:“Asia/Shanghai”,“timezone_offset”:"+08:00"}
,“daily”:[
{ “date”:“2019-10-28”,“text_day”:“多云”,“code_day”:“4”,“text_night”:“晴”,“code_night”:“1”,“high”:“21”,“low”:“14”,“precip”:"",“wind_direction”:“西”,“wind_direction_degree”:“270”,“wind_speed”:“16.20”,“wind_scale”:“3”}
,{“date”:“2019-10-29”,“text_day”:“晴”,“code_day”:“0”,“text_night”:“晴”,“code_night”:“1”,“high”:“22”,“low”:“14”,“precip”:"",“wind_direction”:“东北”,“wind_direction_degree”:“45”,“wind_speed”:“25.20”,“wind_scale”:“4”}
,{“date”:“2019-10-30”,“text_day”:“晴”,“code_day”:“0”,“text_night”:“晴”,“code_night”:“1”,“high”:“22”,“low”:“14”,“precip”:"",“wind_direction”:“东”,“wind_direction_degree”:“90”,“wind_speed”:“16.20”,“wind_scale”:“3”}
],
“last_update”:“2019-10-28T11:17:53+08:00”
}
]
}
解析这个json数据
1.{ }里面是一个一个results数组,就应该写成列表,而weather类表示 { }
package com.example.xhhweather.gson;import java.util.List;public class Weather { private List<WeatherResults> results;//命名一定要与数据中的相同,一定要对应 public List<WeatherResults> getResults() { return results; } public void setResults(List<WeatherResults> results) { this.results = results; } @Override public String toString() { return "Weather{" + "results=" + results + '}'; }}
2.建一个WeatherResults类,results数组里面又有"location":{},“daily”:[],“last_update”:一个字符串
package com.example.xhhweather.gson;import java.util.List; public class WeatherResults { private WeatherResLocation location;//对应location:{},命名一定要与数据中的相同,一定要对应 private List<WeatherResDaily> daily;//对应daily:数组 private String last_update;//对应"last_update":一个字符串 public WeatherResLocation getLocation() { return location; } public List<WeatherResDaily> getDaily() { return daily; } public String getLast_update() { return last_update; } public void setLocation(WeatherResLocation location) { this.location = location; } public void setDaily(List<WeatherResDaily> daily) { this.daily = daily; } public void setLast_update(String last_update) { this.last_update = last_update; } @Override public String toString() { return "WeatherResults{" + "location=" + location + ", daily=" + daily + ", last_update='" + last_update + '\'' + '}'; } }
package com.example.xhhweather.gson;public class WeatherResDaily { private String date; private String text_day; private String code_day; private String text_night; private String code_night; private String high; private String low; private String precip; private String wind_direction; private String wind_direction_degree; private String wind_speed; private String wind_scale; public String getDate() { return date; } public String getText_day() { return text_day; } public String getCode_day() { return code_day; } public String getText_night() { return text_night; } public String getCode_night() { return code_night; } public String getHigh() { return high; } public String getLow() { return low; } public String getPrecip() { return precip; } public String getWind_direction() { return wind_direction; } public String getWind_direction_degree() { return wind_direction_degree; } public String getWind_speed() { return wind_speed; } public String getWind_scale() { return wind_scale; } public void setDate(String date) { this.date = date; } public void setText_day(String text_day) { this.text_day = text_day; } public void setCode_day(String code_day) { this.code_day = code_day; } public void setText_night(String text_night) { this.text_night = text_night; } public void setCode_night(String code_night) { this.code_night = code_night; } public void setHigh(String high) { this.high = high; } public void setLow(String low) { this.low = low; } public void setPrecip(String precip) { this.precip = precip; } public void setWind_direction(String wind_direction) { this.wind_direction = wind_direction; } public void setWind_direction_degree(String wind_direction_degree) { this.wind_direction_degree = wind_direction_degree; } public void setWind_speed(String wind_speed) { this.wind_speed = wind_speed; } public void setWind_scale(String wind_scale) { this.wind_scale = wind_scale; } @Override public String toString() { return "WeatherResDaily{" + "date='" + date + '\'' + ", text_day='" + text_day + '\'' + ", code_day='" + code_day + '\'' + ", text_night='" + text_night + '\'' + ", code_night='" + code_night + '\'' + ", high='" + high + '\'' + ", low='" + low + '\'' + ", precip='" + precip + '\'' + ", wind_direction='" + wind_direction + '\'' + ", wind_direction_degree='" + wind_direction_degree + '\'' + ", wind_speed='" + wind_speed + '\'' + ", wind_scale='" + wind_scale + '\'' + '}'; }}
package com.example.xhhweather.gson;public class WeatherResLocation { private String id; private String name; private String country; private String path; private String timezone; private String timezone_offset; public String getId() { return id; } public String getName() { return name; } public String getCountry() { return country; } public String getPath() { return path; } public String getTimezone() { return timezone; } public String getTimezone_offset() { return timezone_offset; } public void setId(String id) { this.id = id; } public void setName(String name) { this.name = name; } public void setCountry(String country) { this.country = country; } public void setPath(String path) { this.path = path; } public void setTimezone(String timezone) { this.timezone = timezone; } public void setTimezone_offset(String timezone_offset) { this.timezone_offset = timezone_offset; } @Override public String toString() { return "WeatherResLocation{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", country='" + country + '\'' + ", path='" + path + '\'' + ", timezone='" + timezone + '\'' + ", timezone_offset='" + timezone_offset + '\'' + '}'; }}
代码可以自动生成,右键点击general(首先要先命名)
Gson gson =new Gson();
Weather weatherInfo=gson.fromJson(weatherData,Weather.class);
weatherData为你发起请求后返回的json数据
这样就可以得到你想要的数据
那就先到这了,代码会在下一步开源
更多相关文章
- Android之解析Json数据
- Notification中Intent携带数据重复问题
- android中的数据存储
- ThreadLocal原理解析(1):数据存取
- Android--用JSON解析数据
- Android 中的数据存储
- android 直接进行数据库操作