14

Similar documents
01_Service

新・解きながら学ぶJava

获取 Access Token access_token 是接口的全局唯一票据, 接入方调用各接口时都需使用 access_token 开发者需要进行妥善保存 access_token 的存储至少要保留 512 个字符空间 access_token 的有效期目前为 2 个小时, 需定时刷新, 重复

untitled

中 文 摘 要 智 慧 型 手 機 由 於 有 強 大 的 功 能, 以 及 優 渥 的 便 利 性, 還 能 與 網 路 保 持 隨 時 的 鏈 結 與 同 步 更 新, 因 此 深 受 廣 大 消 費 者 喜 愛, 當 然, 手 機 遊 戲 也 成 為 現 代 人 不 可 或 缺 的 娛 樂 之

chp6.ppt

Guava学习之Resources

Microsoft Word - 01.DOC

停止混流接口 请注意 : 该功能需要联系 ZEGO 技术支持开通 1 接口调用说明 http 请求方式 : POST/FORM, 需使用 https 正式环境地址 access_token=access_token (http

untitled

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP: ******************* * 关于 Java 测试试题 ******

09 (File Processes) (mkdir) 9-3 (createnewfile) 9-4 (write) 9-5 (read) 9-6 (deletefile) 9-7 (deletedir) (Exercises)

EJB-Programming-3.PDF

EJB-Programming-4-cn.doc

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

Chapter 9: Objects and Classes

基于ECO的UML模型驱动的数据库应用开发1.doc

Java

Java java.lang.math Java Java.util.Random : ArithmeticException int zero = 0; try { int i= 72 / zero ; }catch (ArithmeticException e ) { // } 0,

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

1.JasperReport ireport JasperReport ireport JDK JDK JDK JDK ant ant...6

RxJava

(TestFailure) JUnit Framework AssertionFailedError JUnit Composite TestSuite Test TestSuite run() run() JUnit

3.1 num = 3 ch = 'C' 2

Android Service

Android + WebService

epub83-1

mvc

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

使用MapReduce读取XML文件

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 ->

untitled

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

Java Access 5-1 Server Client Client Server Server Client 5-2 DataInputStream Class java.io.datainptstream (extends) FilterInputStream InputStream Obj

JavaIO.PDF

Microsoft Word - 第3章.doc

建立Android新專案

Microsoft Word - Broker.doc

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

untitled

《大话设计模式》第一章

PowerPoint 演示文稿

多媒體應用 13 新增專案並完成版面配置 <ExMusic01> <activity_main.xml> ImageView ID imgplay ImageView ID imgstop ImageView ID imgfront TextView ID txtsong TextView ID t

前言 C# C# C# C C# C# C# C# C# microservices C# More Effective C# More Effective C# C# C# C# Effective C# 50 C# C# 7 Effective vii

untitled

6-1 Table Column Data Type Row Record 1. DBMS 2. DBMS MySQL Microsoft Access SQL Server Oracle 3. ODBC SQL 1. Structured Query Language 2. IBM

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

Android线程和进程

untitled

x MapReduce A Italic URL Constant width Constant width bold Constant width italic 這個圖示代表提示或建議 這個圖示代表一般註解

建模与图形思考

Chapter 9: Objects and Classes

RunPC2_.doc

Guava学习之CharSequenceReader

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入

ebook 132-2

使 用 Java 语 言 模 拟 保 险 箱 容 量 门 板 厚 度 箱 体 厚 度 属 性 锁 具 类 型 开 保 险 箱 关 保 险 箱 动 作 存 取 款

Microsoft PowerPoint - string_kruse [兼容模式]

untitled

untitled

1: public class MyOutputStream implements AutoCloseable { 3: public void close() throws IOException { 4: throw new IOException(); 5: } 6:

基于CDIO一体化理念的课程教学大纲设计

OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课

使用Cassandra和Spark 2.0实现Rest API服务

Hadoop&Spark解决二次排序问题(Hadoop篇)

res/layout 目录下的 main.xml 源码 : <?xml version="1.0" encoding="utf 8"?> <TabHost android:layout_height="fill_parent" xml

ASP.NET实现下拉框二级联动组件

TopTest_Adminstrator.doc

59 1 CSpace 2 CSpace CSpace URL CSpace 1 CSpace URL 2 Lucene 3 ID 4 ID Web 1. 2 CSpace LireSolr 3 LireSolr 3 Web LireSolr ID

chapter 2 HTML5 目錄iii HTML HTML HTML HTML HTML canvas

Microsoft Word - PHP7Ch01.docx

提纲 1 2 OS Examples for 3

Socket Socket TcpClient Socket.Connect TcpClient.Connect Socket.Send / Receive NetworkStream 6-5

雲端 Cloud Computing 技術指南 運算 應用 平台與架構 10/04/15 11:55:46 INFO 10/04/15 11:55:53 INFO 10/04/15 11:55:56 INFO 10/04/15 11:56:05 INFO 10/04/15 11:56:07 INFO

建模与图形思考

RUN_PC連載_12_.doc

本章学习目标 小风 Java 实战系列教程 SpringMVC 简介 SpringMVC 的入门案例 SpringMVC 流程分析 配置注解映射器和适配器 注解的使用 使用不同方式的跳转页面 1. SpringMVC 简介 Spring web mvc

untitled

全国计算机技术与软件专业技术资格(水平)考试

untitled

计 算 机 系 统 应 用 年 第 25 卷 第 4 期 线 程 的 复 用 [2,3]. 通 常 情 况 下, 服 务 器 端 程 序 在 启 动 时 创 建 若 干 数 量 的 线 程 对 象 并 缓 存 起 来, 此 时 它 们 处 于

Value Chain ~ (E-Business RD / Pre-Sales / Consultant) APS, Advanc

JBuilder Weblogic

无类继承.key

帝国CMS下在PHP文件中调用数据库类执行SQL语句实例

IoC容器和Dependency Injection模式.doc

2 WF 1 T I P WF WF WF WF WF WF WF WF 2.1 WF WF WF WF WF WF

Oracle高级复制配置手册_业务广告_.doc

WWW PHP Comments Literals Identifiers Keywords Variables Constants Data Types Operators & Expressions 2

, 7, Windows,,,, : ,,,, ;,, ( CIP) /,,. : ;, ( 21 ) ISBN : -. TP CIP ( 2005) 1

1 Framework.NET Framework Microsoft Windows.NET Framework.NET Framework NOTE.NET NET Framework.NET Framework 2.0 ( 3 ).NET Framework 2.0.NET F

Android Robert C.C. Huang Oscar F.Y. Liu Peter C.L. Hsieh 2011/03/21

概述

Go构建日请求千亿微服务最佳实践的副本

WWW PHP

國立臺灣科技大學

C/C++ - 文件IO

没 有 多 余 的 Contruol 或 Action 了 原 来 Domain 层 被 服 务 层 Service layer 遮 挡, 在 右 边 图 中, 则 Domain 层 直 接 暴 露 给 前 台 了, 没 有 被 遮 挡, 裸 露 了 这 样 一 步 到 位 实 现 领 域 模 型

Transcription:

Background Tasks 章国锋 陶煜波浙江 学 CAD&CG 国家重点实验室

目录 一 异步任务 二 异步任务载入器 三 网络连接 四 服务

线程

UI 线程 App 在 UI 线程上运行, 因此这个 UI 线程也称为主线程 该线程负责在屏幕上绘制 UI 该线程通过处理 UI 事件来响应用户操作

UI 线程必须要快 硬件每 16 毫秒更新一次屏幕内容 UI 线程有 16 毫秒来完成它的所有工作 如果它需要太长时间, 应用程序会卡住 / 挂起

APP 没有响应 如果 UI 等待操作完成的时间太长, 则无法响应 下图显示了一个 Application Not Responding(ANR) 对话框

长时间运行的任务 网络操作 大量计算 下载/上传文件 处理图像 加载数据

后台线程 长时间运行的任务更适合放在后台线程上 后台线程包括以下三种 异步任务 (AsyncTask) 载入器 (The Loader Framework) 服务 (Services)

最佳实践 不要阻塞 UI 线程 UI 线程的工作需要在 16 毫秒的时间内完成 在非 UI 线程上执行更耗时的非 UI 逻辑 不要从 UI 线程以外的地方访问 Android UI toolkit UI 仅在 UI 线程上工作

异步任务 (AsyncTask)

AsyncTask 使用 AsyncTask 完成基础的后台任务

需要覆盖两个方法 doinbackground() 在后台线程上运行 包含在后台执行的所有逻辑 onpostexecute() 当 AsyncTask 完成工作后, 这个方法在 UI 线程被调用 处理结果 将结果发布 更新到 UI

其他相关方法 onpreexecute() 在 UI 线程上运行 设置将要执行的后台任务 onprogressupdate() 在 UI 线程上运行 接收来自后台线程的 publishprogress() 的数据

其他相关方法

使用 AsyncTask 继承 AsyncTask 提供传入 doinbackground() 的数据类型 提供 onprogressupdate() 中表示进度的数据类型 提供 onpostexecute() 返回结果的数据类型 如下面的例子中, 传入的数据类型为 String URL, 表示进度的数据类型是 Integer, 返回的结果数据类型是图像 Bitmap

使用 AsyncTask 载入图片的例子 String 查询的图片的 URI, 可以是网络资源, 也可以是本地资源的 URI Integer 代表进度的百分比 Bitmap 返回一张图像

onpreexecute() protected void onpreexecute() { // display a progress bar // show a toast }

doinbackground() protected Bitmap doinbackground(string... query) { // Get the bitmap return bitmap; }

onprogressupdate() protected void onprogressupdate(integer... progress) { } setprogresspercent(progress[0]);

onpostexecute() protected void onpostexecute(bitmap result) { } // Do something with the bitmap

loadimage() public void loadimage (View view) { String query = medittext.gettext().tostring(); new MyAsyncTask(query).execute(); }

AsyncTask 的缺点 当设备配置更改时,Activity 被销毁 此时 AsyncTask 无法再连接到 Activity 新的 AsyncTask 会被创建 但旧的 AsyncTasks 仍然运行 应用程序可能会因此耗尽内存或崩溃

什么时候使用 AsyncTask 处理短暂或可中断的任务 不需要向 UI 或用户返回结果的任务 优先级较低的任务 ( 意味着即使被中断或者暂时完成不了也不是很影响 ) 上述情况之外推荐使用 AsyncTaskLoader

目录 一 异步任务 二 异步任务载入器 三 网络连接 四 服务

载入器 (Loader)

Loader 提供异步的数据加载 配置更改后可以自动重连到 Activity 可以监控数据源的变化并传送新数据 回调在 Activity 中实现 有多种类型的 Loader 可供选择 AsyncTaskLoader,CursorLoader

为什么推荐使用 Loader LoaderManager 替开发者处理配置更改的情况 框架提供了高效优美的实现

LoaderManager 通过回调管理 Loader 可以管理多个 Loader

通过 InitLoader() 获取 Loader 创建并启动 Loader, 或复用现有的 Loader, 包括其数据 使用 restartloader() 清空现有 Loader 中的数据 getloadermanager().initloader(id,args,callback); getloadermanager().initloader(0,null,this); getsupportloadermanager().initloader(0,null,this);

实现异步任务载入器 (AsyncTaskLoader)

AsyncTaskLoader

AsyncTask->AsyncTaskLoader

创建步骤 继承 AsyncTaskLoader 实现构造函数 实现 loadinbackground() 实现 onstartloading()

继承并实现构造函数 public static class StringListLoader extends AsyncTaskLoader<List<String>> { } public StringListLoader(Context context, String querystring) { super(context); mquerystring = querystring; }

loadinbackground() public List<String> loadinbackground() { List<String> data = new ArrayList<String>; //TODO: Load the data from the network or from a database return data; }

onstartloading() 当 restartloader() 或 initloader() 被调用时,LoaderManager 会去回调 onstartloading(), 在 onstartloading() 中做下面三件事 : 检查缓存数据 开始观察数据源 ( 如果需要 ) 如果有数据有更改或没有缓存数据, 调用 forceload() 来加载数据 protected void onstartloading(){ forceload(); }

在 Activity 中实现 Loader 的回调 oncreateloader() - 给定的 ID, 创建并返回一个新的 Loader onloadfinished()- 在先前创建的 Loader 完成其加载时调用 onloaderreset()- 在重置先前创建的 Loader 时调用, 使其数据不可用

oncreateloader() @Override public Loader<List<String>> oncreateloader(int id, Bundle args) { return new StringListLoader(this,args.getString("queryString")); }

onloadfinished() AsyncTaskLoader 的结果 ( 也就是 loadinbackground() 的计算 结果 ) 会传递给 onloadfinished() public void onloadfinished(loader<list<string>> loader, List<String> data) { madapter.setdata(data); }

onloaderreset() 仅在 Loader 被销毁时调用 大部分情况下都不需要用到 @Override public void onloaderreset(final LoaderList<String>> loader) { }

通过 InitLoader() 获取 Loader 在 Activity 中调用 getsupportloadermanager().initloader(0, null, this);

目录 一 异步任务 二 异步任务载入器 三 网络连接 四 服务

连接网络的步骤 1. 给 Manifest 文件增加网络权限 2. 检查网络连接 3. 创建 worker 线程 4. 实现后台任务 1. 创建 URI 2. 创建 HTTP 连接 3. 连接, 获取数据 5. 处理结果

权限

Manifest 中的权限 1. 网络 <uses-permission android:name="android.permission.internet"/> 2. 检查网络状态 <uses-permission android:name="android.permission.access_network_stat E"/>

管理网络连接

获取网络信息 ConnectivityManager 给出网络连接查询的结果 当网络连接发生改变时提醒 app NetworkInfo 描述了指定类型的网络接口的状态 移动数据还是 Wi-Fi

检查网络是否可用 ConnectivityManager connmgr = (ConnectivityManager) getsystemservice(context.connectivity_service); NetworkInfo networkinfo = connmgr.getactivenetworkinfo(); if (networkinfo!= null && networkinfo.isconnected()) { // Create background thread to connect and get data new DownloadWebpageTask().execute(stringUrl); } else { textview.settext("no network connection available."); }

检查移动数据 & Wi-Fi NetworkInfo networkinfo = connmgr.getnetworkinfo(connectivitymanager.type_wifi); boolean iswificonn = networkinfo.isconnected(); networkinfo = connmgr.getnetworkinfo(connectivitymanager.type_mobile); boolean ismobileconn = networkinfo.isconnected();

Worker 线程

使用 Worker 线程 AsyncTask 非常短的任务, 或者不需要返回结果给 UI AsyncTaskLoader 非常长的任务, 或者需要返回结果给 UI Background Service 详情见下一节

后台工作 在后台任务中 : 1. 创建 URI 2. 建立 HTTP 连接 3. 下载数据

创建 URI

URI URI ( Uniform Resource Identifier, 统一资源标识符 ), 是 一个字符串, 定位到一个指定的资源 file:// http:// and https:// content://

URL 的一个例子 使用 Google Book API 进行查询 : https://www.googleapis.com/books/v1/volumes? q=pride+prejudice&maxresults=5&printtype=books final String BASE_URL = "https://www.googleapis.com/books/v1/volumes?"; final String QUERY_PARAM = "q"; final String MAX_RESULTS = "maxresults"; final String PRINT_TYPE = "printtype";

为请求建立一个 URI Uri builturi = Uri.parse(BASE_URL).buildUpon().appendQueryParameter(QUERY_PARAM, "pride+prejudice") "10").appendQueryParameter(MAX_RESULTS,.appendQueryParameter(PRINT_TYPE, "books").build(); URL requesturl = new URL(builtURI.toString());

HTTP 客户端连接

HTTP 连接 使用 HttpURLConnection 必须在一个单独的线程中进行网络连接 需要 InputStream 和 try/catch 语句块

创建一个 HttpURLConnection HttpURLConnection conn = (HttpURLConnection) requesturl.openconnection();

设置连接 conn.setreadtimeout(10000 /* milliseconds */); conn.setconnecttimeout(15000 /* milliseconds */); conn.setrequestmethod("get"); conn.setdoinput(true);

连接和获取回复 conn.connect(); int response = conn.getresponsecode(); InputStream is = conn.getinputstream(); String contentasstring = convertistostring(is, len); return contentasstring;

关闭连接和流 } finally { conn.disconnect(); if (is!= null) { is.close(); } }

把回复转换成字符串

把输入流转换成字符串 public String convertistostring(inputstream stream, int len) throws IOException, UnsupportedEncodingException { } Reader reader = null; reader = new InputStreamReader(stream, "UTF-8"); char[] buffer = new char[len]; reader.read(buffer); return new String(buffer);

BufferReader 效率更高 StringBuilder builder = new StringBuilder(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); String line; while ((line = reader.readline())!= null) { builder.append(line + "\n"); } if (builder.length() == 0) { return null; } resultstring = builder.tostring();

HTTP 客户端库

使用库创建一个连接 使用一个第三方库, 比如 OkHttp 或者 Volley 可以在主线程中调用 代码更少

Volley RequestQueue queue = Volley.newRequestQueue(this); String url ="http://www.google.com"; StringRequest stringrequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { @Override public void onresponse(string response) { // Do something with response } }, new Response.ErrorListener() { @Override public void onerrorresponse(volleyerror error) {} }); queue.add(stringrequest);

OkHTTP OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder().url("http://publicobject.com/helloworld.txt").build(); client.newcall(request).enqueue(new Callback() { @Override public void onresponse(call call, final Response response) throws IOException { try { String responsedata = response.body().string(); JSONObject json = new JSONObject(responseData); final String owner = json.getstring("name"); } catch (JSONException e) {} } });

解析回应值

解析回应值 实现接收和处理回应的方法 (onpostexcute()) 回应值一般是 JSON 或者 XML 使用 helper 类解析回应值 : JSONObject, JSONArray XMLPullParser parses XML

JSON 基础 JSON 对象 (object) 是名称 / 值对 (name/value pair) 的无序集合 以 { 开始, } 结束 每个名称 / 值对之间用, 分开

JSON 数组 JSON 数组 (array) 是一个有序集合 以 [ 开始, ] 结束 以, 分隔

JSON 值 JSON 中的值 (value) 可以是字符串 (string), 数值 ( number), 对象 (object), 数组 (array), 布尔值, null

JSON 例 1 { } "population":1,252,000,000, "country":"india", "cities":[ "New Delhi", "Mumbai", "Kolkata", "Chennai ]

解析 JSON JSONObject jsonobject = new JSONObject(response); String nameofcountry = (String) jsonobject.get("country"); long population = (Long) jsonobject.get("population"); JSONArray listofcities = (JSONArray) jsonobject.get("cities"); Iterator<String> iterator = listofcities.iterator(); while (iterator.hasnext()) { // do something }

JSON 例 2 {"menu": { "id": "file", "value": "File", "popup": { "menuitem": [ {"value": "New", "onclick": "CreateNewDoc()"}, {"value": "Open", "onclick": "OpenDoc()"}, {"value": "Close", "onclick": "CloseDoc()"} ] } }

解析 JSON 获取 menuitem 数组中第三个对象的 onclick 值 : JSONObject data = new JSONObject(responseString); JSONArray menuitemarray = data.getjsonarray("menuitem"); JSONObject thirditem = menuitemarray.getjsonobject(2); String onclick = thirditem.getstring("onclick");

目录 一 异步任务 二 异步任务载入器 三 网络连接 四 服务

服务 (service) 是一个进阶主题 服务很复杂 配置服务的方法有很多种 本节课仅起一个介绍作用 如果想掌握服务, 仍需各位同学进一步自学

为长时间运行的任务创建服务

服务 (service) 是什么 服务是一种在后台运行, 不需要用户界面, 可以执行长 时间的任务的应用组件

服务 (service) 擅长的工作 网络事务 播放音乐 执行文件 I/O 和数据库交互

服务 (service) 的特点 被一个 Intent 启动 当用户切换应用时, 可以持续运行 开发者必须管理其生命周期 其他应用可以使用这项服务 管理权限 在它的宿主进程的主线程中运行

启动式服务 ( 非绑定式服务 ) 由 startservice() 启动 除非被停止, 不然会一直运行下去 一般不需要更新 UI

绑定式服务 提供一个客户端 - 服务器形式的接口, 接口允许组件和服务进行交互 客户端发送请求, 获得结果 使用 bindservice() 启动 当客户端解绑的时候结束

服务和线程 尽管服务与 UI 分离, 但在默认情况下, 服务仍然是运行在主线程里面的 可能引发 app 失去响应错误 为 cpu 密集型工作单独创建一个线程

更新 APP 服务不能与 UI 进行交互, 那么服务完成之后要怎 么把结果返回给 app, 让 app 展示出结果呢? 使用广播

前台服务 大部分服务运行在后台, 但也有服务需要运行在前台 比如音乐播放服务, 因为用户需要跟它进行交互 前台服务比后台服务有更高的优先级, 因为用户能感知到它们的存在, 不会被系统 kill 必须发出通知 当前台服务在运行时, 必须让用户意识到它的存在

API 26 对后台服务的限制 API 26 开始, 在后台运行的 app 不允许创建后台服务了 在前台运行的 app, 可以创建前台服务和后台服务 当 app 切入后台时, 系统会停止 app 的后台服务 startservice() 方法可以抛出一个 IllegalStateException 异常 这些限制不会影响前台服务或者绑定服务

创建一个服务 <service android:name=".exampleservice" /> 管理权限 继承 IntentService 或者 Service 类 实现生命周期方法 从 Activity 中启动服务 确保服务可以停止

停止一个服务 一个启动式服务必须管理其生命周期 如果没有被停止, 会持续运行和消耗资源 服务必须调用 stopself() 方法停止自己 外部组件可以用 stopservice() 方法停止服务 当所有的客户端都解绑时, 绑定式服务会停止 Intent 服务在 onhandleintent() 方法返回之后停止

Intent 服务

Intent 服务 一种简单的服务, 有简单的生命周期 使用 worker 线程来回应请求 完成后会自行停止 对于在后台线程中长时间运行的任务, 非常理想

Intent 服务的局限性 不能与 UI 进行交互 只能一次响应一个请求 不能被中断

Intent 服务受到的限制 Intent 服务同样受到 API 26 中对于后台服务的约束 对于 API 26 以上的 APP,Android Support Library 26.0.0 介绍了一种新的 JobIntentService JobIntentService 提供了与 Intent 服务相似的功能, 但使用 job 而不是服务

实现一个 Intent 服务 public class HelloIntentService extends IntentService { public HelloIntentService() { super("hellointentservice");} @Override protected void onhandleintent(intent intent) { try { // Do some work } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } // When this method returns, IntentService stops the service, as appropriate. }

参考资料 AsyncTask Reference AsyncTaskLoader Reference LoaderManager Reference Processes and Threads Guide Loaders Guide UI 线程性能相关 : Exceed the Android Speed Limit

参考资料 Connect to the Network Guide Managing Network Usage Guide HttpURLConnection reference ConnectivityManager reference InputStream reference Services overview Background Execution Limits

Thanks!