android培训笔记
2018-01-03 18:02:00 weixin_34203426 阅读数 19

今天由本所郭老师给我们讲了自动化测试的内容。

郭老师的博客详见 http://blog.csdn.net/jara0705

自己总结主要脉络如下:

1. 测试的目录结构

创建一个新android项目后,会自动生成test目录和androdiTest目录

一般test目录是作JUnit的,而androidTest是专门测android的,可以理解为UI相关

2. JUnit基本的测试

assertEqual()用来断言一个表达式是否是预期输出

当然还有assertXXX等各种预置的方法,可以使用。

在android studio的Junit方法的左面点击三角,就可以运行和输出测试结果

3. robolectric 我叫它为萝卜测试

这个是测试UI的,它可以模拟某个按键的click事件

但写起来比较麻烦,除非业务基本不变

4. 命令行

命令行是gradlew test就是测test目录

gradlew connectedAndroidTest就是测androidTest目录

5. jacoco 代码覆盖率生成报告工具

可以生成代码自动化测试的报告

加coco, coco是哪个美女?不知道,不见面引发更多想象

配置办法是在build.gradle里先引入plugin: jacoco

再写一个task jacocoTestReport( .... Dependson:"test")

这里Dependson里指定的test就是要跑test目录

6. 终级大招jenkins

上面这么多,最后当然是想在jenkins 里编译发布时全自动进行自动化单元测试了。测试不过不准发布。

在jenkins里安装jacoco等插件

在参数配置里可以设置任务参数

clean

jacocoTestReport

...

这样就可以自动化测试(我们写的jacoco任务depend 我们的test), 及自动生成覆盖率报

告了.

2016-08-03 07:18:00 qq_34203494 阅读数 244
5.1无线连接设备
除了能够在云端通信,安卓的无线API也允许同一局域网中的设备进行通信。甚至没有连接到网络上,而是物理上隔得很近,也可以相互通信。此外。网络服务发现(NSD)可以进一步通过应用程序运行能相互通信的服务去找寻附近运行相同服务的设备。把这个功能整合到我们的应用中,可以提供许多功能,如在同一个房间,用户玩游戏,可以利用NSD实现从一个网络摄像头获取图像,或远程登录到同一网络中的其他机器。

5.1.1 使用网络服务发现
添加网络服务发现到我们的app中,可以使我们的用户辨识在局域网中支持我们的app所请求的服务的设备。
在局域网内注册自己服务的第一步是创建 NsdServiceInfo 对象。此对象包含的信息能够帮助网络中的其他设备决定是否要连接到我们所提供的服务。
public void registerService(int port) {
    // Create the NsdServiceInfo object, and populate it.
    NsdServiceInfo serviceInfo  = new NsdServiceInfo();

    // The name is subject to change based on conflicts
    // with other services advertised on the same network.
    serviceInfo.setServiceName("NsdChat");
    serviceInfo.setServiceType("_http._tcp.");
    serviceInfo.setPort(port);
    ....
}
第二个参数设置了服务类型,即指定应用使用的协议和传输层。语法是“_< protocol >._< transportlayer >”。在上面的代码中,服务使用了TCP协议上的HTTP协议。想要提供打印服务(例如,一台网络打印机)的应用应该将服务的类型设置为“_ipp._tcp”。
发现网络中的服务
与注册网络服务类似,服务发现需要两步骤:用响应的回调函数设置发现监听器,以及调用discoverService()


连接到网络上的服务
当我们的应用发现了网上可接入的服务,首先需要调用resolveService()方法,以确定服务的连接信息。
实现NsdManager.resolveListener对象并将其传入resolveService()方法。并使用这个NsdManager.
ResolveListener对象获得包含连接信息的 NsdSerServiceInfo

当程序退出时注销服务
在应用的生命周期中开启和关闭NSD服务是十分关键的。在程序退出时注销服务可以防止其他程序因为不知道
服务退出而反复尝试连接的行为。另外,服务发现市一中开销很大的操作,应该随着父activity的暂停而停止。

选择一个HttpClient 
大多数连接网络的Android app 会使用http来发送与接受数据。android提供了两种http clients :httpUrlConnection
与Apache HttpClient 。二者均支持Https ,流媒体上传和下载,可配置的超时、IPV6与连接池。

5.3传输数据数据时避免消耗大量电量

5.3.1优化下载以高效访问网络
安卓上的app不仅仅可以在前台运行(重点关注延迟),也可以在后台运行(优先处理耗电量)。

