目录:

13.1 全局获取 Context的技巧

13.2 使用 Intent传递对象

13.2.1 Serializable 方式

13.2.2 Parcelable 方式

13.3 定制自己的日志工具

13.4 调试Android 程序

13.5 创建定时任务

13.5.1 Alarm 机制

13.5.2 Doze模式

13.6 多窗口模式编程

13.6.1 进入多窗口模式

13.6.2 多窗口模式下的生命周期

13.6.3 禁用多窗口模式

13.7 Lambda 表达式

13.8 总结


知识点:

13.1 全局获取 Context的技巧

当应用程序的架构逐渐开始复杂起来的时候,很多的逻辑代码都将脱离Activity类,这个时候你就要伤脑筋了。

下面就来学习一种技巧,让你在项目的任何地方都能够轻松获取到Context。

  Android 提供了一个 Application 类,每当应用程序启动时,系统就会自动将这个类进行初始化。我们可以定制一个自己的 Application 类,以便管理程序内一些全局的状态信息,比如全局的 Context。

  定制一个自己的 Application 并不复杂,首先需要创建一个 MyApplication 类继承自 Application,如下:

public class MyApplication extends Application {private static Context context;@Overridepublic void onCreate() {context = getApplicationContext();}public static Context getContext(){return context;}
}

  接下来在 AndroidManifest.xml 文件的<application>标签下进行指定就可以了,如下:

 <applicationandroid:name=".MyApplication"android:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:supportsRtl="true"android:theme="@style/AppTheme">. . .
</application>

  这样就实现了一种全局获取 Context 的机制,之后在项目的任何地方想要获取 Context,只需调用 MyApplication.getContext() 就可以了,如弹吐司:

Toast.makeText(MyApplication.getContext(),"提示内容",Toast.LENGTH_SHORT).show();

  任何一个项目都只能配置一个 Application,当引用第三方库如 LitePal 时要配置 LitePalApplication 就会起冲突了,这种情况就要在自己的 Application 中去调用 LitePal 的初始化方法,如下:

public class MyApplication extends Application {private static Context context;@Overridepublic void onCreate() {context = getApplicationContext();// 调用 LitePal 的初始化方法LitePal.initialize(context);}public static Context getContext(){return context;}
}

  使用上面的写法,把 Context 对象通过参数传递给 LitePal,效果和在 AndroidManifest.xml 中配置 LitePalApplication 是一样的。

  当然,我个人是更习惯于通过获取全局类实例的方法来定制自己的 Application 类,如下:

public class MyApplication extends Application {private static MyApplication mInstance;@Overridepublic void onCreate() {super.onCreate();mInstance = this;// 调用 LitePal 的初始化方法LitePal.initialize(this);        }/*** Singleton main method. Provides the global static instance of the helper class.* @return The MyApplication instance.*/public static synchronized MyApplication getInstance() {return mInstance;}
}

13.2 使用 Intent传递对象

使用 Intent 时,可以在 Intent 中添加一些附加数据,以达到传值的效果,如在第一个活动中添加如下代码:

Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
intent.putExtra("string_data","hello");
intent.putExtra("int_data",100);
startActivity(intent);

  然后在第二个活动中就可以获得这些值了,如下:

getIntent().getStringExtra("string_data");
getIntent().getIntExtra("int_data",0);

