10.1、全局获取Context的技巧

在实践中有很多的地方都可以使用到Context

弹出Toast的时候需要,启动活动的时候需要、发送广播的时候需要、

操作数据库的时候需要、使用通知的时候需要.......

现在的开发中基本上都在使用Context而发愁过

因为操作都是再活动中进行的,活动的本身就是一个Context对象

当应用程序的架构逐渐开始复杂起来的时候

很多的逻辑代码都将脱离Activity类

但是此时由需要使用Context,也许这个时候会感到废脑子

如封装好的网络操作:

此时再方法中添加一个Context参数

并且假设有一个isNetworkAvaiable()方法来判断网路是否可用

虽说上述是一种解决方案,但是却有点推卸责任的嫌疑

因为我们将获取Context的任务转移给sendHttpRequest()方法的调用方

至于用什么方法能不能得到Context对象,那不是我们需要考虑的问题

再某些情况下,获取Context并非是一件容易的事情

有时候还是挺伤脑筋的。

Android提供了一个Application类,每当应用程序启动的时候

系统就会自动将这个类进行初始化

我们可以指定一个自己的Application类

以便于管理程序内一些全局状态的信息

比如全局的Context。

定义自己的Application其实不复杂

首先创建一个MyApplication类继承Application

public class MyApplication extends Application {

    private static Context context;

    @Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
} public static Context getContext(){
return context;
}
}

重写父类的onCreate()方法

通过调用getApplicationContext()方法得到一个应用级别的Context

然后提供一个静态的getContext()方法,在这里将获取到的Context进行返回

接下来需要告知系统,当程序启动的时候应该初始化MyApplication类

而不是默认的Application类

再AndroidManifest.xml文件中的<application>标签下进行注册

        <activity android:name="com.example.ccrr.material.MyApplication">

        </activity>

指定的时候一定要加上完整的包名,不然系统将无法找到这个类

这样就有一套全局获取Context的机制

不管咋任何地放进行使用Context,只需要调用一些:MyAppcation.getContext()方法即可

此时再sendHttpRequest()方法中优化如下:

这里的sendHttpRequest()方法不需要传入参数的方式来得到Context对象

而是调用MyApplication.getContext()方法即可

之前使用的LitePal就能再内部自动获取到Context

已经配置过Application是否会和LitePalApplication产生冲突

任何一个项目都只能配置一个Application

对于这种情况,LitePal提供了更加简单的使用方法

如下:

使用这种写法就相当于把全局的Context对象通过参数传给LitePal

效果和AndroidManifest.xml配置LitePalApplication是一样的

10.2、使用Intent传递对象

Intent在之前的使用已经相当熟悉了

可以借助他来启动活动、发送广播、启动服务等

同时还可以在Intent中添加一些附带的数据,已达到传值的效果

在FirstActivity中

这调用Intent的putExtra()方法来添加要传递的数据

之后再SecondActivity中

但是putExtra()方法中所支持的数据类型是有限的

对常用一些数据类型都是支持的

若是定义一些自定义的对象的时候就会无从下手

下方的有一些技巧

10.2.1、Seriallizable

serializable是序列化的意思

表示将一个对象转换成可存储或者可传输的状态

序列化后的对象可以在网络上进行传输,也可以存储再本地

至于序列化的方法很简单,只需要让一个类实现Serializable这个接口即可

实例:

定义一个Person类,其中包含了name和age这两个字段,实现序列化实现接口即可

其中get、set方法都是用于赋值和读取字段的数据

最重要的一部分再第一行

这里让Person类去实现Serializable接口

这样所有的Person对象都是看可序列化的

然后再FirstActivity中:

这里新建的一个Personde实例

然后就直接将他们传入到putExtra()方法

由于再Person类实现了Serializable接口,所以是这个写法

再SecondActivity中

调用getSerializableExtra()方法获取通过参数传递过来的序列化对象

接着将它转为Person对象

此时成功实现了使用Intent来传递对象的功能

10.2.2、Parcelable方式

除了Serializable之外,使用Parcelable也可以实现相同的效果

不过不同于将对象序列化

Parceleable方式实现的原理是一个将完整的对象进行分家

而后分解的每一部分都是Intent所支持的数据类型,这样就实现了传递对象的功能。