app如何影响无线电泼状态机
每次创建一个新的网络连接,无线电就切换到full power状态。在上面典型的3G无线电波状态机情况下,
无线电会在传输数据时保持在full power的状态,加上一个附加的5秒拖尾时间,再之后会经过12秒进入到
low power能量状态,因此对于典型的3G设备,每一次数据传输的回话都会导致无线电消耗大概20秒时间
来提取电能。

实际上,这意味着一个每18秒传输1秒非捆绑数据的app,会一直保持激活状态(18=1秒的传输数据+5秒
过渡时间回到low power+12秒过渡事件回到standby)。因此每分钟会消耗18秒high power的电量,42
秒low power 的电量。
通过比较,同一个app,每分钟传输持续3秒的捆绑数据,会使得无线电波持续在high power状态仅仅8秒,
在low power状态仅仅12秒钟。

预取数据
预取数据是一种减少数据传输会话数量的有效方法,预取技术指的是在一定时间内,单次连接操作,以最大
的下载能力来下载所有用户可能需要的数据。

预取技术通过减少应用里由于在执行一个动作或者查看数据之前等待下载完成造成的延迟,来提高用户体验。
根据正在下载的数据大小与可能用到的数据量来决定预取的频率。做一个粗略的估计,根据上面介绍的状态
机,对于有50%的机会会被当前的用户会话用到的数据,我们可以预取大约6秒,这使得潜在可能要用到的
数据量与可能下载好的数据量相一致。

通常来说,预取1-5MB会比较好,这种情况下,我们仅仅只需要每隔2-5分钟开始另一段下载。
根据这个原理,大数据的下载,比如视频文件,应该每隔2-5分钟开始另一端下载,这样能有效的预取到
下面几分钟内的数据进行预览。

值得注意的是,更进一步的下载应该是捆绑的。

一个音乐播放器
一个比较好的方法是维护正在播放的那首歌曲的缓冲区。对于流媒体音乐,不应该维护一段连续的数据流,
这样会使得无线电波一直保持激活状态,而应该用http流直播来集中传输音频流。(下载好2MB,开始一次
取出,再去下载下面的2MB)。

一个新闻阅读器
一个比较好的方法是在启动的时候预取一个合理数量的数据,比如在启动的时候预取第一条新闻的标题与缩略图
信息,确保较短的启动时间。之后继续获取剩余新闻的标题和缩略图信息。同时获取至少在主要标题列表可用的
每篇文章的文本。

批量处理传送和连接
每次发起一个连接——不论相关数据的大小——当使用典型的3G无线网络时,可能会导致无线电消耗大约20秒
的电量。
一个app每20秒ping一次服务器,仅仅是为了确认app正在运行和对用户课件,那么无线电会无限期地处于开启
状态,导致即使再没有实际数据传输的情况下,仍会消耗大量电量。

因此,对传送的数据进行捆绑操作和创建一个等待传输队列就显得非常重要。操作正确的话,可以使得大量的数据
集中进行发送,这样使得无线电波的激活时间尽可能的少,同时减少大部分电量的花费。

意味着我们应该通过队列延迟容忍传送来批量处理我们的传输数据,和抢占调度更新和预取,使得当要求时间敏感
传输时,数据会被全部执行。同样地,我们的计划更新和定期的预取应该开启等待传输队列的执行工作。

减少连接
通常来说,重用已经存在的网络连接比起重新建立一个新的连接更有效率。重用网络连接同样可以使得在拥挤不堪
的网络环境中进行更加智能地作出反应。
一个有用的妥协不是立即关闭连接,而是在固定期间的timeout之前关闭(即稍微晚点却又不至于到timeout)

最小定期更新造成的影响
每次app去向server询问检查是否有更新操作的时候,都会激活无线电,这样造成了不惜要的能量消耗。
GCM是一个用来从server到特定app传输数据的轻量级机制。使用GCM,server会在某个app需要获取新数据的时候
比起轮询方式(app为了即时拿到最新的数据需要定时去pIngserver),GCM这种由事件驱动的模式会在仅仅有数据
更新的时候通知app去创建网络连接来获取数据。

