udacity android 实践笔记: lesson 4 part b

2024-04-11 14:58

本文主要是介绍udacity android 实践笔记: lesson 4 part b,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

udacity android 实践笔记: lesson 4 part b


作者:干货店打杂的 /titer1 /Archimedes
出处:https://code.csdn.net/titer1
联系:1307316一九六八(短信最佳)
声明:本文采用以下协议进行授权: 自由转载-非商用-非衍生-保持署名|Creative Commons BY-NC-ND 3.0 ,转载请注明作者及出处。
tips:https://code.csdn.net/titer1/pat_aha/blob/master/Markdown/android/


摘要

  • 完全展示content provider添加的过程
  • 动态展示android单元测试的过程
    动图出没喔!o(^▽^)o,动图在最后

overviw 图

还是老图,(create / insert /query)

下面 我们开始 content provider的学习

复习四大 组件content provider
service
broadcast provider
actvity 

本章 overview

4.07 init code for content provider


- 测试打桩函数就占了大半
- 然后传统的函数里面修改了 weatherContrace
- 增加了 weatherProvider
- 修改了 fetchweatherTask函数,代码的来源是
从 forececastFragment代码拆解出来的。
- 除了修改weatherContrace,其他文件都是 新增加的

关键词 uri

weatherContract里面增加的最多就是生成uri的函数

/* Inner class that defines the table contents of the location table */public static final class LocationEntry implements BaseColumns {...public static Uri buildLocationUri(long id) {return ContentUris.withAppendedId(CONTENT_URI, id);}}===
    /* Inner class that defines the table contents of the weather table */public static final class WeatherEntry implements BaseColumns {...public static Uri buildWeatherLocation(String locationSetting) {return null;}public static Uri buildWeatherLocationWithStartDate(String locationSetting, long startDate) {long normalizedDate = normalizeDate(startDate);return CONTENT_URI.buildUpon().appendPath(locationSetting).appendQueryParameter(COLUMN_DATE, Long.toString(normalizedDate)).build();}public static Uri buildWeatherLocationWithDate(String locationSetting, long date) {return CONTENT_URI.buildUpon().appendPath(locationSetting).appendPath(Long.toString(normalizeDate(date))).build();}public static String getLocationSettingFromUri(Uri uri) {return uri.getPathSegments().get(1);}public static long getDateFromUri(Uri uri) {return Long.parseLong(uri.getPathSegments().get(2));}public static long getStartDateFromUri(Uri uri) {String dateString = uri.getQueryParameter(COLUMN_DATE);if (null != dateString && dateString.length() > 0)return Long.parseLong(dateString);elsereturn 0;}}
}

4.08 uri location with weather

仅2处更新