修改Person中的代码

Parcleable的实现方式稍微复杂一些

首先让类实现Parcleable接口,因此必须实现describeContents()方法和writeToParcel()方法

describeContents() 方法直接返回为0即可

writeToParcel() 方法中需要调用Parcel的writeXxx()方法,将Person类中的字段一一写相互

注意:根据数据类型进行调用,string、int....

还需要再Person类中提供一个名为CREATOR的常量

这里创建一个Paraelable.Creator接口的一个实现

接着重写createFromParcel()和newArray()这两个方法

createFromParcel()方法中读取刚刚写出的name、age字段,并且创建一个Person对象进行返回

其中name个age都是需要调用Parcel的readXxx()方法读取到,这里也需要注意类型string、int,以及读顺序和写顺序相同

再newArray()方法中只需要new一个Person数组,使用方法中传入size作为数组的大小即可

再SecondActivity中:

这里使用getParcelableExtra()方法来获取数据传递过来的对象

其他地方一致

10.3、定制自己的日志工具

对于日志的使用

并且再开发中经常使用做数据测试操作

但是这种使用再日志的控制方面还是做的不是很好

再大型项目中会再很多地方使用日志进行打印

再项目完成时就是再代码中调式的日志问题

在项目上线时还会进行打印,很容易降低程序的运行效率、还有可能将数据泄露出

解决最简单的方式是能够自由地控制日志的打印

当程序处于开发阶段就让日志打印出来

程序上线之后舅把日志屏幕掉

需要定制一个自己的日志工具:

10.4、创建定时任务

定时任务由两种实现方式:

1、使用Java Api里提供的Timer类

2、使用Android的Alarm机制

两种方式在多数情况下都能实现类似的效果

但Timer有一个明显的短板

不适用于那些长期在后台运行的定时任务

为了能让电池更加耐用,每种手机都会由自己的休眠策略

Android手机就会长期在不操作的情况下自动让CPU进入到休眠状态

这就有可能导致Timer中的定时任务无法正常执行

而Alarm具有唤醒CPU的功能

可以保证在大多数情况下需要请求执行任务的时候CPU都能正常工作

唤醒CPU和唤醒屏幕不是一个概念的问题

10.4.1、Alarm机制

主要借助了AlarmManager类来实现的

这个类和NotificationManager有点类似

都是通过调用Context的getSystemService()方法来获取实例

这里需要传入的的参数是Context.ALARM_SERVICE

因此获取一个AlarmManage的实例:

接下来调用AlarmManager的set()方法就可以设置一个定时任务

比如设置一个10秒中后执行,就可以写成:

set()方法需要传入三个参数

1、整形参数,用于指定AlarmManager的工作类型有四个可选值

  ELAPSED_REALTIME、ELAPSED_REALTIME_WARKUP、RTC和RTC_WAKEUP

  ELAPSED_REALTIME:表示让定时任务的触发时间从系统开机开始算起,但是不会唤醒CPU

  ELAPSED_REALTIME_WARKUP:表示让定时任务的触发时间从系统时间开始算起,但是不会唤醒CPU

  RTC:表示任务的触发时间是从1970年1月1日0点开始算起,但是会唤醒CPU

  RTC_WAKEUP:表示任务的触发时间是从1970年1月1日0点开始算起,但是会唤醒CPU

  使用SystemClock.elapsedRealtime()方法可以获取到系统开机至今所经历时间的毫秒数

  使用System.currentTimeMills()方法可以获取到1970年1月1日0点至今所经历的毫秒数

2、这个参数是定时任务触发的事件,以毫秒为单位

  如果第一个参数使用的是ELAPSED_REALTIME、ELAPSED_REALTIME_WARKUP

  这里传入开机至今的事件加上延迟执行的时间

  如果第一个参数使用的是RTC、RTC_WAKEUP

  这里传入1970年1月1日0点至今的时间在加上延迟的时间

3、此时的参数是一个PendingIntent,这里一般会调用getService()方法或者getBroadcast方法来获取一个能够

  执行服务或广播的PendingIntent,这样当任务被触发的时候,服务的onStratCommand()方法或广播接收器

  onReceive()方法就可以得到执行

所以此时的set()方法,设定一个任务在10秒钟后执行可以:

如果要实现一个长时间在后台定时运行的服务

首先创建一个普通的服务

再将触发的定时任务代码写在onStratCommand()方法

首先在onStratCommand()方法中开启一个子线程

在这里可以执行一些具体的操作

之所以在子线程中执行逻辑操作

是因为逻辑操作也需要耗时的

在主线程中执行可能会对定时的准确性造成影响

创建线程之后的代码就是Alarm机制的使用

首先获取了AlarmManager的实例

然后在定义任务的触发时间为一小时之后

在使用PendingIntent执行处理定时任务的服务为LongRunningSevice

最后调用set()方法完成设定

这样就定义了一个 长时间在后台运行的服务实现

因为一旦启动了LongRunningService

就会在onStartCommand()方法里设定一个定时任务

这样一个小时后将会再次启动LongRunningServie

从而形成了一个永久的循环

保证LongRuningService的onStratCommand()方法可以每隔一小时就执行一次

注意的是:

4.4系统开始,Alarm任务的触发时间将会变得不准确

有时会延迟一段时间之后任务才能得到执行

这不是一个bug,而是系统对耗电方面性能的优化

系统会自动检测目前有多少个Alarm任务存在

然后触发时间相近的几个任务放在一起执行

这样就可以大幅度减少CPU被唤醒的次数,从而提高电池的使用时间

如果要求Alarm任务的执行时间必须准确无误

Android提供了解决方案

使用AlarmManager的setExact()方法来代替set()方法

基本上就可以保证任务能够准确的执行

10.4.2、Doze模式

虽然Android的每个版本都在手机电量方面的努力进行优化

不过一直没有解决后台服务泛滥、手机电量消耗过快的问题

于是在Android6.0系统中,谷歌加入了一个全新的Doze模式

从而及大幅度的延长电池的使用寿命

首先Doze模式:

当用户设备是一个Android6.0或以上的系统时

如果设备未插电源,处于静止状态,且屏幕关闭了一段时间之后,就会进入Doze模式

早Doze模式下:系统会对CPU、网络、Alarm等活动进行限制,从而延长了电池的使用寿命

系统并不会一直处于Doze模式,而是间接性的退出Doze模式一小段时间

在这段时间中,应用可以完成他们的同部操作、Alarm任务等等

随着设备进入Doze模式的时间越长,间接性的退出Doze模式的时间间隔也会越来越长

因为如果设备长时间不使用的话,是没必要频繁的退出Doze模式来执行同部操作的

Android在这些细节上的把控使得电池寿命进一步得到了延长

Doze模式下会有一些功能会受到限制:

最后一条:

在Doze模式下,我们的Alarm任务将会变得不准时

当然,这在大多情况下是合理的,因为当用户长时间不使用手机才会进入Doze模式

通常这种情况下对ALarm任务的准确性要求没有那么高

真的有特殊需求

需求对Alarm任务模式即使在Doze模式情况下也能必须正常执行

Android还提供了解决方案

调用AlarmManage的setAndAllowWhileIdle()或setExactAndAllowWhileIdle()方法

能够让定时任务即使在Doze模式下也能进行正常执行

这两个方法之间的区别和set()、setExact()方法之间的区别一致。