使用不严格的重复通知和指数避退算法来优化轮询
CSMA/CD协议中,一旦检测到冲突,为降低再冲突的概率,需要等待一个随机时间,然后再使用CSMA方法试图传输。为了保证这种退避维持稳定,采用了二进制指数退避算法的技术,其算法过程如下:
1. 将冲突发生后的时间划分为长度为2t的时隙
2. 发生第一次冲突后,各个站点等待0或1个时隙再开始重传
3. 发生第二次冲突后,各个站点随机地选择等待0,1,2或3个时隙再开始重传
4. 第i次冲突后,在0至2的i次方减一间随机地选择一个等待的时隙数,再开始重传
5. 10次冲突后,选择等待的时隙数固定在0至1023(2的10次方减一)间
6. 16次冲突后,发送失败,报告上层。
另一个方法是在 app 在上一次更新操作之后还未被使用的情况下,使用指数退避算法 exponential back-off algorithm 来减少更新频率。断言一个最小的更新频率和任何时候使用 app 都去重置频率通常都是有用的方法。例如

SharedPreferences sp =
  context.getSharedPreferences(PREFS, Context.MODE_WORLD_READABLE);

boolean appUsed = sp.getBoolean(PREFS_APPUSED, false);
long updateInterval = sp.getLong(PREFS_INTERVAL, DEFAULT_REFRESH_INTERVAL);

if (!appUsed)
  if ((updateInterval *= 2) > MAX_REFRESH_INTERVAL)
    updateInterval = MAX_REFRESH_INTERVAL;

Editor spEdit = sp.edit();
spEdit.putBoolean(PREFS_APPUSED, false);
spEdit.putLong(PREFS_INTERVAL, updateInterval);
spEdit.apply();

rescheduleUpdates(updateInterval);
executeUpdateOrPrefetch();
初始化一个网络连接的花费不会因为是否成功下载了数据而改变。对于那些成功完成是很重要的时间敏感的传输,我们可以使用指数退避算法来减少重复尝试的次数,这样能够避免浪费电量。例如:
private void retryIn(long interval) {
  boolean success = attemptTransfer();

  if (!success) {
    retryIn(interval*2 < MAX_RETRY_INTERVAL ?
            interval*2 : MAX_RETRY_INTERVAL);
  }
}
5.3.4
例如:如果LTE无线电的带宽与电量消耗都是3G无线电的2倍,我们应该在每次会话的时候都下载4倍于3G的数据量,或者差不多10MB .当然,下载这么多数据的时候,我们需要好好考虑预取本地存储的效率并且需要经常刷新预取的缓存。

我们可以使用connnectivity manager来判断当前激活的无限电波,并且根据不同结果来修改预取操作。

5.4 云同步 

5.4.1使用备份 API 
对于一些数据量相对较少的情况下(通常少于1MB),例如用户偏好设置、笔记、游戏分数或者是其他的一些状态数据,可以使用backup API来提供一个轻量级的解决方案。

注册Android backup Service 
这节课中所使用的Android backup Service 需要进行注册。

编写备份代理
创建辈分代理最简单的方法就是继承BackupAgentHelper。重写onCreate()方法。
onCreate()中创建一个BackupHelper,目前 Android Framework 包含了两个帮助类:FileBackupHelper 与SharedPreferencesBackupHelper
在我们创建一个帮助类并且指向需要备份的数据的时候,仅仅需要使用addhelper()方法将它们添加到backAgentHelper当众,之后再增加一个key
用来恢复数据。
为了使程序更加灵活,FileBackupHelper的构造函数可以带有任意数量的文件名,我们只需要简单地通过额外增加一个参数,就能实现同时对最高分
文件与游戏进度文件进行备份。

备份用户同样比较简单。和创建FilebackupHelper一样创建一个sharedPreferenceBackupHelper。在这种情况下,不是添加文件名到构造函数中。而是
添加被应用所使用的shared Preference Groups的名称。

请求备份
为了请求一个备份,仅仅需要创建一个BackupManager实例,然后调用它的dataChanged()方法即可。

恢复备份数据
如果确实有必须手动去触发恢复,只需要调用requestRestor()方法就可以了。

5.6使用Sync Adapter传输数据

我们可以考虑一下使用Android的同步适配器框架。该框架可以用来帮主管理数据,自动传输数据,以及协调不同应用间的同步问题。
插件架构
自动执行
自动网络检测
提升电池使用效率
账户管理和授权

5.6.1创建Stub授权器

Sync Adapter 框架假定我们的 Sync Adapter 在同步数据时,设备存储端关联了一个账户,且服务器端需要进行登录验证。因此,我们需要提供一个叫做授权器(Authenticator)的组件作为 Sync Adapter 的一部分。该组件会集成在 Android 账户及认证框架中,并提供一个标准的接口来处理用户凭据,比如登录信息。

