来源:网易云课堂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. 微信公众号入门学习1_使用C#,ASP.NET APIController如何公众号接入服务器并启动开发者模式

    前言:  本文是以微信公众号中的订阅号(个人)来进行简单介绍,本人也是刚刚开始学习,有不足之处,欢迎批评指正. 先粘贴2个帮助链接: 入门指引:http://mp.weixin.qq.com/wiki ...

  2. 【要什么自行车】ASP.NET MVC4笔记03:调用编辑器 kindeditor

    参考:http://www.cnblogs.com/guzhongx/p/kindeditor.html 1.下载kindeditor,存放于Content文件夹下 <script src=&q ...

  3. jquery更改加载图片大小

    <script type="text/javascript"> $("img").css("width","80%&q ...

  4. springMVC分页,interceptor实现

    PageInterceptor.java @Intercepts({ @Signature(type = StatementHandler.class, method = "prepare& ...

  5. 51Node 1483----化学变换(暴力枚举)

    51Node  1483----化学变换 有n种不同的化学试剂.第i种有ai升.每次实验都要把所有的化学试剂混在一起,但是这些试剂的量一定要相等.所以现在的首要任务是把这些化学试剂的量弄成相等. 有两 ...

  6. 市面上常见的javaEE WEB服务软件

    常见的市面上web服务软件 Tomcat:轻量级的WEB应用程序服务器(开源),开源组织Apache的产品.免费的.支持部分的JavaEE规范.(servlet.jsp.jdbc,但ejb, rmi不 ...

  7. Verilog学习笔记简单功能实现(八)...............异步FIFO

    基本原理:       1.读写指针的工作原理 写指针:总是指向下一个将要被写入的单元,复位时,指向第1个单元(编号为0). 读指针:总是指向当前要被读出的数据,复位时,指向第1个单元(编号为0). ...

  8. [转载]OSI七层模型详解

    OSI 七层模型通过七个层次化的结构模型使不同的系统不同的网络之间实现可靠的通讯,因此其最主要的功能就是帮助不同类型的主机实现数据传输 . 完成中继功能的节点通常称为中继系统.在OSI七层模型中,处于 ...

  9. C语言的数据、常量和变量

    一.数据 图片文字等都是数据,在计算机中以0和1存储. (一)分类 数据分为静态数据和动态数据. ①. 静态数据:一些永久性的的数据,一般存储在硬盘中,只要硬盘没坏数据都是存在的.一般以文件的形式存储 ...

  10. PHP发短信 PEAR 包:Services_Sms

    PHP发短信 PEAR 包:Services_Sms 对于这种第三方库,PHP官方称之为PEAR,需要按照PEAR标准开发(标准URI). PEAR的优势:一键安装到php/lib/php目录,req ...