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简单版天气预报,显示天气预报(第二步)_第1张图片
Android简单版天气预报,显示天气预报(第二步)_第2张图片
那就先到这了,代码会在下一步开源

你可能感兴趣的:(Android)