即使我们的应用不使用账户,我们仍然需要提供一个授权器组件。在这种情况下,授权器所处理的信息将被忽略,所以我们可以提供一个包含了方法存根(Stub Method)的授权器组件。同时我们需要提供一个绑定 Service,来允许 Sync Adapter 框架调用授权器的方法。


添加一个Stub 授权器组件
要在应用中添加一个 Stub 授权器,首先我们需要创建一个继承AbstractAccountAuthenticator 的类,在所有需要重写的方法中,我们不进行任何处理,仅返回 null 或者抛出异常。


将授权器绑定到框架
为了让Sync Adapter框架可以访问我们的授权器,我们必须为它创建一个绑定服务。这一服务提供一个Android Binder对象,允许框架调用我们的授权器,并且在授权器和框架间
传递数据。
因为框架会在它第一次需要访问授权器时启动该service,所以我们也可以使用该服务来实例化授权器。具体而言,我们需要在服务的Service.onCreate()方法中调用授权器的
构造函数。

添加授权器的元数据文件
在<Mainfest>文件中声明授权器

5.6.2创建stub Content provider 
Sync Adapter  框架是设计成用来和设备数据一起工作,而这些设备数据应该被灵活且安全的Contentprovider
框架管理。因此,Sync Adapter框架会期望应用已经成为它的本地数据定义了Content provider。

5.6.3创建Sync Adapter 
5.6.4执行Sync Adapter 

5.7使用Volley传输网络数据
Volley有如下优点:
1、自动调度网络请求。
2、高并发网络连接
3、通过标准http cache coherence (高速缓存一致性)缓存磁盘和内存透明的响应。
4、支持指定请求的优先级
5、支持指定请求的优先级
6、撤销请求API
7、框架容易被定制
8、强大的指令可以使得异步加载网络数据并正确地显示到UI的操作更简单。
9、包含了调试与追踪工具

Volley擅长执行用来显示UI的RPC类型操作,例如获取搜索结果的数据。它轻松的整合了任何协议,并
输出操作结果的数据,可以是原始的字符串,也可以是图片,或者是JSON,通过提供内置的我们可能
使用到的功能,Volley可以使得我们免去重复编写样板代码,使我们可以把关注点放在app的功能逻辑

Volley不适合用来下载打的数据文件,因为Volley会保持在解析的过程中所有的响应。

5.7.1发送简单的网络请求
1)Add the Internet Permission 
2)User new RequestQueue
3)Send a Request 
为了发送一个请求,你只需要构造一个请求并通过add()方法添加到RequestQueue中,一旦你添加了这个请求
它会通过队列,得到处理,然后得到原始的响应数据并返回。

当你执行add()方法时,Volley触发执行一个缓存处理线程以及一系列网络处理线程。当你添加一个请求到
队列中,它将被缓存线程所捕获并触发:如果这个请求可以被缓存处理,那么会在缓存线程中执行响应数据
的解析并返回到主线程。如果请求不能被缓存所处理,它会被放到网络队列中。网络线程池中的第一个可用
的网络线程会从队列中获取到这个请求并执行HTTP操作,解析工作线程的响应数据,把数据写道缓存中并把
接卸之后的数据返回到主线程。

4)Cancel a Request 
对请求Request对象调用Cancel()方法取消一个请求。一旦取消,Volley会确保你的响应hanlder不会被执行。
这意味着在实际操作中你可以在activity的onstop方法中取消所有pending在队列中的请求。你不需要通过检测
getactivity()==null来丢弃你的响应handler。
你可以为每个请求对象都绑定一个tag对象,然后你可以使用这个tag提供取消的范围。你可以为你的所有请求
都绑定到执行的activity上,然后你可以在onstop方法执行requestQueue.cancleall(this)。

5.7.2建立请求队列
这节课会介绍一种推荐的实现方式:创建一个单例的RequestQueue,这使得RequestQueue能够保持在我们
app的生命周期中。

建立网络和缓存
一个RequestQueue需要两部分来支持它的工作:一部分是网络操作,用来传输请求,另一个是用来处理缓存
操作的Cache。在Volley的工具箱中包含了标准的实现方式:DiskBaseCache提供了每个文件与之对应响应
数据一一映射的缓存实现。BasicNetwork提供了一个基于AndroidHttpClient 或者HttpURLConnection的网络
传输。

