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. 湘潭校赛 Easy Wuxing

    Easy Wuxing Accepted : 25   Submit : 124 Time Limit : 1000 MS   Memory Limit : 65536 KB 题目描述 “五行”是中国 ...

  2. 有序的数据结构中:内存操作红黑树快,磁盘操作b+树快

    红黑树常用于存储内存中的有序数据,增删很快,b+树常用于文件系统和数据库索引,因为b树的子节点大于红黑树,红黑树只能有2个子节点,b树子节点大于2,子节点树多这一特点保证了存储相同大小的数据,树的高度 ...

  3. 一个简单的DLL生成和测试

    DLL文件内容: SKLDll.h #ifndef _SKLDLL_H_#define _SKLDLL_H_ #ifndef DLL_API #define DLL_API extern " ...

  4. Java提供了哪些IO方式?IO, BIO, NIO, AIO是什么?

    IO一直是软件开发中的核心部分之一,而随着互联网技术的提高,IO的重要性也越来越重.纵观开发界,能够巧妙运用IO,不但对于公司,而且对于开发人员都非常的重要.Java的IO机制也是一直在不断的完善,以 ...

  5. CSS字体无法设置成功的问题

    在 CSS 中设置字体名称,直接写中文是可以的.但是在文件编码(GB2312.UTF-8 等)不匹配时会产生乱码的错误.xp 系统不支持 类似微软雅黑的中文. 方案一: 你可以使用英文来替代. 比如 ...

  6. Vue2.0项目打包后只能访问首页,其他页面路径错误找不到

    原因是你使用了vue-router的history,可以尝试去掉  // mode:"history",

  7. CentOS 6.x 安装vnc

    https://www.cnblogs.com/pipci/p/7833581.html   1.安装vnc server [root@pxe ~]# yum install tigervnc-ser ...

  8. ArcGIS10.3+Oracle12C+ArcGIS Server10.3安装布署(之二)

    1.创建PDB 输入 dbca 命令 2.安装完成后,连接PDBSDE的容器数据库 3.环境变量 从Oracle的官方网站下载   instantclient-basic-nt-12.1.0.2.0. ...

  9. arcgis 加载高德地图 es6的方式

    目前很多arcgis 加载高德地图是dojo的方式 外部引入文件,现在改成这种方式 /** * Created by Administrator on 2018/5/14 0014. */ impor ...

  10. maven 超级pom位置、maven命令、构件、下载位置、手动打包位置、中央仓库ip

    1.超级pom位置 ----> 解压M2_HOME/lib/maven-model-builder-3.5.4.jar 2.运行maven 命令实际上是运行了 java 命令,因为maven插件 ...