Android-入门学习笔记-线程与并行

3

"你感觉到了吗?" 应用的 GitHub Repo 地址.

6

Android 系统能够同时运行多个线程, 因此可以相互独立的处理 两组或多组任务。如果有多个线程需要运行, Android 还会就何时运行哪些线程进行优先级排序, 并确定各线程的运行时长。

线程也知道如何保存其位置。它不仅会记录所有变量的值, 还会记住完成当前正在执行的指令 会调用的函数系列: 即能够重新完成工作所需的一切内容。

构建所有多线程应用程序都是为了能够同时运行两个或 多个进程。现代编程语言和 CPU 旨在利用多线程, 因此,在 Android 平台上构建应用并没有什么不同!

有关更进一步的讨论,请参阅“进程与线程”这篇文章

还有另一篇关于“保持你的应用及时响应”这一话题的开发者指南

7

我强烈建议观看关于线程的 Android Performance Patterns Youtube视频,演讲者为 Google 技术推广工程师 Colt McAnlis。

 8

设计提示:理论上,应用中的内容是即时加载的。如果 未加载,请尝试允许用户与应用的其他部分进行交互, 以便用户不会坐在那里无所事事,或是观看进度条。如果应用中没有 任何有意义的事可供用户去做,材料设计规范提供了有关如何针对需要花费很长时间加载的内容来 显示进度的指南。

 10

AsyncTask 文档

使用 AsyncTask 进行后台处理

 11

要检查 NetworkConnect 应用,可以从开发者站点下载代码。或者 在 Android Studio 内,单击文件 (File) > 新建 (New) > 导入示例 (Import Sample),并搜索 "Network Connect" 示例。

内部类

12

提示:如果你陷入僵局,需要更详细的步骤,请参阅此 列表。但是,首先要尝试自己完成任务!

  1. 创建 AsyncTask 的子类作为 MainActivity 类中的 私有内部类。 实现 doInBackground() 方法来获取地震数据并 返回结果。 实现 onPostExecute() 方法以根据我们的结果 更新 UI。

  2. 在 MainActivity onCreate() 方法中创建我们的内部类的实例, 并执行。

 13

我要指出的是,目前,我们的代码是针对最佳 情况编写的。我们假设 EarthquakeAsyncTask 通过我们预期的输入调用, 且在执行网络请求时未出现任何 错误。

如果…

  • 未来使用此应用的队友更改了代码,并试图以不输入任何参数的方式来执行 EarthquakeAsyncTask,这将如何?我们的应用可能会崩溃,因为它假设至少为任务输入 1 个字符串。
  • USGS 的计算机存在内部服务器错误,无法将响应解析为 Event 对象,这又将如何?我们的应用将尝试使用无效或空 Event 对象更新 UI。

我们试图进一步验证我们的应用,以便我们或接触代码的任何其他开发者 不会不小心在应用中导致 bug 或崩溃。 为此,我们需要将当前类以外的代码编写假设、 以及超出我们控制的假设 最小化。

如果我们可以接受任何输入(零输入、1 个 输入、2 个输入等)或处理任何意外行为(服务器 做出有效或无效响应),并做出得体的处理而不使应用崩溃, 那么就说明我们的代码变得更加稳健。

为了这个目的,请对 "你感觉到了吗?" 应用进行下列修改, 以处理 EarthquakeAsyncTask 中空或 Null 情况。