使用单例模式
如果我们的应用持续地使用网络,更加高效的方式应该是建立一个RequestQueue的单例,这样它能够持续
保持在整个app的生命周期中。我们可以通过多种方式来实现这个单例。
推荐的方式是实现一个单例类,里面封装了RequestQueue()对象与其他Volley功能。
另一种方法是继承Application类,并在Application.OnCreate()方法里面建立RequestQueue。但是我们
不推荐这个方法,因为一个static的单例能够以一种更加模块化的方式提供同样的功能。

一个关键的概念是RequestQueue必须使用Application context来实例化,而不是Activity context。这确保了
RequestQueue在我们的app的生命周期中一直存货,而不会因为activity的重新创建而被重新创建

5.7.3 创建标准的网络请求 
请求一张图片
Volley为请求图片提供如下的类。用来支持不同的层级进行图片处理
ImageRequest ——一个封装好的,用来处理URL请求图片并且返回一张解完码的位图(Bitmap)。它同样提供了
一些简便的接口方法,例如指定一个大小进行重新裁剪。它的主要好处是Volley会确保类似decode,resize等
耗时操作在工作线程中执行。

Imageloader——一个用来处理加载与缓存从网络上获取到的图片的帮助类
ImageLoader是大量ImageRequest的协调器。例如,在listview中需要显示大量缩略图的时候。ImageLoader为
通常的Volley cache提供了更加前瞻的内存缓存,这个缓存对于防止图片抖动非常有用。这还使得在不阻塞或者
延迟主线程的前提下实现缓存命中。Imageloader还能够实现响应联合,避免几乎每一个响应回调里面都设置
Bitmap到view上面。响应联合使得能够同时提交多个响应。

NetworkImageLoader——在Imageloader的基础上建立,并且通过网络URL取回的图片的情况下,有效地替换
ImageView。如果view从层次结构中分离,NetworkImageView也可以管理取消挂起请求。

上面的代码是通过前一节的单例类来访问RequestQueue与ImageLoader。这种方法保证了我们的app创建这些
类的实例会持续存在于app的生命周期。这对于ImageLoader(一个用来处理加载与缓存图片的帮助类)很重要
的原因是:内存缓存的主要功能是允许非抖动旋转。使用单例模式可以使得Bitmap的缓存比activity存在的时间长
。如果我们在activity中创建ImageLoader。这个ImageLoader有可能会在每次旋转设备都被重新创建,可能导致抖动

举一个LRU cache的例子
Volley 工具箱中提供了一种通过 DiskBasedCache 类实现的标准缓存。这个类能够缓存文件到磁盘的指定目录。但是为了使用 ImageLoader,我们应该提供一个自定义的内存 LRC bitmap 缓存,这个缓存实现了 ImageLoader.ImageCache 接口。我们可能想把缓存设置成一个单例。
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
import android.util.DisplayMetrics;
import com.android.volley.toolbox.ImageLoader.ImageCache;

public class LruBitmapCache extends LruCache<StringBitmap>
        implements ImageCache 
{

    public LruBitmapCache(int maxSize) {
        super(maxSize);
    }
     //构造器嵌套构造器
    public LruBitmapCache(Context ctx) {
        this(getCacheSize(ctx));
    }

    @Override
    protected int sizeOf(String key, Bitmap value) {
        return value.getRowBytes() * value.getHeight();
    }

    @Override
    public Bitmap getBitmap(String url) {
        return get(url);
    }

    @Override
    public void putBitmap(String url, Bitmap bitmap) {
        put(url, bitmap);
    }

    // Returns a cache size equal to approximately three screens worth of images.
    public static int getCacheSize(Context ctx) {
        final DisplayMetrics displayMetrics = ctx.getResources().
                getDisplayMetrics();
        final int screenWidth = displayMetrics.widthPixels;
        final int screenHeight = displayMetrics.heightPixels;
        // 4 bytes per pixel
        final int screenBytes = screenWidth * screenHeight * 4;

        return screenBytes * 3;
    }
}
请求JSON
Volley提供了以下的类用来执行JSON请求
jsonArrayRequest——一个为了获取给定URL的JSONArray响应正文的请求。
jsonObjectRequest——一个为了获取给定URL的JSONOBJECT响应正文的请求。

这两个类都是基于一个公共基类JsonRequest。

5.7.4 实现自定义网络请求

