来源:网易云课堂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() {
@Override
public 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;//需要insert
try {
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
@Override
public IBinder onBind(Intent intent) {
return null;
} @Override
public int onStartCommand(Intent intent, int flags, int startId) {
//在子线程中发起网络请求,将请求结果保存到数据库中
new Thread(new Runnable() {
@Override
public void run() {
updateWeather();
}
}).start(); //使用AlarmManager实现定时任务
AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
int anHour = 8 * 60 *60 * 1000;//8小时
long triggerAtTime = SystemClock.elapsedRealtime() + anHour;
//service -> receiver
Intent 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{
@Override
public void onReceive(Context context, Intent intent) {
//receiver->service
Intent 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);
}
@Override
public boolean onCreate() {
mMyDBHelper = new MyDBHelper(getContext(), "weatherDataDB.db", null, 1);
return true;
} @Nullable
@Override
public 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
@Override
public 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
@Override
public 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;
} @Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
} @Override
public 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,把四大组件都用到了,把基本用法复习了一遍,温故知新.

android开发练习:天气应用的更多相关文章

  1. Android经典项目开发之天气APP实例分享

    原文:Android经典项目开发之天气APP实例分享 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/mzc186/article/details/5 ...

  2. 50个Android开发人员必备UI效果源码[转载]

    50个Android开发人员必备UI效果源码[转载] http://blog.csdn.net/qq1059458376/article/details/8145497 Android 仿微信之主页面 ...

  3. 【Mood-12】Android开发相关书籍推荐

    新年伊始,找到Android进阶干货若干,2015拜读. 1.Android应用UI设计模式 目前,谷歌Android操作系统在移动市场中风头正劲,并且未来发展势不可挡.<Android应用UI ...

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

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

  5. Android开发心得(转)

    前言: 很早以前,就听人说过android以后会火起来,作为一个前瞻性对它有所了解会是一个转型的好机会,javaweb太成熟饱和了,现在市面上各种android手机层出不穷,网上各种android视频 ...

  6. Android解析中国天气网的Json数据

    在Android开发中.一般的APP都是通过获取server端的数据来更新UI.从server获取到的数据能够是Json.它的数据量要比XML要小,这里解析中国天气网上获取的数据,尽管已经不再更新了. ...

  7. Android开发周报:反编译对抗研究、动手制作智能镜子

    新闻 <Android Wear落地中国 谷歌增强安卓生态控制力> :9月8日,由摩托罗拉推出的智能手表Moto 360二代作为国内发售的第一款搭载官方Android Wear的设备,正式 ...

  8. Android开发周报:Android L默认加密用户数据

    Android开发周报:Android L默认加密用户数据 新闻 <iCloud前车之鉴,Android L默认开启加密功能>:iCloud 艳照风波再起,第二波女星照片流出,大量女星的裸 ...

  9. Android开发10:传感器器及地图相关应用

    前言 啦啦啦~各位小伙伴们好~经过这一学期的Android知识的学习,我们学到了很多和Android开发相关的知识,这一学期的学习也要告一段落了. 一起进入我们今天的相关内容~这次我们将一起学习使用 ...

随机推荐

  1. Net.Sockets

    #region 程序集 System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 // C:\Program ...

  2. c# 中基类变量指向派生类对象的实例化

    这一篇文章转载自:http://www.xuebuyuan.com/390279.html 我对这篇文章进行了一一的验证,确实是这样子的,也明白了很多东西,觉得很有用,转载过来希望能够帮助大家. 1. ...

  3. C语言学习017:malloc和free

    malloc和free都包含在<stdlib.h>头文件中 局部变量由于存储在栈中,一旦离开函数,变量就会被释放,当我们需要将数据持久使用,就需要将数据保存到堆中,而在堆中申请内存空间就需 ...

  4. 从C#到Objective-C,循序渐进学习苹果开发(6)--视图控制器的使用

    本随笔系列主要介绍从一个Windows平台从事C#开发到Mac平台苹果开发的一系列感想和体验历程,本系列文章是在起步阶段逐步积累的,希望带给大家更好,更真实的转换历程体验.本篇主要开始介绍基于XCod ...

  5. GitHub简单教程

    Hello World程序是计算机编程中由来已久的惯例,这是一个当你在学习新事物的时候开始的一个简单的小练习.让我们开始GitHub的"Hello World". 你将学会: -  ...

  6. Castle ActiveRecord框架学习(二):快速搭建简单博客网站

    一.数据库 1.数据表 Category:类别标签表(字段Type=1为类别,Type=2为标签) Category_Post:类别标签与文章中间表 Post:文章表 Comment:评论表 2.数据 ...

  7. 【C#】第3章补充(一)如何在WPF中绘制正弦曲线

    分类:C#.VS2015 创建日期:2016-06-19 使用教材:(十二五国家级规划教材)<C#程序设计及应用教程>(第3版) 一.要点 本例子提前使用了教材第13章介绍的基本知识. 二 ...

  8. PYTHON3连接MYSQL数据库

    http://smilejay.com/2013/03/python3-mysql-connector/ Python 2.x 上连接MySQL的库倒是不少的,其中比较著名就是MySQLdb(Djan ...

  9. Delphi iOS 开启文件共享 UIFileSharingEnabled

    Apple 在 iOS 提供了文件共享(FileSharing)功能,让 App 有一个对外窗口的目录,透过 iTunes 可以任意管理这个目录的文档内容(可拖入文档,也能将文档拖出备份). 如果 A ...

  10. springmvc 配置多视图,返回jsp,velocity,freeMarker,tiles(模板)等等

    springmvc-servlet.xml配置 <!-- Velocity --> <bean id="velocityViewResolver" class = ...