那些Android开发者必备的技能

Posted 姓chen的大键哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了那些Android开发者必备的技能相关的知识,希望对你有一定的参考价值。

文章目录


这都0202年了,android手机早已是人手一部,随着5G的推广,Android手机会出现新变化,这对Android开发者来说既是契机又是挑战。时代在变化,技术在更新,作为一名Android开发者,有些开发技巧必须掌握,这样能提高我们的开发效率

全局获取Context

当应用程序的架构逐渐复杂的时候,很多逻辑代码都将脱离Activity类,若某一个逻辑需要获取Context,那需要通过Application类来实现。
Android提供了一个Application类,每当应用程序启动的时候,系统就会自动将这个类进行初始化。开发者可以定制Application类来管理全局状态信息,例如Context。

public class MyApplication extends Application 

	private static Context context;
	@Override
	public void onCreate() 
		//获取应用Context
		context = getApplicationContext();
	
	//通过这个静态方法从非Activity类中获取Context
	public static Context getContext() 
		return context;
	

通过上述代码可以在其他类中获取Context,除此之外,还需要在AndroidManifest.xml文件更改默认的Application,这样程序启动时就会初始化自定义Application类了(每个项目只能配置一个Application):

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
	package="cn.chenjianlink.android.test"
	android:versionCode="1"
	android:versionName="1.0" >
	...
	<application
		android:name="cn.chenjianlink.android.MyApplication"
		...>
		...
	</application>
</manifest>

用Intent传递对象

使用用Intent来传递对象通常有两种实现方式:Serializable和Parcelable

Serializable方式

Serializable表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。实现Serializable序列化方式只需要一个类实现Serializable接口,然后为类中要序列化的字段添加get、set方法:

public class Person implements Serializable
	private String name;

	private int age;

	public String getName() 
		return name;
	
	public void setName(String name) 
		this.name = name;
	
	public int getAge() 
		return age;
	
	public void setAge(int age) 
		this.age = age;
	

将这个类的对象传入Intent对象中:

Person person = new Person();
person.setName("chenjian");
person.setAge(22);
Intent intent = new Intent(MainActivity.this, MyActivity.class);
intent.putExtra("person_data", person);
startActivity(intent);

要从Intent中获取这个对象则通过如下代码:

Person person = (Person) getIntent().getSerializableExtra("person_data");
  • getSerializableExtra():获取通过参数传递过来的序列化对象,只适用Serializable方式

Parcelable方式

Parcelable方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是Intent所支持的数据类型,这样就能传递对象。
要通过Parcelable方式传递对象,则需要实现Parcelable接口,重写describeContents()writeToParcel() 这两个方法

public class Person implements Parcelable 
	private String name;
	private int age;
	...
	@Override
	public int describeContents() 
		return 0;
	
	@Override
	public void writeToParcel(Parcel dest, int flags) 
		dest.writeString(name);
		dest.writeInt(age);
	
	public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() 
		@Override
		public Person createFromParcel(Parcel source) 
			Person person = new Person();
			person.name = source.readString(); // 读取name
			person.age = source.readInt(); // 读取age
			return person;
		
		@Override
		public Person[] newArray(int size) 
			return new Person[size];
		
	;

  • describeContents() 方法一般直接返回0
  • writeToParcel() 方法中调用Parcel类的writeXxx() 方法将要序列化的字段进行写出
  • 必须提供一个名为CREATOR 的常量,一般是Parcelable.Creator接口的一个实现。重写createFromParcel()newArray() 这两个方法
  • createFromParcel() 方法中调用readXxx() 方法获取字段,读取顺序与writeToParcel() 方法中写入顺序一致,最后返回类对象
  • newArray() 方法中需要new出一个类的数组,并使用方法中传入的size作为数组大小

定制日志工具

在开发过程中会经常用到日志工具,在项目中会有大量与日志相关的代码,项目上线以后这些日志会照常打印,有可能会泄露机密数据,但在项目上线前将这些日志代码删除也不现实,后期维护的时候仍需要这些日志,对付这种情况,能自由控制日志的打印是最好的方法,开发时打印日志,上线时屏蔽日志。

public class LogUtil 
	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);
		
	

通过设置level的数值来实现对日志的打印与屏蔽

定时任务

Android中的定时任务一般有两种实现方式,一种是使用Java API里提供的Timer类,一种是使用Android的Alarm机制。为了能让电池更加耐用,每种手机都会有自己的休眠策略,Android手机就会在长时间不操作的情况下自动让CPU进入到睡眠状态,这就有可能导致Timer中的定时任务无法正常运行。Alarm则具有唤醒CPU的功能,它可以保证在大多数情况下需要执行定时任务的时候CPU都能正常工作