10、Android--技巧的更多相关文章

  1. 【转】天啦噜!原来Chrome自带的开发者工具还能这么用!(提升JS调试能力的10个技巧)

    天啦噜!原来Chrome自带的开发者工具还能这么用! (提升JS调试能力的10个技巧)   Chrome自带开发者工具.它的功能十分丰富,包括元素.网络.安全等等.今天我们主要介绍JavaScript ...

  2. 编写高性能Web应用程序的10个技巧

    这篇文章讨论了: ·一般ASP.NET性能的秘密 ·能提高ASP.NET表现的有用的技巧和窍门 ·在ASP.NET中使用数据库的建议 ·ASP.NET中的缓存和后台处理 使用ASP.NET编写一个We ...

  3. ExecutorService - 10个技巧和窍门

    ExecutorService已经成为Java并发编程中常用的基础库,几乎所有到线程 任务等执行都要委托ExecutorService.下面是使用过程中10个技巧和窍门. 1.为线程池和线程取名 当我 ...

  4. 让你的 Node.js 应用跑得更快的 10 个技巧(转)

    Node.js 受益于它的事件驱动和异步的特征,已经很快了.但是,在现代网络中只是快是不行的.如果你打算用 Node.js 开发你的下一个Web 应用的话,那么你就应该无所不用其极,让你的应用更快,异 ...

  5. 转自微软内部资料:编写高性能 Web 应用程序的 10 个技巧

    编写高性能 Web 应用程序的 10 个技巧 转自微软资料数据层性能技巧 1 — 返回多个结果集技巧 2 — 分页的数据访问技巧 3 — 连接池技巧 4 — ASP.NET 缓存 API技巧 5 — ...

  6. 10个技巧优化PHP程序Laravel 5框架

    10个技巧优化PHP程序Laravel 5框架 性能一直是 Laravel 框架为人诟病的一个点,所以调优 Laravel 程序算是一个必学的技能. 接下来分享一些开发的最佳实践www.itxdl.c ...

  7. MAC OS进阶必看——这10个技巧让你秒变MAC达人

    文章内容及图片来源于:什么值得买,如果涉及版权问题,请联系作者删除 文章收录于:风云社区(提供上千款各类mac软件的下载) 使用mac系统也有好几个年头,出色的办公效率以及越来越广的兼容性让mac成为 ...

  8. Eclipse调试Java的10个技巧【转】

    clipse调试Java的10个技巧 先提三点 不要使用System.out.println作为调试工具 启用所有组件的详细的日志记录级别 使用一个日志分析器来阅读日志 1.条件断点 想象一下我们平时 ...

  9. Android技巧分享——如何用电脑下载在Google play中应用的apk文件

    [Android技巧分享系列] 1.Android技巧分享——让官方模拟器和genymotion虚拟机飞起来 2.Android技巧分享——如何用电脑下载在Google play中应用的apk文件 G ...

  10. 2016 Top 10 Android Library

    过去的 2016 年,开源社区异常活跃,很多个人与公司争相开源自己的项目,让人眼花缭乱,然而有些项目只是昙花一现,有些项目却持久创造价值,为开发者提供了极大的便利,这些终究由时间来判断.今天,我就来整 ...

随机推荐

  1. angular2 如何使用websocket

    1.npm下载: npm install angular2-websocket 2.需要在哪个组件使用就在那里引入: import {$WebSocket} from 'angular2-websoc ...

  2. OpenGL学习--02--绘制一个红色三角形

    The OpenGL buffer is created, bound, filled and configured with the standard functions (glGenBuffers ...

  3. IDEA操作maven时控制台中文乱码

    windows环境下,Intellij idea12中maven操作时,控制台中文乱码问题(编译报错或者clean install时出现的其他错误描述乱码) 在cmd中mvn中文正常显示,log4j打 ...

  4. ArcGIS for JavaScript 关于路径开发的一些记录(一)

    今年毕业,进入公司的第一个任务就是单独负责一个项目的地图模块,用ArcGIS API for JavaScript来开发web地图.花了大概一个礼拜的时间学会了安装和搭建ArcGIS Server和A ...

  5. 搭建Kafka开发环境

    Kafka版本是:kafka_2.10-0.8.2.1 1.maven工程方式 在pom.xml中配置kafka依赖 1 2 3 4 5 <dependency>     <grou ...

  6. 二、ionic如何使用外链

    1.ionic如何使用外链并返回原有页面? html如下: 对应的controller如下: (function() { angular.module('app').controller('extra ...

  7. javascript strict mode

    ECMAScript 版本5是目前最广泛使用的js版本. 其中的一个重要feature strict mode很多人不是很清除和理解. 什么是strict mode? strict mdoe是一种强制 ...

  8. Linux 挂载

    千万不要挂载到 根目录下 也不要用 umount -fl  会死的 fdisk -l 看 能挂载的是哪个盘 格式化 mkfs.ext4 /dev/vde 创建一个文件 mkdir /testmnt 卸 ...

  9. Oracle EBS OM发运行状态自动更改

  10. I/O复用及epoll基础知识

    IO multiplexing IO multiplexing这个词可能有点陌生,但是如果我说select,epoll,大概就都能明白了.有些地方也称这种IO方式为event driven IO.我们 ...