“Rimon天气”Android天气查询软件项目总结

“Rimon天气”是我在自学Android软件开发一段时间后,以郭霖写的《第一行代码》书中的天气查询软件“酷欧天气”为参考,改写的天气查询app。与酷欧天气相比,项目改动如下:

  1. 天气API由中国天气网改为百度APIStore提供的天气api
  2. 城市列表数据由网络请求改为调用本地数据库
  3. 可通过中文搜索城市或定位到所在城市来选择需查询天气的城市
  4. 添加增减已选择城市的数量、可显示未来4天天气预报等功能

考虑到该项目的主要目的是为了熟悉Android应用程序开发的整个流程和各基础控件的使用,项目并没有使用第三方开源库,因此界面显示和动画效果会比较粗糙,但正是由于没有使用第三方开源库,开发过程中遇到的很多问题都比较典型,在自己寻找方法解决问题的过程中,能够很好地提升自己的思考能力和解决问题的能力。下面我将本项目分为四个阶段,分别总结出在这四个阶段中所遇到的一些问题及应引起关注的地方,以此来巩固已掌握的技能点。

阶段一:天气api改为百度APIStore提供的天气api

由于目前中国天气网的免费天气API接口能够获取的天气信息比较有限,因此决定改用信息相对较丰富的百度APIStore提供的天气api。这样将会出现以下问题:

  1. 选择完城市后,部分城市查询出来的天气信息与所选择城市不符或无所选城市的天气信息
    原因:由于酷欧天气获取城市列表是通过网络请求中国天气网提供的城市列表api,而更换天气api为百度的后,两个平台对应的城市代码(citycode)有差别,因此使用中国天气网的城市代码去请求百度天气API的天气信息会出现部分城市信息错误的情况。
    解决方法:把从中国天气网获得城市列表更换为从百度天气API获得的可查询城市列表。

阶段二:城市列表数据由从网络获取改为调用本地数据库

由于每次从城市列表中查询没有被查询过的城市时都需要进行网络请求,而网络请求的快慢受到网络环境的影响,质量差的网络环境会加长用户等待时间,导致不好的用户体验,因此决定将城市列表的获取方式改为查询本地SQLite数据库(该数据库使用自己编写的程序,使用百度天气API逐个请求可用城市列表并存储到新建的数据库中,最后在应用启动的时候将数据库复制到应用对应的数据库文件路径上)。这样将会出现以下问题:

  1. 在应用初次启动时,出现卡顿或ANR错误
    原因:城市列表数据库文件较大,在复制assets文件夹下的数据库文件到应用相应文件夹时,可能会阻塞主线程,从而出现ANR错误。
    解决方法:与网络请求相类似,将复制数据库操作放到子线程中完成。

阶段三:增加中文搜索城市或定位到所在城市功能

为了更方便查找到目标城市,在三级选择城市的基础上增加了中文搜索城市和定位城市的功能,过程中遇到如下问题:

  1. 调用 locationManager.getLastKnownLocation(provider)方法时hint报错
    原因: Android6.0后变更了权限请求规则,需要动态获取权限。
    解决方法:按照hint提示,增加检查和获取权限的请求。

  2. 调用locationManager.getLastKnownLocation(provider)时location总是为空
    原因:寻找中……
    解决方法:使用do……while循环,当Location为空时,再次获取Location。

阶段四:添加增减已选择城市的数量、天气预报等功能

  1. 已选城市数量变动时,自定义页面指示器无法及时更新
    原因: viewpager采用预加载机制,加载新城市时预加载页面若已存在则默认会复用改页面,不重新加载,因此页面指示器无法及时更新。
    解决方法:重写FragmentPagerAdapter的getItemPosition方法,使返回值恒为PagerAdapter.POSITION_NONE,这样在调用notifyDataSetChanged()方法后,即使预加载页面已存在,也会重新加载一遍。

  2. 添加城市跳回到weatherActivity时,城市数量不增加,数据不更新。
    原因:对activity和fragment生命周期不熟悉,onCreat()后若活动没有destroy掉,不会重新调用onCreat方法。
    解决方法:将刷新页面的逻辑放在重写的onNewIntent()方法中。

  3. 存在多个城市时,随机出现加载天气时当前fragment显示的城市及其天气信息与其位置不对应
    原因:并发网络请求时(new thread().start()),数据返回顺序随机,导致数据显示错误。
    解决办法:为网络请求部分代码添加同步锁(使用synchronized),使每次只能有一个线程请求网络,避免出现并发网络请求。

  4. 显示天气预报数据的自定义view在不同dpi设备上显示的大小和位置不一
    原因: onDraw()方法中的坐标单位长度单位为px,每台设备的长和宽px值不同。
    解决方法:使用dp2px变换后的长度作为坐标点的坐标,固定的dp值在不同设备上的显示不受dpi的影响。

目前Rimon天气软件待解决的问题:

  1. 获取经纬度对应城市的API不稳定,经常请求错误或返回空结果;
  2. 获取定位权限时如果选择拒绝,应用程序会无响应;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android天气预报实验报告模板 public class SetCityActivity extends Activity { //定义的一个自动定位的列表 private ListView gpsView; //定义的一个省份可伸缩性的列表 private ExpandableListView provinceList; //定义的用于过滤的文本输入框 private TextView filterText; //定义的一个记录城市码的SharedPreferences文件名 public static final String CITY_CODE_FILE="city_code"; //城市的编码 private String[][] cityCodes; //省份 private String[] groups; //对应的城市 private String[][] childs; //自定义的伸缩列表适配器 private MyListAdapter adapter; //记录应用程序widget的ID private int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.set_city); gpsView = (ListView)findViewById(R.id.gps_view); provinceList= (ExpandableListView)findViewById(R.id.provinceList); //设置自动定位的适配器 gpsView.setAdapter(new GPSListAdapter(SetCityActivity.this)); //==============================GPS================================= //当单击自动定位时 gpsView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { TextView localeCity = (TextView)view.findViewById(R.id.locateCityText); localeCity.setText("正在定位..."); final LocateHandler handler = new LocateHandler(localeCity); //添加一个线程来处理定位 new Thread(){ public void run() { Map<Integer, String> cityMap= getLocationCityInfo(); //记录匹配的城市的索引 int provinceIndex = -1; int cityIndex = -1; //传给处理类的数据封装对象 Bundle bundle = new Bundle(); if(cityMap!=null) { //得到图家名 String country = cityMap.get(LocationXMLParser.COUNTRYNAME); //只匹配中国地区的天气 if(country!=null&&country.equals("中国")){ //得到省 String province = cityMap.get(LocationXMLParser.ADMINISTRATIVEAREANAME); //得到市 String city = cityMap.get(LocationXMLParser.LOCALITYNAME); //得到区县 String towns = cityMap.get(LocationXMLParser.DEPENDENTLOCALITYNAME); Log.i("GPS", "============"+province+"."+city+"."+towns+"=============="); //将GPS定位的城市与提供能查天气城市进行匹配 StringBuilder matchCity = new StringBuilder(city); matchCity.append("."); matchCity.append(towns); //找到省份 for(int i=0; i<groups.length; i++) { if(groups[i].equals(province)) { provinceIndex = i; break; } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值