来源:网易云课堂GeekBand第七次作业

作业要求:
做一个天气应用

  1. 接口参考: http://apistore.baidu.com/apiworks/servicedetail/880.html,只是参考API,可自行查找使用其他API接口
  2. 考察内容:获取数据,解析JSON
  3. 数据缓存在数据库中,使用ContentProvider来处理
  4. 如果不强制刷新,则使用缓存数据每隔一定时间再刷新一次

前期准备

1.选择合适的API!选择合适的API!选择合适的API!(重要的话说三遍,中途变更API严重影响效率和心情).
2.gson.如何添加依赖库 http://www.cnblogs.com/happyhacking/p/5257002.html

目录结构

UI

注意:在布局的过程中weightSum和layout_weight要慎用,尤其是在内容长度可变的情况下,使用结果往往不符合预期.

主要逻辑

主要逻辑集中在查询按钮的点击事件上

(注意:cursor.moveToFirst(),Long.valueOf()和Long.getLong()的用法.)

 mQueryButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//判断用户是否输入了城市名称if (!TextUtils.isEmpty(mCityName.getText())) {//首先查询本地数据库Uri uri = Uri.parse("content://com.example.janiszhang.weatherdemo.provider/weatherdata");Cursor cursor = getContentResolver().query(uri, null, "cityname = ?", new String[]{mCityName.getText() + ""}, null);if (cursor.moveToFirst()) {// 查询成功    //这里不可以使用cursor!= null来判断!!!!Log.i("zhangbz", cursor.getString(cursor.getColumnIndex("savetime")));if ((System.currentTimeMillis() - Long.valueOf(cursor.getString(cursor.getColumnIndex("savetime")))) < (1000*60)) {//这里不可以使用Long.getLong(),因为它返回的是系统属性的值,其参数是被请求的系统属性的名称//如果数据库中的数据没有过期,就从数据库中查询updateUIfromDatabase(cursor);} else {//如果数据库中的数据过期了,则通过网络查询并update到数据库shouldUpdate = true;try {httpArg = "city=" + URLEncoder.encode(mCityName.getText().toString(), "UTF-8");//中文需要编码} catch (UnsupportedEncodingException e) {e.printStackTrace();}new MyAsyncTask().execute(httpArg);//使用asynctask}} else {//网络查询并insert到数据库shouldUpdate = false;//需要inserttry {httpArg = "city=" + URLEncoder.encode(mCityName.getText().toString(), "UTF-8");//中文需要编码} catch (UnsupportedEncodingException e) {e.printStackTrace();}new MyAsyncTask().execute(httpArg);}SharedPreferences sp = getSharedPreferences("last", Context.MODE_PRIVATE);SharedPreferences.Editor editor = sp.edit();editor.putString("cityname", mCityName.getText().toString());editor.apply();//开启自动更新Intent intent = new Intent(MainActivity.this, AutoUpdateService.class);startService(intent);}}});

重点记录

使用Gson解析数据

            Gson gson = new Gson();WeatherDataStatus weatherDataStatus = gson.fromJson(s, WeatherDataStatus.class);

这里注意两个问题:
1.使用gson解析json数据时,不需要为整个json数据创建实体类,只需要为需要解析的数据定义变量和提供getter/setter方法.
2.注意区分什么是json数组:

        //json数组:中括号[{"这是json数组": "这是json数组"}, {"这是json数组": "这是json数组"}, {"这是json数组": "这是json数组"}]//注意和这种情况区分开{"这不是json数组": [{"这才是json数组": "这才是json数组"}, {"这才是json数组": "这才是json数组"}, {"这才是json数组": "这才是json数组"}]}

自动更新的实现

service需要由Activity启动,之后由service和receiver配合相互唤醒.

AutoUpdateService.class

public class AutoUpdateService extends Service{private String mCityname;@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {//在子线程中发起网络请求,将请求结果保存到数据库中new Thread(new Runnable() {@Overridepublic void run() {updateWeather();}}).start();//使用AlarmManager实现定时任务AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);int anHour = 8 * 60 *60 * 1000;//8小时long triggerAtTime = SystemClock.elapsedRealtime() + anHour;//service -> receiverIntent i = new Intent(this, AutoUpdateReceiver.class);PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0);manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi);return super.onStartCommand(intent, flags, startId);}//...}

AutoUpdateReceiver.class

public class AutoUpdateReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {//receiver->serviceIntent i = new Intent(context, AutoUpdateService.class);context.startService(i);}
}

contentprovider的练习

虽然用在这里很牵强,但是目的是练习嘛.
很久没有使用contentprovider,以下为基本使用方法.

public class MyProvider extends ContentProvider{public static final int WEATHERDATA_DIR = 0;public static final String AUTHORITY = "com.example.janiszhang.weatherdemo.provider";private static UriMatcher sUriMatcher;private MyDBHelper mMyDBHelper;static {sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);sUriMatcher.addURI(AUTHORITY, "weatherdata", WEATHERDATA_DIR);}@Overridepublic boolean onCreate() {mMyDBHelper = new MyDBHelper(getContext(),  "weatherDataDB.db", null, 1);return true;}@Nullable@Overridepublic Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {SQLiteDatabase db = mMyDBHelper.getReadableDatabase();Cursor cursor = null;switch (sUriMatcher.match(uri)) {case WEATHERDATA_DIR:cursor = db.query("weatherdata", projection, selection, selectionArgs, null, null, sortOrder);break;}return cursor;}@Nullable@Overridepublic String getType(Uri uri) {switch (sUriMatcher.match(uri)) {case WEATHERDATA_DIR:return "vnd.android.cursor.dir/vnd.com.example.janiszhang.weatherdemo.provider.weatherdata";}return null;}@Nullable@Overridepublic Uri insert(Uri uri, ContentValues values) {SQLiteDatabase db = mMyDBHelper.getReadableDatabase();Uri uriReturn = null;switch (sUriMatcher.match(uri)) {case WEATHERDATA_DIR:long newId = db.insert("weatherdata", null, values);uriReturn = Uri.parse("content://" + AUTHORITY + "/weatherdata/" + newId);break;}return uriReturn;}@Overridepublic int delete(Uri uri, String selection, String[] selectionArgs) {return 0;}@Overridepublic int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {SQLiteDatabase db = mMyDBHelper.getWritableDatabase();int updateRows = 0;switch (sUriMatcher.match(uri)) {case WEATHERDATA_DIR:updateRows = db.update("weatherdata", values, selection, selectionArgs);break;}return updateRows;}
}

github地址:https://github.com/zhangbz/WeatherDemo

总结:写这个demo,把四大组件都用到了,把基本用法复习了一遍,温故知新.

转载于:https://www.cnblogs.com/happyhacking/p/5264168.html

android开发练习:天气应用相关推荐