1/2 weatherContract

        /*Student: This is the buildWeatherLocation function you filled in.*/public static Uri buildWeatherLocation(String locationSetting) {return CONTENT_URI.buildUpon().appendPath(locationSetting).build();//上一版本这里返回空值}

##2/2 test

仅仅打开 这里的注释
“` java
/*
Students: This is NOT a complete test for the WeatherContract — just for the functions
that we expect you to write.
*/
public class TestWeatherContract extends AndroidTestCase {

// intentionally includes a slash to make sure Uri is getting quoted correctly
private static final String TEST_WEATHER_LOCATION = "/North Pole";
private static final long TEST_WEATHER_DATE = 1419033600L;  // December 20th, 2014/*Students: Uncomment this out to test your weather location function.*/
public void testBuildWeatherLocation() {Uri locationUri = WeatherContract.WeatherEntry.buildWeatherLocation(TEST_WEATHER_LOCATION);assertNotNull("Error: Null Uri returned.  You must fill-in buildWeatherLocation in " +"WeatherContract.",locationUri);assertEquals("Error: Weather location not properly appended to the end of the Uri",TEST_WEATHER_LOCATION, locationUri.getLastPathSegment());assertEquals("Error: Weather location Uri doesn't match our expected result",locationUri.toString(),"content://com.example.android.sunshine.app/weather/%2FNorth%20Pole");
}

}
“`

4.09 write uri matcher

1/2 weatherProvider

这是框架里面的代码,更新一处

    /*Students: Here is where you need to create the UriMatcher. This UriMatcher willmatch each URI to the WEATHER, WEATHER_WITH_LOCATION, WEATHER_WITH_LOCATION_AND_DATE,and LOCATION integer constants defined above.  You can test this by uncommenting thetestUriMatcher test within TestUriMatcher.*/static UriMatcher buildUriMatcher() {// I know what you're thinking.  Why create a UriMatcher when you can use regular// expressions instead?  Because you're not crazy, that's why.// All paths added to the UriMatcher have a corresponding code to return when a match is// found.  The code passed into the constructor represents the code to return for the root// URI.  It's common to use NO_MATCH as the code for this case.final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);final String authority = WeatherContract.CONTENT_AUTHORITY;// For each type of URI you want to add, create a corresponding code.matcher.addURI(authority, WeatherContract.PATH_WEATHER, WEATHER);matcher.addURI(authority, WeatherContract.PATH_WEATHER + "/*", WEATHER_WITH_LOCATION);matcher.addURI(authority, WeatherContract.PATH_WEATHER + "/*/#", WEATHER_WITH_LOCATION_AND_DATE);matcher.addURI(authority, WeatherContract.PATH_LOCATION, LOCATION);return matcher;}

2/2 test

依然是已经写好的测试代码框架,这里仅仅打开注释

public class TestUriMatcher extends AndroidTestCase {
.../*Students: This function tests that your UriMatcher returns the correct integer valuefor each of the Uri types that our ContentProvider can handle.  Uncomment this when you areready to test your UriMatcher.*/public void testUriMatcher() {UriMatcher testMatcher = WeatherProvider.buildUriMatcher();assertEquals("Error: The WEATHER URI was matched incorrectly.",testMatcher.match(TEST_WEATHER_DIR), WeatherProvider.WEATHER);assertEquals("Error: The WEATHER WITH LOCATION URI was matched incorrectly.",testMatcher.match(TEST_WEATHER_WITH_LOCATION_DIR), WeatherProvider.WEATHER_WITH_LOCATION);assertEquals("Error: The WEATHER WITH LOCATION AND DATE URI was matched incorrectly.",testMatcher.match(TEST_WEATHER_WITH_LOCATION_AND_DATE_DIR), WeatherProvider.WEATHER_WITH_LOCATION_AND_DATE);assertEquals("Error: The LOCATION URI was matched incorrectly.",testMatcher.match(TEST_LOCATION_DIR), WeatherProvider.LOCATION);}

···

4.10 register content provider

1/2

这里仅仅使能(打开注释) testProviderRegistry


public class TestProvider extends AndroidTestCase {.../*This test checks to make sure that the content provider is registered correctly.Students: Uncomment this test to make sure you've correctly registered the WeatherProvider.*/public void testProviderRegistry() {PackageManager pm = mContext.getPackageManager();// We define the component name based on the package name from the context and the// WeatherProvider class.ComponentName componentName = new ComponentName(mContext.getPackageName(),WeatherProvider.class.getName());try {// Fetch the provider info using the component name from the PackageManager// This throws an exception if the provider isn't registered.ProviderInfo providerInfo = pm.getProviderInfo(componentName, 0);// Make sure that the registered authority matches the authority from the Contract.assertEquals("Error: WeatherProvider registered with authority: " + providerInfo.authority +" instead of authority: " + WeatherContract.CONTENT_AUTHORITY,providerInfo.authority, WeatherContract.CONTENT_AUTHORITY);} catch (PackageManager.NameNotFoundException e) {// I guess the provider isn't registered correctly.assertTrue("Error: WeatherProvider not registered at " + mContext.getPackageName(),false);}}}

androidManifest update

        <provider
            android:authorities="com.example.android.sunshine.app"android:name=".data.WeatherProvider" />

小憩

增加provider布凑
- 估计要从 1代版本代码 和 2代代码 进行比较

聪明的编译器

智能提示
android 在debug模式下,有很有趣的话题在里面,比如变量值的提示
还有搜索字符时,主动过滤注释里面字符

test ok 单元测试的方法 && testPractise


并且 我没有选右键触发,而是直接 run ( shift f10)
(4a-28 )里面单元测试的方法,完全可以复现


- 展现运行的配置
- 展示出错情形如何定位错误
- 展示正常情况

使用的是 sunshine version2 的4.02的代码,code: testPractise
todo 实践后思考
空白的android test工程是怎样的?
4.02章节里面,命名只有有效的3个testcase,怎么显示有6个testcase ?

testDb之testCreateDb

4.04 (git version) delete the testPractise,

实际运行记录:
我在所有的 assertTrue,assertFalse,assertEqual
位置都下了断点,但是只有testDb中的testCreateDb 被触发,
数字上,run窗口显示的“6 of 6”ok,
但6个中的4个被触发,
我怀疑这个6是不是显示过时

testdb之testLocationTable

测试完全通过.

  • 该函数完整的调用了db的操作函数
    • insert
    • query

并且有趣的是调用了TestUtilities.validateCurrentRecord。
(这里面还有2个assert,这里面的断言终于被触发了)

这是我观察中
testUtilities类中函数的第一次调用,
上一轮,我在这个类的static函数里面设置断点,
都没有被调用。

还有这个类testUtilities提供了数据库插入的样本数据

todo
实践后思考:
既然单元测试都是利用AndroidTestCase
那么为什么每次都是testDb被调用,
而其他AndroidTestCase的继承类testUtilities 没有被直接调用.

testWeatherTable 和重构 testLocationTable

4.06 lesson,
而且有趣的是前者内部调用调用了
locationTable的内容

竟然所有的测试通过了

todo 内容深入分析// Fifth Step: Validate the location QueryTestUtilities.validateCurrentRecord("testInsertReadDb weatherEntry failed to validate",weatherCursor, weatherValues);

小憩

github 前6个小节,就是认识单元测试

单元测试的魔力很大啊,这里

后续

from 4.06 -4.10 (github)
测试函数有:
- test weatherContract
- test uri matcher
- test Provider
- test providerRegistery

构造一个content provider,每个模块都不能马虎

晚安 小憩

至少方向是光明的

下一天 复习

解释 前面 为什么 不是 全部的uri都被命中

再看 weather provider 和 testProvider的演示
作者是逐一功能的enable,逐一测试。逐渐深入

几乎每种testProvider的函数(query/getType/insert/updat)
都含有uri matcher的筛选

新近发现 可以 查看 每一个测试的内容:

video 4b-24 是个阶段总结

bulkinsert 其实利用了事务,只有endtrancsation 才执行操作

小节

小节:整章节 就是 uri 使用
- define uri
- update uri(feflect to number)
- uri matcher (I think ,here addmatch)
- implement (I think, sUriMatcher.match(uri);)

说到,开源很多 封装了 content provider ? toco
如何理解 notification oserver ..here

整合

至此,我们的content provider 还没有和 database 联合起来。
操作不是 test*.java,也不主要是 weatherprovider里面

我们将精力集中到 FetchweatherTask
- addlocation
- getWeatherDataFromJson insert + query part
(网络收报后的处理例程)

看到凡是使用了getContentResolver的地方,都是利用了contentprovider的地方,

最后

为了ui theread 更加流畅,引出Loader
至此,我们的video 来到4b的借书,代码
代码范围是:

todo 附code

小节

android 你好
android 再见
呵呵,本博客android暂停更新,如果有兴趣可以短信联系

这篇关于udacity android 实践笔记: lesson 4 part b的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/894403

相关文章

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动

论文阅读笔记: Segment Anything

文章目录 Segment Anything摘要引言任务模型数据引擎数据集负责任的人工智能 Segment Anything Model图像编码器提示编码器mask解码器解决歧义损失和训练 Segment Anything 论文地址: https://arxiv.org/abs/2304.02643 代码地址:https://github.com/facebookresear

数学建模笔记—— 非线性规划

数学建模笔记—— 非线性规划 非线性规划1. 模型原理1.1 非线性规划的标准型1.2 非线性规划求解的Matlab函数 2. 典型例题3. matlab代码求解3.1 例1 一个简单示例3.2 例2 选址问题1. 第一问 线性规划2. 第二问 非线性规划 非线性规划 非线性规划是一种求解目标函数或约束条件中有一个或几个非线性函数的最优化问题的方法。运筹学的一个重要分支。2

【C++学习笔记 20】C++中的智能指针

智能指针的功能 在上一篇笔记提到了在栈和堆上创建变量的区别,使用new关键字创建变量时,需要搭配delete关键字销毁变量。而智能指针的作用就是调用new分配内存时,不必自己去调用delete,甚至不用调用new。 智能指针实际上就是对原始指针的包装。 unique_ptr 最简单的智能指针,是一种作用域指针,意思是当指针超出该作用域时,会自动调用delete。它名为unique的原因是这个