编写一个自定义请求
大多数的请求类型都已经包含在Volley的工具箱里面。如果我们的请求返回数值是一个String,image或者json。
那么是不需要自己去实现请求的。
那些需要自定义的请求类型,我们需要执行以下操作:
1)继承Request<T>类,<T>表示解析过的响应请求预期的数据类型。因此如果我们需要解析的响应类型是
一个String ,可以通过继承Request<String>来创建自定义的请求。
2)实现抽象方法 parseNetworkResponse 与deliverResponse()
2018-07-21 10:56:27 weixin_38374558 阅读数 86

 1。

  基本的生命周期

这些状态中只有三种可以是静态。也就是说,活动只能在三种状态之一下存在很长时间。

  • 恢复:在这种状态下,活动处​​于前台,且用户可以与其交互。(有时也称为“运行”状态。)
  • 暂停:在这种状态下,活动被在前台中处于半透明状态或者未覆盖整个屏幕的另一个Activity-部分阻挡。暂停的活动不会接收用户输入并且无法执行任何代码。
  • 停止:在这种状态下,活动被完全隐藏并且对用户不可见;它被视为处于后台。停止时,活动实例及其诸如成员变量等所有状态信息将保留,但它无法执行任何代码。

2。

<activity android:name=".MainActivity" android:label="@string/app_name">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

如果程序中没有声明了MAIN  action或者LAUNCHER  category的活动,那么在设备的主界面列表里面不会呈现app图标。

3.如果活动含有在的onCreate调用时创建的后台线程,或者是其他有可能导致内存泄漏的资源,则应该在的OnDestroy()时进行资源清理,杀死后台线程。

4.除非程序在onCreate()方法里面就调用了finish()方法,系统通常是在执行了onPause()与onStop()之后再调用onDestroy()。在某些情况下,例如我们的活动只是做了一个临时的逻辑跳转的功能,它只是用来决定跳转到哪一个活动,这样的话,需要在的onCreate里面调用完成方法,这样系统会直接调用onDestory,跳过生命周期中的其他方法。

5。

当系统调用活动中的onPause(),从技术上讲,意味着活动仍然处于部分可见的状态。但更多时候意味着用户正在离开这个活动,并马上会进入停止状态。通常应该在的onPause()回调方法里面做以下事情:

  • 停止动画或者是其他正在运行的操作,那些都会导致CPU的浪费。
  • 提交在用户离开时期待保存的内容(例如邮件草稿)。
  • 释放系统资源,例如广播接收器,传感器(比如GPS),或者是其他任何会影响到电量的资源。

6。

当用户从暂停状态恢复活动时,系统会调用的onResume()方法。

请注意,系统每次调用这个方法时,活动都处于前台,包括第一次创建的时候。所以,应该实现的onResume()来初始化那些在的onPause方法里面释放掉的组件,并执行那些活动每次进入恢复状态都需要的初始化动作(例如开始动画与初始化那些只有在获取用户焦点时才需要的组件)

 

7.  因为系统在activity停止时会在内存中保存Activity的实例,所以有时不需要实现onStop(),onRestart()甚至是onStart()方法. 因为大多数的activity相对比较简单,activity会自己停止与重启,我们只需要使用onPause()来停止正在运行的动作并断开系统资源链接。

8.极端情况下,系统会直接杀死我们的app进程,并不执行activity的onDestroy()回调方法, 因此我们需要使用onStop()来释放资源,从而避免内存泄漏。

9.