在 doInBackground 方法中,检查 url 数组是否至少具有 1 个 条目且第一个条目不为空。如果数组长度为 0 或第一个条目为空,则通过返回 null 提早离开 此方法。我们需要返回 null,因为需要有对象 作为返回值。如果有 1 个有效字符串 URL,则继续 获取数据。

  protected Event doInBackground(String... urls) {
      // 如果不存在任何 URL 或第一个 URL 为空,切勿执行请求。 if (urls.length < 1 || urls[0] == null) { return null; } Event result = Utils.fetchEarthquakeData(urls[0]); return result; } 

在 onPostExecute 方法中,如果不存在地震结果,则提早 返回。

  protected void onPostExecute(Event result) { // 如果不存在任何结果,则不执行任何操作。 if (result == null) { return; } updateUi(result); } 

下面是完整的 EarthquakeAsyncTask 类声明。

  /**
  * {@link AsyncTask} 用于在后台线程上执行网络请求,然后
  * 使用响应中的第一个地震更新 UI。
  */
  private class EarthquakeAsyncTask extends AsyncTask<String, Void, Event> { /** * 此方法在后台线程上激活(调用),因此我们可以执行 * 诸如做出网络请求等长时间运行操作。 * * 因为不能从后台线程更新 UI,所以我们仅返回 * {@link Event} 对象作为结果。 */ protected Event doInBackground(String... urls) { // 如果不存在任何 URL 或第一个 URL 为空,切勿执行请求。 if (urls.length < 1 || urls[0] == null) { return null; } Event result = Utils.fetchEarthquakeData(urls[0]); return result; } /** * 此方法是在完成后台工作后,在主 UI 线程上 * 激活的。 * * 可以在此方法内修改 UI。我们得到 {@link Event} 对象 * (该对象从 doInBackground() 方法返回),并更新屏幕上的视图。 */ protected void onPostExecute(Event result) { // 如果不存在任何结果,则不执行任何操作。 if (result == null) { return; } updateUi(result); } } 

你编译并运行应用时,应该看起来是这样的。

 
 

要在 GitHub 上浏览“你感觉到了吗?”应用的完整和最终状态, 请单击此处

15

所以最近我们看到 List 与 ArrayList 的大量使用。它们 二者的使用方式看起来相似,但此处 有何区别呢?

这里的根本区别很简单:List 是 接口,而 ArrayList 是具体类。无法创建 List 的对象实例,因为它是接口 且其方法未实现。但是可以创建 ArrayList 的对象实例并为 E 指定泛型参数, 因为它是具体类。

例如:要使用 Earthquake 数据类型定义 ArrayList 的实例, 可以编写:

  ArrayList<Earthquake> earthquakeList = new ArrayList<Earthquake>();

这将会运行良好。你也可以 在 List 数据类型的变量中存储该对象:

  List<Earthquake> earthquakeList = new ArrayList<Earthquake>();

这样做的原因是为了具有更大的灵活性:

与 ArrayList 类相似的另一种类型的类是 LinkedList,此类 也可用于实现 List 接口。这两种类具有相似的方法 和实现策略,但二者内部详细信息和存储器 略有不同。如果出于某种原因,你的应用会 因使用 LinkedList 而非 ArrayList 而从中受益,则 仅在实例的定义位置进行更新会很容易, 并且所有 List 代码仍能正常工作!下面是一个例子:

  List<Earthquake> earthquakeList = new ArrayList<Earthquake>();
  earthquakeList.add(foo);

变为:

  List<Earthquake> earthquakeList = new LinkedList<Earthquake>();
  earthquakeList.add(foo);

并且它仍能工作!

在所有情况下,最佳的做法是,只要需要列表对象(不管是 ArrayList 还是 LinkedList)时,便使用 List, 这样你就可以 保持代码的灵活性。

要了解有关这方面的更多信息,请阅读 List 接口的文档, 并查看 何时使用 List 和何时可能使用 ArrayList 与 LinkedList 中有关 StackOverflow 的热烈讨论。

16

是时候挽起袖子开始编码了!

修改 地震报告应用,以做出对此 URL 的网络请求。 此查询将为你提供全球最近发生的震级至少为 6 级 的 10 大地震。http://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&eventtype=earthquake&orderby=time&minmag=6&limit=10

收到响应后,解析 JSON,然后更新 应用中的列表。

提示 #1:在进行这些增量更改时, 尝试尽可能多地编译并运行应用。否则,最后可能会有大量错误 需要解决。

提示 #2:请记住,你可以回过来参考 "Soonami" 和 "Did You Feel it" 示例应用。

如果你需要更多调试提示,请查看此论坛线程,其他 学生会在这里就如何完成此长编码任务发表建议。

来自你们课程导师的备注: 上面那个 HTTP 链接,有可能会返回 301 的状态码,是因为请求被重定向到HTTPS了。浏览器通常会自动处理这个重定向,但是我们现在的代码请求并不会自动处理这个问题,所以把链接改成HTTPS即可。

顺便,更多关于 HTTP 状态码( HTTP Status Code )的介绍可以看这里,更多关于 HTTPS 可以看这里。当然去看Wikipedia的介绍也是极好的。

17

“Android 性能模式”视频

 18

作为提示,以下是可能的答案选项:

onLoaderReset()

onCreateLoader()

LoaderManager.LoaderCallbacks

LoaderManager

onLoadFinished()

getLoaderManager().initLoader(0, null, this);

有关详细信息,请查看此处:

Loader 开发者指南

LoaderManager

LoaderCallbacks

19

作为提示,以下是可能的答案选项:

AsyncTaskLoader

List

loadInBackground()

如果遇到困难,请查看以下资源:

AsyncTaskLoader 示例

Loader 开发者指南

LoaderManager

LoaderManager.LoaderCallbacks

 21

当 地震报告应用具有在整个代码中添加的日志消息时, 请测试以下场景:

  • 旋转设备
  • 转至主屏幕并返回到应用
  • 按返回按钮
  • 打开近期任务
  • 切换到不同的应用
  • 返回到应用
  • 走进自己的场景!

 

22

可选:你是否了解尝试将空状态变为 愉快用户体验的 Android 应用?在论坛上 分享屏幕截图。

ListView setEmptyView() 方法。

材料设计原则 - 与空状态有关。

 23

提示:在常见 Android 视图备忘表中查看 ProgressBar 视图的示例。

Material Design 进度与活动

提示:执行以下 2 个测试,检查加载指示符 将通向地震结果列表还是 空视图。

测试 #1:强制后台线程睡眠 2 秒钟

为强制后台线程睡眠 2 秒钟,我们 暂时模拟一个极慢的网络响应时间我们 “假设”耗时很久来获取响应。这 可以较正常情况下延长屏幕上加载下拉菜单的时间, 以便我们查看。

在 QueryUtils.java 文件的 fetchEarthquakeData() 方法内, 将此代码段添加到方法顶部。将方法中的 其余部分代码保持不变。强制后台线程 暂停执行并等待 2 秒钟(2000 毫秒), 然后再继续执行此方法中的其余代码行。 如果尝试单独添加 Thread.sleep(2000); 方法调用, Android Studio 将告知存在未捕获的异常,所以 我们需要使用 try/catch 块将该语句括起来。

在 QueryUtils.java 中:

  public static List<Earthquake> fetchEarthquakeData(String requestUrl) {

      try {
         Thread.sleep(2000);
      } catch (InterruptedException e) { e.printStackTrace(); } … } 

现在,当运行应用时,将显示 2 秒钟的加载指示符, 然后才出现地震列表。

测试 #2:假设没有从服务器返回任何结果

在 EarthquakeActivity onLoadFInished 方法中,暂时注释掉 向适配器添加地震数据的 代码行。这会使应用看起来像是没有要显示的地震 结果。

在 QueryUtils.java 中:

  @Override
  public void onLoadFinished(Loader<List<Earthquake>> loader, List<Earthquake> earthquakes) { ... // 如果存在 {@link Earthquake} 的有效列表,则将其添加到适配器的 // 数据集。这将触发 ListView 执行更新。 if (earthquakes != null && !earthquakes.isEmpty()) { // mAdapter.addAll(earthquakes); } } 

现在,当运行应用时,将显示 2 秒钟的加载指示符, 然后出现显示“未发现地震。(No earthquakes found.)”的空状态

24

 

转载于:https://www.cnblogs.com/infocodez/p/8394972.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值