  但上面的 putExtra() 方法中所支持的数据类型是有限的,若要传递一些自定义对象时就无从下手了,下面就来学习下用 Intent 来传递对象的技巧:SerializableParcelable

13.2.1 Serializable 方式

Serializable是序列化的意思,表示将一个对象转化成可储存或可传输的状态。序列化的对象可在网络上传输也可存储到本地。将一个类序列化只要去实现 Serializable 接口就可以了。

比如一个 Person1 类,将它序列化可以这样写:

package com.dak.administrator.firstcode.more;import android.os.Parcel;
import android.os.Parcelable;/*** Created by Administrator on 2018/11/13.*/public class Person implements Parcelable {private int age;private String name;public static final Creator<Person> CREATOR = new Creator<Person>() {@Overridepublic Person createFromParcel(Parcel in) {Person person = new Person();person.age = in.readInt();  //顺序要和写入相同person.name = in.readString();return person;}@Overridepublic Person[] newArray(int size) {return new Person[size];}};@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel parcel, int i) {parcel.writeInt(age);parcel.writeString(name);}
}

接下来在第一个活动中的写法非常简单:

Person1 person = new Person1();
person.setName("Tom");
person.setAge(18);
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
intent.putExtra("person_data",person);
startActivity(intent);

然后在第二个活动中获取对象也非常简单:

Person1 person = (Person1) getIntent().getSerializableExtra("person_data");

这样就实现了使用 Intent 传递对象了。

13.2.2 Parcelable 方式

Parcelable 也可以实现相同的效果,不过不同于将对象进行序列化,Parcelable 方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是Intent所支持的数据类型,这样也就实现传递对象的功能了。

新建Person类继承Parcelable:

package com.dak.administrator.firstcode.more;import android.os.Parcel;
import android.os.Parcelable;/*** Created by Administrator on 2018/11/13.*/public class Person implements Parcelable {private int age;private String name;public static final Creator<Person> CREATOR = new Creator<Person>() {@Overridepublic Person createFromParcel(Parcel in) {Person person = new Person();person.age = in.readInt();  //顺序要和写入相同person.name = in.readString();return person;}@Overridepublic Person[] newArray(int size) {return new Person[size];}};@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel parcel, int i) {parcel.writeInt(age);parcel.writeString(name);}
}

注意:Serializable 的方式较为简单,但由于把整个对象进行序列化,效率会比 Parcelable 方式低。一般推荐使用 Parcelable 的方式来实现 Intent 传递对象的功能。

13.3 定制自己的日志工具

虽然Android自带的日志工具功能非常强大,但也不是没有缺点,比如,你正在编写一个比较庞大的项目,用到了大量的日志,这样在项目正式上线后,仍然会照常打印,这样不仅会降低程序的运行效率,还有可能就将一些机密性额数据泄露出去。

为此,我们自定义LogUtil 类:

public class LogUtils {public static final int VERBOSE = 1;public static final int DEBUG = 2;public static final int INFO = 3;public static final int WARN = 4;public static final int ERROR = 5;public static final int NOTHING = 6;public static int level = VERBOSE;public static void v(String tag,String msg){if (level <= VERBOSE){Log.v(tag,msg);}}public static void d(String tag,String msg){if (level <= DEBUG){Log.d(tag,msg);}}public static void i(String tag,String msg){if (level <= INFO){Log.i(tag,msg);}}public static void w(String tag,String msg){if (level <= WARN){Log.w(tag,msg);}}public static void e(String tag,String msg){if (level <= ERROR){Log.e(tag,msg);}}
}

13.4 调试Android 程序

当开发过程中遇到一些奇怪的bug,但又迟迟定位不出来,最好的解决方法就是调试了。

不用多说,调试的第一步肯定是添加断点,添加断点的方式也很多简单,只需要在响应的代码行左边点击一下就可以了。

如果想要取消这个断点,再次点击即可。

功能:

F7 跳入  看到方法往里走

F8 跳过  每按一次代码就会向下执行一行

F9 跨断点调试

等等。

推荐链接:https://blog.csdn.net/dd864140130/article/details/51560664

13.5 创建定时任务

Android 中的定时任务一般有两种实现方式,一种是使用 Java API 里提供的 Timer 类(不太适用于需要长期在后台运行的定时任务),一种是使用 Android 的 Alarm 机制(具有唤醒 CPU 功能,可以保证大多数情况下执行定时任务时 CPU 能正常工作)。

13.5.1 Alarm 机制

Alarm 机制的用法不复杂,主要是借助 AlarmManager 类来实现的。比如想要设定一个任务在 10 秒钟后执行,可写成:

// 获取 AlarmManager 的实例
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);// 设置触发时间
// SystemClock.elapsedRealtime() 获取系统开机至今所经历时间的毫秒数
// SystemClock.currentTimeMillis() 获取1970年1月1日0点至今所经历时间的毫秒数
long triggerAtTime = SystemClock.elapsedRealtime() + 10 * 1000;// 3个参数:指定 AlarmManager 的工作类型、定时任务的触发时间、PendingIntent
// 其中AlarmManager 的工作类型有四种:
// ELAPSED_REALTIME 定时任务的触发时间从系统开机开始时算起,不会唤醒 CPU
// ELAPSED_REALTIME_WAKEUP 系统开机开始时算起,会唤醒 CPU
// RTC 从1970年1月1日0点开始算起,不会唤醒 CPU
// RTC_WAKEUP 从1970年1月1日0点开始算起,会唤醒 CPU
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtTime,pandingIntent);

举个例子,实现一个长时间在后台定时运行的服务,首先新建一个普通的服务 LongRunningService,将触发定时任务的代码写到 onStartCommand() 方法中,如下:

public class LongRunningService extends Service {public LongRunningService() {}@Overridepublic IBinder onBind(Intent intent) {throw new UnsupportedOperationException("Not yet implemented");}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {new Thread(new Runnable() {@Overridepublic void run() {// 在这里执行具体的逻辑操作}}).start();AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);int anHour = 60 * 60 * 1000;//1小时的毫秒数long triggerAtTime = SystemClock.elapsedRealtime() + anHour;Intent i = new Intent(this,LongRunningService.class);PendingIntent pi = PendingIntent.getService(this,0,i,0);manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtTime,pi);return super.onStartCommand(intent, flags, startId);}
}

然后,要启动定时服务时调用如下代码即可:

Intent intent = new Intent(context,LongRunningService.class);
context.startService(intent);

值得注意的是,从 Android 4.4开始,由于系统在耗电方面的优化,Alarm 任务的触发时间变得不准确,可能会延迟一段时间后再执行。当然,使用 AlarmManager 的 setExact() 方法来替代 set() 方法,基本上可以保证任务准时执行。

13.5.2 Doze模式

  在 Android 6.0中,谷歌加入了一个全新的 Doze 模式,可以极大幅度地延长电池的使用寿命。下面就来了解下这个模式,掌握一些编程时注意事项。

  在 6.0 及以上系统的设备上,若未插接电源,处于静止状态(7.0中删除了这一条件),且屏幕关闭了一段时间之后,就会进入到 Doze 模式。在 Doze 模式下,系统会对 CPU、网络、Alarm 等活动进行限制,从而延长电池的使用寿命。

  当然,系统不会一直处于 Doze 模式,而是会间歇性的退出一小段时间,在这段时间应用可以去完成它们的同步操作、Alarm 任务等,其工作过程如下:

Doze 模式的工作过程

  Doze 模式下受限的功能有:
 (1)网络访问被禁止
 (2)系统忽略唤醒CPU或屏幕操作
 (3)系统不再执行WIFI扫描
 (4)系统不再执行同步任务
 (5)Alarm 任务将会在下次退出 Doze 模式时执行

  特殊需求,要 Alarm 任务在 Doze 模式下也必须正常执行,则可以调用 AlarmManager 的 setAndAllowWhileIdle() 或 setExactAndAllowWhileIdle() 方法。

13.6 多窗口模式编程

Android 7.0 系统中引入了一个非常有特色的功能——多窗口模式,它允许我们在同一个屏幕中打开两个应用程序。

13.6.1 进入多窗口模式

在 OverView 列表界面长按任意一个活动的标题,将该活动拖到屏幕突出显示的区域,则可以进入多窗口模式。

打开任意一个程序,长按 OverView 按钮,也可以进入多窗口模式。

13.6.2 多窗口模式下的生命周期

这一块是比较重要的。

多窗口模式并不会改变活动原有的生命周期,只是会将用户最近交互过的那个活动设置为运行状态,而将多窗口模式下另外一个可见活动设置为暂停状态。若这时用户又去和暂停的活动进行交互,那么该活动就变成运行状态,之前处于运行状态的活动变成暂停状态。

进入多窗口模式时活动会被重新创建,若要改变这一默认行为,可以在 AndroidManifest.xml 中对活动添加如下配置:

android:configChanges="orientation|keyboardHidden|screenSize|screenLayout"

  添加这行配置后,不管是进入多窗口模式还是横竖屏切换,活动都不会被重新创建,而是会将屏幕发生变化的事件通知到 Activity 的 onConfigurationChanged() 方法中。因此,若要在屏幕发生变化时进行相应的逻辑处理,那么在活动中重写 onConfigurationChanged() 方法即可。

13.6.3 禁用多窗口模式

在 AndroidManifest.xml 中,只要在Activity 或者 application中添加 android:resizeableActivity="false"  即可。

13.7 Lambda 表达式

Lambda表达式本质上是一种一名方法,它既没有方法名,也没有访问修饰符和返回值类型,使用它来编写代码将会更加简介,也更加易读。

Android Studio 2.1.1之前,需要自己导入插件

 dependencies {classpath 'me.tatarka:gradle-retrolambda:3.2.0'}

在 Module 的 build.gradle 中添加如下代码

// 应用插件apply plugin: 'me.tatarka.retrolambda'// 支持Java8android {compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}}

Android Studio 2.1.1之后(支持lambda插件)

android {defaultConfig {jackOptions {// 打开jack编译器enabled true}}// 编译支持Java8compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}}

相关教程:https://blog.csdn.net/ioriogami/article/details/12782141/

在Android中使用lambda表达式:https://www.jianshu.com/p/ef6cbf5ade71

13.8 总结

郭霖总结:

整整13章的内容你已经学完了!本书的所有知识点也到此结束,是不是感觉有些激动呢,下面就让我们来回顾和总结一下这就么久以来学过的所有东西吧。

这13章的内容不算很多,但却已经把Adroid中绝大部分比较重要的知识点都覆盖到了。我们从搭建开发环境开始学起,后面逐步学习了四大组件、UI、碎片、数据存储、多媒体、网络、定位服务、Material Design等内容,本章中又学习了如全局获取Context.定制日志工具、调试程序、多窗口模式编程、Lambda表达式等高级技巧,相信你已经从一名初学者蜕变成为Android开发好手了。

不过,虽然你已经储备了足够多的知识,并掌握了很多的最佳实践技巧,但是你还从来没有真正开发过一一 个完整的项目,也许在将所有学到的知识混合到-一起使用的时候,你会感到有些手足无措。因此,前进的脚步仍然不能停下,下一章中我们会结合前面章节所学的内容,-一起开发-一个天气预报程序。锻炼的机会可千万不能错过,赶快进人到下一章吧。

我的总结:

本专栏到此结束,下一步将阅读Andorid 开发艺术探索,希望各位,届时给个赞,关注我一下,让我可以更努力去学习,然后分享给大家。

第一行代码最后两章分别是 酷派天气 和 上架App的内容,对此就不作为相关知识点来记录了。以下给出我多个章节的代码链接,如有需要,欢迎下载。

多章代码链接:https://download.csdn.net/download/lhk147852369/10812367

第一行代码——第十三章:继续进阶——你还应该掌握的高级技巧相关推荐

  1. 第一行代码Android第二章读书笔记

    第一行代码Android第二章读书笔记 Activity 1.1 手动创建活动 1.2 Toast和Menu/销毁活动 Intent 2.1 显示/隐式 2.2 传递/返回数据 活动的生命周期 3.1 ...

  2. 第一行代码 第六章 数据储存方案 - LitePal数据库存储

    LitePal – 一款开源的Android数据库框架. 它采用对象关系映射的模式(ORM),将开发中常用的数据库功能进行封装,使得不用编写SQL语句就可以完成各种建表和增删改查的操作. 在项目中使用 ...

  3. Android第一行代码——第三章:控件的使用方法5A-00-1A-C4-8C-55(2009+jjy)

    标题:这章主要学习如何控件的使用方法 1 TextView. 创建activity_main.xml中的代码 代码如下: <?xml version="1.0" encodi ...

  4. 《Android 第一行代码》十一章 Service学习笔记

    Android中Service学习笔记 Service的基本使用方法 Service的启动方式有两种,第一种是使用startService()和stopService()方法来启动和停止Service ...

  5. 《Android 第一行代码》十一章 “服务的最佳实践”

    服务的最佳实践 项目笔记 上面我们学习的Service服务的基本使用,接下来通过一个具体的下载实例来强化service的使用过程. 1. 新建一个DownloadListener接口 此接口提供了5个 ...

  6. 第一行代码-第二版(郭霖著)笔记十一(高级技巧)

    目录 一.全局获取Context的技巧 二.使用Intent传递对象 1.Serializable方式 2.Parcelable方式 三.定制自己的日志工具 四.调试Android程序 五.深色主题 ...

  7. 第一行代码 Android (郭霖 著)

    https://github.com/guolindev/booksource 第1章 开始启程----你的第一行Android代码 (已看) 第2章 先从看得到的入手----探究活动 (已看) 第3 ...

  8. 《第一行代码》封面诞生记

    <第一行代码>这本书,自2014年首次出版以来,已经过去了6年的时间.在这6年时间里,这本书一共升级改版了3次,包括即将出版但还未出版的这次. 虽然每次改版升级,书的封面都会或多或少发生些 ...

  9. 第一行代码第一章——你的第一行Android代码

    第一行代码第一章-你的第一行Android代码 知识点目录 1.1 了解全貌--Android王国简介 * 1.1.1 Android系统架构 * 1.1.2 Android已发布的版本 * 1.1. ...

最新文章

  1. python中完善decorator
  2. JS中的call和apply
  3. 如何用 Markdown 来画图?
  4. 分布式理论:CAP理论
  5. Mysql优化(三):优化order by
  6. Qt文档阅读笔记-Threaded Fortune Server Example解析
  7. C# 实现在线软件自动升级自动下载更新文件
  8. win10 安装Pytorch GPU版+CUDA+cuDNN(篇幅较长保姆教程) (含CUDA11.1与cuDNN8.0.4安装包)
  9. App ui界面设计模板素材,分分钟激活灵感
  10. (万里开源)greatdb mysql 8.0以上版本创建用户并授权远程连接
  11. Python——Matplotlib库入门
  12. 破圈法求最小生成树_【学科加油站】悉大COMP9007 最小生成树知识点总结!
  13. java中this用法
  14. web网页设计制作成品 ——服装明星主页(7页) 表格带留言板带音乐HTML+CSS+JavaScript
  15. Android app中这样用flow更方便-加载列表数据
  16. 基于SDN网络的优化技术和QoS研究分析(二)
  17. 看《梦华录》上头的人都该尝试下这款抖音特效
  18. C# Unsafe code may only appear if compiling with /unsafe
  19. 为什么你关不掉手机里的广告?
  20. Uber火了!它改变了哪些营销游戏规则?

热门文章

  1. CSAPP第五章家庭作业参考答案
  2. 计算机进位制转换方法,计算机进位数制及其转换方法和技巧
  3. 输入股票代码判断深市还是沪市,python
  4. 幂函数的c语言程序,C ++中的幂函数
  5. c语言:(指针)输入一行文字,找出其中的大写字母,小写字母,数字,空格以及其他字符
  6. 解读企业领域热词——BYOD
  7. 下次激活策略10_实体店生意经:6招引流策略,引爆客流!可套用任何行业
  8. 全新笔记本电脑荣耀MagicBook 14 整合优化搭配软件协同属实好用
  9. 解决pip下载速度慢的问题:更换国内源
  10. 卧槽!用低代码平台,3个小时搭了一套“健康上报系统”!