通常,不应该使用onPause()来保存用户改变的数据 (例如填入表格中的个人信息) 到永久存储(File或者DB)上。仅仅当确认用户期待那些改变能够被自动保存的时候(例如正在撰写邮件草稿),才把那些数据存到永久存储 。但是,我们应该避免在onPause()时执行CPU-intensive 的工作,例如写数据到DB,因为它会导致切换到下一个activity变得缓慢(应该把那些heavy-load的工作放到onStop()

如果activity实际上是要被Stop,那么我们应该为了切换的顺畅而减少在OnPause()方法里面的工作量。

Note:当activity处于暂停状态,Activity

 10.

activity已经停止后,Activity对象会保存在内存中,并在activity resume时被重新调用。我们不需要在恢复到Resumed state状态前重新初始化那些被保存在内存中的组件。系统同样保存了每一个在布局中的视图的当前状态,如果用户在EditText组件中输入了text,它会被保存,因此不需要保存与恢复它。

Note: 即使系统会在activity stop时停止这个activity,它仍然会保存View对象的状态(比如EditText中的文字) 到一个Bundle中,并且在用户返回这个activity时恢复它们(下一小节会介绍在activity销毁与重新建立时如何使用Bundle

11.当activity从Stopped状态回到前台时,它会调用onRestart().系统再调用onStart()方法,onStart()方法会在每次activity可见时都会被调用。onRestart()方法则是只在activity从stopped状态恢复时才会被调用,因此我们可以使用它来执行一些特殊的恢复(restoration)工作,请注意之前是被stopped而不是destrory。

当系统Destory我们的activity,它会为activity调用onDestroy()方法。因为我们会在onStop方法里面做释放资源的操作,那么onDestory方法则是我们最后去清除那些可能导致内存泄漏的地方。因此需要确保那些线程都被destroyed并且所有的操作都被停止。

12. 你的Activity会在每次旋转屏幕时被destroyed与recreated。当屏幕改变方向时,系统会Destory与Recreate前台的activity,因为屏幕配置被改变,你的Activity可能需要加载另一些替代的资源(例如layout). 

13. 

默认情况下, 系统使用 Bundle 实例来保存每一个View(视图)对象中的信息(例如输入EditText 中的文本内容)。因此,如果Activity被destroyed与recreated, 则layout的状态信息会自动恢复到之前的状态。然而,activity也许存在更多你想要恢复的状态信息,例如记录用户Progress的成员变量(member variables)。

Note: 为了使Android系统能够恢复Activity中的View的状态,每个View都必须有一个唯一ID,由android:id定义。

为了可以保存额外更多的数据到saved instance state。在Activity的生命周期里面存在一个额外的回调函数,你必须重写这个函数。该回调函数并没有在前面课程的图片示例中显示。这个方法是onSaveInstanceState() ,当用户离开Activity时,系统会调用它。当系统调用这个函数时,系统会在Activity被异常Destory时传递 Bundle 对象,这样我们就可以增加额外的信息到Bundle中并保存到系统中。若系统在Activity被Destory之后想重新创建这个Activity实例时,之前的Bundle对象会(系统)被传递到你我们activity的onRestoreInstanceState()方法与 onCreate() 方法中。

基本的生命周期,saveState和

Figure 2. 当系统开始停止Activity时,只有在Activity实例会需要重新创建的情况下才会调用到onSaveInstanceState() (1) ,在这个方法里面可以指定额外的状态数据到Bunde中。如果这个Activity被destroyed然后这个实例又需要被重新创建时,系统会传递在 (1) 中的状态数据到 onCreate() (2) 与 onRestoreInstanceState()(3).

(通常来说,跳转到其他的activity或者是点击Home都会导致当前的activity执行onSaveInstanceState,因为这种情况下的activity都是有可能会被destory并且是需要保存状态以便后续恢复使用的,而从跳转的activity点击back回到前一个activity,那么跳转前的activity是执行退栈的操作,所以这种情况下是不会执行onSaveInstanceState的,因为这个activity不可能存在需要重建的操作)

14.

当我们的activity开始Stop,系统会调用 onSaveInstanceState() ,Activity可以用键值对的集合来保存状态信息。这个方法会默认保存Activity视图的状态信息,如在 EditText 组件中的文本或 ListView 的滑动位置。

为了给Activity保存额外的状态信息,你必须实现onSaveInstanceState() 并增加key-value pairs到 Bundle 对象中,例如:

static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
...

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save the user's current game state
    savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
    savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);

    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);
}

 

当Activity从Destory中重建,我们可以从系统传递的Activity的Bundle中恢复保存的状态。 onCreate() 与 onRestoreInstanceState() 回调方法都接收到了同样的Bundle,里面包含了同样的实例状态信息。

由于onCreate()方法会在第一次创建新的活动实例与重新创建之前被Destory的实例时都被调用,我们必须在尝试读取Bundle对象前检测它是否为null。如果它为null,系统则是创建一个新的活动实例,而不是恢复之前被Destory的活性的影响。

下面是一个示例:演示在的onCreate方法里面恢复一些数据:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); // Always call the superclass first

    // Check whether we're recreating a previously destroyed instance
    if (savedInstanceState != null) {
        // Restore value of members from saved state
        mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
        mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
    } else {
        // Probably initialize members with default values for a new instance
    }
    ...
}

我们也可以选择实现onRestoreInstanceState(),而不是在onCreate方法里面恢复数据  。onRestoreInstanceState()方法会在onStart()方法之后执行。系统仅仅会在存在需要恢复的状态信息时才会调用onRestoreInstanceState(),因此不需要检查Bundle是否为null。