Alarm机制

Alarm机制需要借助AlarmManager类来实现,通过调用Context的getSystemService() 方法来获取实例:

AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

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

long triggerAtTime = SystemClock.elapsedRealtime() + 10 * 1000;
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pendingIntent);

set() 方法接收三个参数:

  • 第一个参数是一个整型参数,用于指定AlarmManager 的工作类型:
  • ELAPSED_REALTIME:让定时任务的触发时间从系统开机开始算起,不会唤醒CPU
  • ELAPSED_REALTIME_WAKEUP:让定时任务的触发时间从系统开机开始算起,会唤醒CPU
  • RTC:让定时任务的触发时间从1970年1月1日0点开始算起,不会唤醒CPU
  • RTC_WAKEUP:让定时任务的触发时间从1970年1月1日0点开始算起,会唤醒CPU。
  • 使用SystemClock.elapsedRealtime() 方法可以获取到系统开机至今所经历时间的毫秒数,使用System.currentTimeMillis() 方法可以获取到1970年1月1日0点至今所经历时间的毫秒数
  • 第二个参数是定时任务触发的时间,以毫秒为单位。如果第一个参数使用的是ELAPSED_REALTIME或ELAPSED_REALTIME_WAKEUP,传入开机至今的时间再加上延迟执行的时间。如果第一个参数使用的是RTC或RTC_WAKEUP,则传入1970年1月1日0点至今的时间再加上延迟执行的时间。
  • 第三个参数是PendingIntent对象

从Android 4.4系统开始,系统在耗电性方面进行的优化,会自动检测目前有多少Alarm任务存在,然后将触发时间相近的几个任务放在一起执行,大幅度地减少CPU被唤醒的次数,从而有效延长电池的使用时间,Alarm任务的触发时间将会变得不准确,有可能会延迟一段时间后任务才能得到执行。若要求Alarm任务的执行时间必须准确无误,使用AlarmManager的setExact() 方法来替代set() 方法

Doze模式

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

系统并不会一直处于Doze模式,而是会间歇性地退出Doze模式一小段时间,在这段时间中,应用就可以去完成它们的同步操作、Alarm任务等等。

随着设备进入Doze模式的时间越长,间歇性地退出Doze模式的时间间隔也会越长
在Doze模式下,有这些功能会受到限制:

  • 网络访问被禁止
  • 系统忽略唤醒CPU或者屏幕操作
  • 系统不再执行WIFI扫描
  • 系统不再执行同步服务
  • Alarm任务将会在下次退出Doze模式的时候执行(调用AlarmManager的setAndAllowWhileIdle()setExactAndAllowWhileIdle() 方法就能让定时任务即使在Doze模式下也能正常执行)

多窗口模式编程

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

进入多窗口模式

有两种方式可以进入多窗口模式:

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

多窗口模式下的生命周期

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

禁用多窗口模式

当项目的targetSdkVersion指定成24或者更高时,要在AndroidManifest.xml的<application>或<activity>标签中加入如下属性:

android:resizeableActivity=["true" | "false"]

true 表示应用支持多窗口模式,false 表示应用不支持多窗口模式,如果不配置这个属性,那么默认值为true

当项目指定的targetSdkVersion低于24,并且活动是不允许横竖屏切换的,那么该应用也将不支持多窗口模式,想要让应用不允许横竖屏切换,那么就需要在AndroidManifest.xml的<activity>标签中加入如下配置:

android:screenOrientation=["portrait" | "landscape"]

portrait表示活动只支持竖屏,landscape表示活动只支持横屏

使用Java8新特性

想要在在Android项目中使用Java新特性,需要在app/build.gradle中添加如下配置:

android 
	...
	defaultConfig 
		...
		jackOptions.enabled = true
	
	compileOptions 
		sourceCompatibility JavaVersion.VERSION_1_8
		targetCompatibility JavaVersion.VERSION_1_8
	
	...

以上是关于那些Android开发者必备的技能的主要内容,如果未能解决你的问题,请参考以下文章

Android高工必备技能

成为一个优秀的Android开发者,需要必备哪些技术&工作技能?

Android Framework已然成为高薪Android开发者必备技能

后端技能树修炼:基于队列的流量削峰模式

百度,腾讯,字节,阿里等一线大厂 Android 性能优化实战解析,Android 进阶必备技能!

JetPack现在都成了Android开发必备技能了嘛?