安卓天气应用的练习

经过完全的安卓网络和数据处理课程的学习,极客班的老师布置了一个制作天气应用的作业。
我参考郭霖大神在第一行代码中的欧酷天气制作了一个天气应有的Demo。
在省市县的查找方面跟欧酷天气基本一致。
首先看下载Android下的目录结构,![这里写图片描述](https://img-blog.csdn.net/20160104115329059)
主要的页面就是城市选择和天气显示页面。通过SQLite建立了省、市、县三个等级的表,以便查找当前所在位置的天气。同时建立了网络请求的工具类。
首先看界面代码。
public class ChooseAreaActivity extends AppCompatActivity {
    //数据库的不同等级。
    public static final int LEVEL_PROVINCE = 0;
    public static final int LEVEL_CITY = 1;
    public static final int LEVEL_COUNTY = 2;

    private ProgressDialog progressDialog;
    private TextView titleText;
    private ListView listView;
    private ArrayAdapter<String> adapter;
    private ZIqiweatherDB zIqiweatherDB;
    private List<String> dataList = new ArrayList<String>();

    /**
     * 省列表
     * @param savedInstanceState
     */
    private List<Province> provinceList;

    /**
     * 市列表
     * @param savedInstanceState
     */
    private List<City> cityList;

    /**
     * 县列表
     * @param savedInstanceState
     */
    private List<County> countyList;

    /**
     * 选中的省份
     * @param savedInstanceState
     */
    private Province selectedProvince;

    /**
     * 选中的城市
     * @param savedInstanceState
     */
    private City selectedCity;

    /**
     * 当前选中的级别
     * @param savedInstanceState
     */
    private int currentLevel;

    /**
     * 是否从weatherareaActivity跳转过来
     * @param savedInstanceState
     */
    private boolean isFromWeatherActivity;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        requestWindowFeature(Window.FEATURE_NO_TITLE);
        isFromWeatherActivity = getIntent().getBooleanExtra("from_weather_activity",false);

        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        if (preferences.getBoolean("city_selected",false)&& !isFromWeatherActivity){
            Intent intent = new Intent(this,WeatherActivity.class);
            startActivity(intent);
            finish();
            return;
        }
        setContentView(R.layout.activity_choose_area);
        listView = (ListView) findViewById(R.id.list_view);
        titleText = (TextView) findViewById(R.id.title_text);
        adapter =new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,dataList);
        listView.setAdapter(adapter);
        zIqiweatherDB = ZIqiweatherDB.getInstance(this);
        listView.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> arg0, View view, int index, long arg3) {
                if (currentLevel == LEVEL_PROVINCE) {
                    selectedProvince = provinceList.get(index);
                    queryCities();
                } else if (currentLevel == LEVEL_CITY) {
                    selectedCity = cityList.get(index);
                    queryCounties();
                }else if (currentLevel == LEVEL_COUNTY){
                    String countyCode = countyList.get(index).getCountyName();
                    Intent intent = new Intent(ChooseAreaActivity.this,WeatherActivity.class);
                    intent.putExtra("county_code",countyCode);
                    startActivity(intent);
                    finish();
                }
            }
        });
        queryProvince();//加载省级数据
    }

    /**
     * 查询全国所有的省,优先从数据库查询,如果没有查询到再去服务器上查询。
     * @param
     * @return
     */
    private void queryProvince(){
        provinceList = zIqiweatherDB.loadProvinces();
        if (provinceList.size()>0){
            dataList.clear();
            for (Province province :provinceList){
                dataList.add(province.getProvinceName());
            }
            adapter.notifyDataSetChanged();
            listView.setSelection(0);
            titleText.setText("中国");
            currentLevel = LEVEL_PROVINCE;
        }else {
            queryFromServer(null,"province");
        }
    }

    /**
     * 查询选中省内所有的市,优先从数据库查询,如果没有查询到再去服务器上查询。
     * @param
     * @return
     */
    private void queryCities(){
        cityList = zIqiweatherDB.loadCities(selectedProvince.getId());
        if (cityList.size()>0){
            dataList.clear();
            for (City city:cityList){
                dataList.add(city.getCityName());
            }
            adapter.notifyDataSetChanged();
            listView.setSelection(0);
            titleText.setText(selectedProvince.getProvinceName());
            currentLevel = LEVEL_CITY;
        }else {
            queryFromServer(selectedProvince.getProvinceCode(),"city");
        }
    }

    /**
     * 查询选中市内所有的县,优先从数据库查询,如果没有查询到再去服务器上查询
     * @param
     * @return
     */
    private void queryCounties(){
        countyList = zIqiweatherDB.loadCounties(selectedCity.getId());
        if (countyList.size()>0){
            dataList.clear();
            for (County county:countyList){
                dataList.add(county.getCountyName());
            }
            adapter.notifyDataSetChanged();
            listView.setSelection(0);
            titleText.setText(selectedCity.getCityName());
            currentLevel =LEVEL_COUNTY;
        }else {
            queryFromServer(selectedCity.getCityCode(),"county");
        }
    }

    /**
     * 根据传入的代号和类型从服务器上查询省市县数据
     * @param
     * @return
     */
    private void queryFromServer(final  String code,final String type){
        String address;
        if (!TextUtils.isEmpty(code)){
            address = "http://www.weather.com.cn/data/list3/city"+code+".xml";
        }else {
            address="http://www.weather.com.cn/data/list3/city.xml";
        }
        showProgressDialog();
        HttpUtil.sendHttpRequest(address, new HttpCallbackListener() {
            @Override
            public void onFinish(String response) {
                boolean result = false;
                if ("province".equals(type)){
                    result = Utility.handleProvinceResponse(zIqiweatherDB,response);
                }else if ("city".equals(type)){
                    result=Utility.handleCitiesResponse(zIqiweatherDB,response,selectedProvince.getId());
                }else if ("county".equals(type)){
                    result=Utility.handleCountiesResponse(zIqiweatherDB,response,selectedCity.getId());
                }
                if (result){
                    //通过runOnUiThread()方法回到主线程处理逻辑
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            closeProgressDialog();
                            if ("province".equals(type)){
                                queryProvince();
                            }else if ("city".equals(type)){
                                queryCities();
                            }else if ("county".equals(type)){
                                queryCounties();
                            }
                        }
                    });
                }
            }

            @Override
            public void onError(Exception e) {
                //通过runOnUiThread()方法回到主线程处理逻辑
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        closeProgressDialog();
                        Toast.makeText(ChooseAreaActivity.this,"加载失败",Toast.LENGTH_SHORT
                        ).show();
                    }
                });

            }
        });
    }

    /**
     * 显示进度对话框
     * @param
     * @return
     */
    private void showProgressDialog(){
        if (progressDialog == null){
            progressDialog = new ProgressDialog(this);
            progressDialog.setMessage("正在加载...");
            progressDialog.setCanceledOnTouchOutside(false);
        }
        progressDialog.show();
    }

    /**
     * 关闭进度对话框
     * @param
     * @return
     */
    private void closeProgressDialog(){
        if (progressDialog != null){
            progressDialog.dismiss();
        }
    }

    /**
     * 捕获back按键,根据当前的级别来判断,此时应该返回市列表、省列表、还是直接退出。
     * @param
     * @return
     */
    @Override
    public void onBackPressed(){
        if (currentLevel == LEVEL_COUNTY){
            queryCities();
        }else if (currentLevel == LEVEL_CITY){
            queryProvince();
        }else {
            if (isFromWeatherActivity){
                Intent intent = new Intent(this,WeatherActivity.class);
                startActivity(intent);
            }
            finish();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_choose_area, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}
这样通过一层一层的选择就可以得到当前需要查看天气的城市代码,然后根据城市代码去查天气。
public class WeatherActivity extends AppCompatActivity implements View.OnClickListener {

//    private LinearLayout weatherInfoLayout;

    /**
     * 用于显示城市名
     *
     * @param savedInstanceState
     */
    private TextView cityNameText;

    /**
     * 用于显示发布时间
     *
     * @param savedInstanceState
     */
    private TextView publishText;

    /**
     * 用于显示天气描述信息
     *
     * @param savedInstanceState
     */
    private TextView weatherDespText;

    /**
     * 用于显示气温1
     *
     * @param savedInstanceState
     */
    private TextView tempText;

    /**
     * 用于显示气温2
     *
     * @param savedInstanceState
     */
    private TextView windText;

    /**
     * 用于显示当前日期
     *
     * @param savedInstanceState
     */
    private TextView currentDateText;

    /**
     * 切换城市按钮
     *
     * @param savedInstanceState
     */
    private Button switchCity;

    /**
     * 更新天气按钮
     *
     * @param savedInstanceState
     */
    private Button refreshWeather;

    private String county = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_weather);
        //初始化控件
        cityNameText = (TextView) findViewById(R.id.city_name);
        publishText = (TextView) findViewById(R.id.publish_text);
        weatherDespText = (TextView) findViewById(R.id.weather_text);
        tempText = (TextView) findViewById(R.id.temp_text);
        windText = (TextView) findViewById(R.id.wind_text);
        currentDateText = (TextView) findViewById(R.id.date_text);
        switchCity = (Button) findViewById(R.id.switch_button);
        refreshWeather = (Button) findViewById(R.id.refresh_button);
        String countyCode = getIntent().getStringExtra("county_code");
        county = countyCode;
        if (!TextUtils.isEmpty(countyCode)) {
            //有县级代号就去查询天气
            publishText.setText("同步中...");
            cityNameText.setText(countyCode);
            queryWeatherCode(countyCode);
        } else {
            //没有县级代号天气就直接显示当地天气
            showWeather();
        }
        switchCity.setOnClickListener(this);
        refreshWeather.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.switch_button:
                Intent intent = new Intent(this, ChooseAreaActivity.class);
                intent.putExtra("from_weather_activity", true);
                startActivity(intent);
                finish();
                break;
            case R.id.refresh_button:

                queryWeatherCode(county);
                SimpleDateFormat formatter = new SimpleDateFormat ("MM月dd日 HH:mm:ss ");
                Date curDate = new Date(System.currentTimeMillis());//获取当前时间
                String str = formatter.format(curDate);
                publishText.setText(str+"刷新");
                break;
            default:
                break;
        }
    }

    /**
     * 查询县级代号所对应的天气代号
     */
    private void queryWeatherCode(String countyCode) {
        String address = "https://api.heweather.com/x3/weather?city=" + countyCode + "&key=你到该网站获取到的key";
        queryFromServer(address, "county_code");
    }

    /**
     * 根据传入的地址和类型去向服务器查询天气代号或者天气信息
     */
    private void queryFromServer(final String address, final String type) {
        HttpUtil.sendHttpRequest(address, new HttpCallbackListener() {
            @Override
            public void onFinish(String response) {
                if (!TextUtils.isEmpty(response)) {
                    //从服务器返回的数据中解析出天气
                    Utility.handleWeatherResponse(WeatherActivity.this, response);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            showWeather();
                        }
                    });
                }
            }


            @Override
            public void onError(Exception e) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        publishText.setText("同步失败");
                    }
                });
            }
        });
    }

    /**
     * 从SharedPreferences文件中读取存储的天气信息,并显示到界面上
     */
    private void showWeather() {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        cityNameText.setText(preferences.getString("city_name", ""));

        String temp = preferences.getString("temp1","")+"~"+preferences.getString("temp2","");
        tempText.setText(temp);
        String wind =preferences.getString("windDirection", "")+"--"+preferences.getString("windLevel","")+"级";
        windText.setText(wind);

        currentDateText.setText(preferences.getString("current_date", ""));
        String weatherNow = preferences.getString("weather_now","");
        String weatherNext= preferences.getString("weather_next", "");
        if (weatherNow == weatherNext){
            weatherDespText.setText(weatherNow);
        }else {
            weatherDespText.setText(weatherNow+"转"+weatherNext);
        }
    }
}
在显示天气的页面中,当确定当前城市代号是县级城市时就去查询城市代表的天气,获得的是一个JSON数据,将其解析放入sharedpreference中,当调用showlocation时将其获取出来。
同时显示天气的页面里还有切换城市按钮和刷新天气按钮。
调用的API网站是https://api.heweather.com/x3/weather?city=+ countyCode + "&key=你到该网站获取到的key。在网页获取到返回的JSON数据时解析起来一定要仔细。
解析网络的代码就只放出对于该网站的JSON示例。

    /**
     * 解析服务器返回的JSON数据,并将解析出的数据存储到本地
     */
    public static void handleWeatherResponse(Context context,String response){

        try {
            JSONObject jsonObject = new JSONObject(response);
            JSONArray jsonArray = jsonObject.getJSONArray("HeWeather data service 3.0");
            JSONObject newInfo = jsonArray.getJSONObject(0);
            //获取basic
            JSONObject basic = newInfo.getJSONObject("basic");
            JSONArray daily_forecast = newInfo.getJSONArray("daily_forecast");
            JSONObject condInfo = daily_forecast.getJSONObject(0);
            JSONObject cond = condInfo.getJSONObject("cond");
            JSONObject temp =condInfo.getJSONObject("tmp");
            JSONObject wind =condInfo.getJSONObject("wind");
            String cityName = basic.getString("city");
            String weatherNow = cond.getString("txt_d");
            String weatherNext = cond.getString("txt_n");
            String temp1 = temp.getString("min");
            String temp2 = temp.getString("max");
            String windDirection = wind.getString("dir");
            String windLevel =wind.getString("sc");
            saveWeatherInfo(context,cityName,weatherNow,weatherNext,temp1,temp2,windDirection,windLevel);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    private static void saveWeatherInfo(Context context, String cityName, String weatherNow,String weatherNext,String temp1,String temp2,String windDirection,String windLevel
    ) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月d日", Locale.CHINA);
        SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
        editor.putBoolean("city_selected", true);
        editor.putString("city_name", cityName);
        editor.putString("weather_now", weatherNow);
        editor.putString("weather_next",weatherNext);
        editor.putString("temp1", temp1);
        editor.putString("temp2", temp2);
        editor.putString("windDirection",windDirection);
        editor.putString("windLevel",windLevel);
        editor.putString("current_date", sdf.format(new Date()));
        editor.commit();

    }
这里只获取了天气、温度、风向几个数据。还是那句话,解析JSON数据的时候一定要仔细小心,理清楚各个JSON对象的层级关系,在数组中是否还有嵌套,只要有一个数据解析错就无法显示,一定要小心。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值