public void onRestoreInstanceState(Bundle savedInstanceState) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState);

    // Restore state members from saved instance
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
    mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}

 

2016-09-14 10:50:58 li905663280 阅读数 284

Android官方培训课程中文版笔记

steps

1.建立第一个App

用android studio 新建一个新的项目,usb连接设备,点击运行,则能看到结果。mainActivity 覆写onCreate方法,并且设置rootView.怎么启动其他的界面。先新建一个Activity,在第一个Activity中通过点击按钮,触发加载activity界面,通过Intent对象将点击的context和目标activity的class类进行关联,传递参数,参数进行转换为textView,让目标activity进行显示。

2.activity的生命周期

onCreate,在activity被创建的时候调用,很快完成,完成的任务需要少,让加载更快。状态为created;onStart ,启动,很快的完成了。状态为Started;onResume ,状态变化Resumed,让activity能被用户所看见。onPause,暂停,让视图变得不可见,在切换app的时候调用。状态变为Paused,恢复可见用onResume;onStop,停止activity,恢复启动用onStart;onDestroy,销毁,结束

3.fragment

fragment是一中视图,必须要被包含在view中。fragment可以通过不同屏幕大小配置不同的xml来改变布局,也可以灵活生成fagment,fragment有自己的生命周期,可以多次使用,主要方法,onCreateView,生成view,有两不同的包可以引入,support.v4,和v7.前者的能支持的android版本更低。创建fragment.管理生命周期。处理传来的参数。如何将fragment加入已经存在activity中,根据support.v4和v7的方法不同通过fragmentManager.获得fragment事务管理,进行增加或者移除fragment.

4.如何创建自定义View,创建View的子类,提供context,和参数的构造函数,再通过配置文件,配置他的属性。对属性进行获取,显示

2016-09-14
last update 2016-09-15

2018-07-22 15:01:07 weixin_38374558 阅读数 33

http://hukai.me/android-training-course-in-chinese/multimedia/printing/index.html

  • 打印照片

    这节课将展示如何打印一幅图像。

  • 打印自定义文档

    这节课将展示如何连接到Android打印管理器,创建一个打印适配器并建立要打印的内容。

     

Android 官方培训文档 笔记 (6-10)

阅读数 578

6、Android联系人与位置信息 GMS6.1Android联系人信息ContactsProvider是用户联系人信息的集中仓库,它包含了来自联系人应用与社交应用的联系人数据。在我们的应用中,我们可以通过调用ContentResolver()方法或者通过发送Intent给联系人应用来访问Contactsprovider的信息。6.1.1获取联系人列表

博文 来自: qq_34203494

Android官方培训课程-笔记(数据保存)

阅读数 121

1.如果创建了一个MODE_WORLD_READABLE或者MODE_WORLD_WRITEABLE 模式的sharedpreference文件,则其他任何app均可通过文件名访问该文件。2. Internalstorage: 总是可用的 这里的文件默认只能被我们的app所访问。 当用户卸载app的时候,系统会把internal内该app相关的文件都清除干净。 Int...

博文 来自: weixin_38374558

Android 官方培训文档 笔记 (4)

阅读数 236

4Android图像与动画4.1高效显示Bitmap在安卓应用中加载Bitmaps的操作是需要特别小心处理的,有下面几个方面的原因:1、移动设备的系统资源有限。安卓设备对于蛋哥程序至少需要16MB的内容。AndroidCompatibilityDefinitionDocument(CDD),Section3.7.VirtualMachineCompat

博文 来自: qq_34203494

Android 官方培训文档 笔记 (3)

阅读数 225

3、Android多媒体 3.1.1管理音频播放使用硬件音量键来控制应用的音量在oncreate方法中调用setVolumeControlStream(AudioManager.Stream_Music);使用硬件的播放控制按键来控制应用的音频播放许多线控或无线耳机都会有许多媒体播放控制按钮。无论用户按下设备商任意一个控制按钮,系统都会广播一个带有ACTIO

博文 来自: qq_34203494

Android官方培训课程-笔记(拍照)

阅读数 29

http://hukai.me/android-training-course-in-chinese/multimedia/camera/index.html 轻松拍摄照片 用仅仅几行代码调用其他应用拍照。 轻松录制视频 用仅仅几行代码调用其他应用录像。 控制相机 直接控制相机硬件,实现你自己的相机应用。 与第一行代码第八章结合来看 ...

博文 来自: weixin_38374558
没有更多推荐了,返回首页