  1. 基于Android实现的天气预测APP

    基于Android开发的天气预测APP 一.相关技术 1.1 网络 网络数据源使用 Retrofit 库访问彩云 API 提供的 Webservice 接口来实现. Retrofit 通过封装络请求和 ...

  2. 用于android天气开发的背景图,Android开发天气预报APP的设计与实现毕业设计.pdf

    摘要 随着移动互联网技术和通信技术的发展,智能手机几乎成为人们 生活的必需品.近年来,Android系统已经成为智能手机中用户量最 多的操作系统.通过Android程序开发和设计天气预报手机应用,可 ...

  3. Compose Android 开发终极挑战赛: 天气应用

    前因后果 Compose beta 版发布也快一个月了,Google 官方发起的 Android 开发挑战赛也举办到了最后一期,四期的挑战分别是: 第一期挑战是做一个领养宠物的应用,全球一共有五百份礼 ...

  4. 应用程序基础知识:activity和intent——Android开发秘籍

    应用程序基础知识:activity和intent --Android开发秘籍 v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#defaul ...

  5. android开发模式,Android开发中无处不在的设计模式

    Android开发中无处不在的设计模式――单例模式 Android开发中无处不在的设计模式――Builder模式 前面介绍了单例模式和Builder模式,有兴趣的见上面两个链接,这篇文章侧重介绍1下视 ...

  6. Android开发中常见的设计模式

    对于开发人员来说,设计模式有时候就是一道坎,但是设计模式又非常有用,过了这道坎,它可以让你水平提高一个档次.而在android开发中,必要的了解一些设计模式又是非常有必要的.对于想系统的学习设计模式的 ...

  7. 《Android开发案例驱动教程》

    <Android开发案例驱动教程> 作者:关东升,赵志荣 Java或C++程序员转变成为Android程序员 采用案例驱动模式展开讲解知识点,即介绍案例->案例涉及技术->展开 ...

  8. Android开发笔记(一百一十八)自定义悬浮窗

    WindowManager 在前面< Android开发笔记(六十六)自定义对话框>中,我们提到每个页面都是一个Window窗口,许多的Window对象需要一个管家来打理,这个管家我们称之 ...

  9. Android开发学习持续更新中

    Android开发 单个Activity界面内的操作 控件1TextView控件使用 控件2Button控件使用 1首先对于android的按键格式 2对按键监听事件进行绑定 控件3EditText文 ...

  10. Android开发:开源库集合

    开源库大全 目录 抽屉菜单 ListView WebView SwitchButton 按钮 点赞按钮 进度条 TabLayout 图标 下拉刷新 ViewPager 图表(Chart) 菜单(Men ...

最新文章

  1. 关于hql一些不常见但好用的技巧(个人总结)
  2. 【Codeforces Round #767 (Div. 2)】 C. Meximum Array 题解
  3. C#中StringBuilder类的使用
  4. 《实用》secureCRT远程连接linux虚拟机-突然连接不上-解决办法
  5. redis存储新闻列表_Redis对象——集合(Set)
  6. 2007高考:考生要根据家庭经济条件慎重填报按办学成本收费的高校及专业
  7. tensorflow2.0学习(一)
  8. Caffe中如果高效实现卷积层
  9. 使用 HTML5 File API 实现client log
  10. 吴陆 java,成年人的世界,崩溃无声。
  11. 学python能做什么-学了Python都能干什么,哪个最赚钱?
  12. 中国工业行业分类英文翻译
  13. 开源iTunes替代品– aTunes
  14. 路飞学城mysql练习
  15. PhalAPI学习笔记拓展篇 ——— 基于MySQL数据库交互题目
  16. java 动态定时提醒_java实现定时提醒功能
  17. quarz定时任务 spring整合quartz
  18. 谈谈浏览器中富文本编辑器的技术演进
  19. 中国三大互联网巨头陷入移动战争
  20. linux批量重命名脚本,Mac / Linux Shell 批量重命名的方法总览

热门文章

  1. pycharm调试步骤(详细)
  2. 类的加载器ClassLoader及其示例
  3. 电脑已安装软件提取安装包_SPSS 24,软件安装包及安装教程
  4. 凸优化第三章凸函数 3.6关于广义不等式的凸性
  5. mysql 指定驱动表_了解MySQL联表查询中的驱动表,优化查询,以小表驱动大表
  6. Raki的读paper小记:Word2Vec
  7. 940mx黑苹果驱动_黑苹果intel网卡驱动方法
  8. PHP MD5 SHA1 比较 漏洞绕过
  9. 拦截器(Interceptor)和过滤器(Filter)区别
  10. 第二章:WebDriver 打开Firefox浏览器 和 Chrome 浏览器