Android基础知识——你还应该掌握的高级技巧

文章目录

  • 1.全局获得Context的技巧
  • 2.使用Intent传递对象
    • 2.1Serializable方式
    • 2.2Parcelable方式
  • 3.定制自己的日志工具
  • 4.创建定时任务
    • 4.1Alarm机制
    • 4.2Doze模式
  • 5.多窗口模式编程
    • 5.1多窗口模式下的生命周期
    • 5.2禁用多窗口模式

1.全局获得Context的技巧

在我们学习Android基础知识的时候,你会发现在很多地方我们都会使用到Context,弹出Toast的时候需要,启动活动的时候需要,发送广播的时候需要,操作数据库的时候需要,使用通知的时候需要,等等等等。所以有时候在需要使用Context时,却不知道该怎么获得Context将会是一件非常伤脑筋的事情。本节我们就来介绍一个全局获得Context的技巧。

使用步骤:

1.新建类继承Application类,在其中获取Context并定义一个用于外部获取Context的方法。
2.给AndroidManifest.xml设置android:name属性。也就是告知系统,当程序启动时应该初始化MyApplication类,而不是默认的Application类。

示例:

1//步骤一 2public class MyApplication extends Application { 3 4 5 private static Context context; 6 7 @Override 8 public void onCreate() { 9 10 11 super.onCreate(); 12 context=getApplicationContext(); 13 } 14 15 public static Context getContext(){ 16 17 18 return context; 19 } 20} 21//步骤二 22<manifest xmlns:android="http://schemas.android.com/apk/res/android" 23 xmlns:tools="http://schemas.android.com/tools" 24 package="com.example.temp"> 25 26 <application 27 android:name=".MyApplication"//告知系统当程序启动时初始化MyApplication类 28 android:allowBackup="true" 29 android:icon="@mipmap/ic_launcher" 30 android:label="@string/app_name" 31 android:roundIcon="@mipmap/ic_launcher_round" 32 android:supportsRtl="true" 33 android:theme="@style/AppTheme"> 34 35 <activity android:name=".MainActivity"> 36 <intent-filter> 37 <action android:name="android.intent.action.MAIN" /> 38 39 <category android:name="android.intent.category.LAUNCHER" /> 40 </intent-filter> 41 </activity> 42 </application> 43 44</manifest>

这里还有个小问题:在我们学习LitePal时我们也需要设置AndroidManifest.xml中的android:name属性,那当你两者都想要使用时该怎样处理呢?其实解决方法也很简单,我们只需在我们自己的Application中调用LitePal的初始化方法即可。

示例:

1public class MyApplication extends Application { 2 3 4 private static Context context; 5 6 @Override 7 public void onCreate() { 8 9 10 super.onCreate(); 11 context=getApplicationContext(); 12 LitePal.initialize(context); 13 } 14 15 public static Context getContext(){ 16 17 18 return context; 19 } 20}

2.使用Intent传递对象

Intent传递基础类型的数据相信你已经比较熟悉了,可是如果我们想要用Intent传递一个对象的话那该怎样处理呢?本节我们就来学习一下使用Intent传递对象。

2.1Serializable方式

使用步骤:

1.定义一个你想要传递的类,并让该类继承Serializable接口。
2.调用putExtra()方法向Intent中存储对象,调用getSerializableExtra()方法从Intent中获取对象。

Serializable详解:Serializable是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。

示例:

1//步骤一 2public class Student implements Serializable { 3 4 5 String name; 6 int age; 7 8 public Student(String name,int age){ 9 10 11 this.name=name; 12 this.age=age; 13 } 14} 15//步骤二 16public class MainActivity extends AppCompatActivity { 17 18 19 20 @Override 21 protected void onCreate(final Bundle savedInstanceState) { 22 23 24 super.onCreate(savedInstanceState); 25 setContentView(R.layout.activity_main); 26 Button button=(Button) findViewById(R.id.button); 27 button.setOnClickListener(new View.OnClickListener() { 28 29 30 @Override 31 public void onClick(View view) { 32 33 34 Intent intent=new Intent(MainActivity.this,MainActivity2.class); 35 Student student=new Student("Tom",18); 36 intent.putExtra("Student",student);//向Intent中存储对象 37 startActivity(intent); 38 } 39 }); 40 } 41} 42 43public class MainActivity2 extends AppCompatActivity { 44 45 46 47 @Override 48 protected void onCreate(Bundle savedInstanceState) { 49 50 51 super.onCreate(savedInstanceState); 52 setContentView(R.layout.activity_main2); 53 Intent intent=getIntent(); 54 Student student= (Student) intent.getSerializableExtra("Student");//从Intent中获取对象 55 Toast.makeText(MainActivity2.this,student.name,Toast.LENGTH_SHORT).show(); 56 } 57}

2.2Parcelable方式

使用步骤:

1.定义一个你想要传递的类,让其继承Parcelable接口并实现接口中的一些方法。
2.调用putExtra()方法向Intent中存储对象,调用getParcelableExtra()方法从Intent中获取对象。

Parcelable详解:Parcelable方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是Intent所支持的数据类型,这样也就实现传递对象的功能了。

示例:

1//步骤一 2public class Student implements Parcelable { 3 4 5 String name; 6 int age; 7 8 public Student(){ 9 10 11 } 12 13 public Student(String name,int age){ 14 15 16 this.name=name; 17 this.age=age; 18 } 19 20 public static final Creator<Student> CREATOR = new Creator<Student>() { 21 22 23 @Override 24 public Student createFromParcel(Parcel in) { 25 26 27 Student student=new Student(); 28 student.name=in.readString();//读取name(注意这里的读取顺序要和写入顺序完全相同) 29 student.age=in.readInt();//读取int 30 return student; 31 } 32 33 @Override 34 public Student[] newArray(int size) { 35 36 37 return new Student[size]; 38 } 39 }; 40 41 @Override 42 public int describeContents() { 43 44 45 return 0; 46 } 47 48 @Override 49 public void writeToParcel(Parcel parcel, int i) { 50 51 52 parcel.writeString(name);//写出name 53 parcel.writeInt(age);//写出age 54 } 55} 56//步骤二 57public class MainActivity extends AppCompatActivity { 58 59 60 61 @Override 62 protected void onCreate(final Bundle savedInstanceState) { 63 64 65 super.onCreate(savedInstanceState); 66 setContentView(R.layout.activity_main); 67 Button button=(Button) findViewById(R.id.button); 68 button.setOnClickListener(new View.OnClickListener() { 69 70 71 @Override 72 public void onClick(View view) { 73 74 75 Intent intent=new Intent(MainActivity.this,MainActivity2.class); 76 Student student=new Student("Tom",18); 77 intent.putExtra("Student",student);//向Intent中存储对象 78 startActivity(intent); 79 } 80 }); 81 } 82} 83 84public class MainActivity2 extends AppCompatActivity { 85 86 87 88 @Override 89 protected void onCreate(Bundle savedInstanceState) { 90 91 92 super.onCreate(savedInstanceState); 93 setContentView(R.layout.activity_main2); 94 Intent intent=getIntent(); 95 Student student= (Student) intent.getParcelableExtra("Student");//从Intent中获取对象 96 Toast.makeText(MainActivity2.this,student.name,Toast.LENGTH_SHORT).show(); 97 } 98}

3.定制自己的日志工具

现在让我们设想一个场景,你正在编写一个比较庞大的项目,期间为了方便调试,在代码的很多地方都打印了大量的日志。最近项目已经基本完成了,但是却有一个非常令人头痛的问题,之前用于调试的那些日志,在项目正式上线之后仍然会照常打印,这样不仅会降低程序的运行效率,还有可能将一些机密性的数据泄露出去。那可能会有人说我把打印日志的代码一行一行全部删掉就行了,这显然不是什么好点子,不仅费事费力,而且以后你继续维护这个项目时可能还会需要这些日志。本节我们就来学习该如何优雅的解决这个问题。

解决方法:

事实上这个问题的解决方法非常简单,我们只需要定义一个自己的日志工具,并在里面对打印日志条件加上限制条件即可。

示例:

1public class LogUtil { 2 3 4 5 private static final int VERBOSE=1; 6 private static final int DEBUG=2; 7 private static final int INFO=3; 8 private static final int WARN=4; 9 private static final int ERROR=5; 10 private static final int NOTHING=6; 11 private static int level=VERBOSE;//我们只需要更改level的值即可对不同等级的打印语句进行限制,而当我们不想打印任何日志时,我们只需将level的值设置为NOTHING即可。 12 13 public static void v(String tag,String msg){ 14 15 16 if(level<=VERBOSE){ 17 18 19 Log.v(tag,msg); 20 } 21 } 22 23 public static void d(String tag,String msg){ 24 25 26 if(level<=DEBUG){ 27 28 29 Log.d(tag,msg); 30 } 31 } 32 33 public static void i(String tag,String msg){ 34 35 36 if(level<=INFO){ 37 38 39 Log.i(tag,msg); 40 } 41 } 42 43 public static void w(String tag,String msg){ 44 45 46 if(level<=WARN){ 47 48 49 Log.w(tag,msg); 50 } 51 } 52 53 public static void e(String tag,String msg){ 54 55 56 if(level<=ERROR){ 57 58 59 Log.e(tag,msg); 60 } 61 } 62}

4.创建定时任务

Android中的定时任务一般有两种实现方式,一种是java API里提供的Timer类,一种是使用Android的Alarm机制。而两者的区别在于:Android手机会在长时间不操作的情况下自动让CPU进入到睡眠状态,这就有可能导致Timer中的定时任务无法正常运行,而Alarm则具有唤醒CPU的功能。(这里要注意唤醒CPU和唤醒屏幕完全是两个概念)

4.1Alarm机制

使用步骤:

1.获取AlarmManager实例。
2.调用manager.set()方法创建定时任务。

示例:

1public class MainActivity extends AppCompatActivity { 2 3 4 5 @Override 6 protected void onCreate(final Bundle savedInstanceState) { 7 8 9 super.onCreate(savedInstanceState); 10 setContentView(R.layout.activity_main); 11 Button button=(Button) findViewById(R.id.button); 12 button.setOnClickListener(new View.OnClickListener() { 13 14 15 @Override 16 public void onClick(View view) { 17 18 19 Intent intent=new Intent(MainActivity.this,MainActivity2.class); 20 PendingIntent pendingIntent=PendingIntent.getActivity(MainActivity.this,0,intent,0); 21 AlarmManager alarmManager= (AlarmManager) getSystemService(ALARM_SERVICE);//步骤一 22 long time= SystemClock.elapsedRealtime()+1000; 23 alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,time,pendingIntent);//步骤二 24 } 25 }); 26 } 27}

manager.set()方法详解:第一个参数同于设置工作类型,ELAPSED_REALTIME型:表示定时任务的触发时间从系统开机开始算起,但不会唤醒CPU;ELAPSED_REALTIME_WAKEUP类型:表示定时任务的触发时间从系统开机开始算起,且会唤醒CPU;RTC类型:表示定时任务的触发时间从1970年1月1日0点开始算起,但不会唤醒CPU;RTC_WAKEUP类型:表示定时任务的触发时间从1970年1月1日0点开始算起,且会唤醒CPU。第二个参数就是定时任务的触发时间,以毫秒为单位(注意要与第一个参数相匹配)。第三个参数就是定时调度任务要执行的具体事件了。

注意:从Android4.4系统开始,Alarm任务的触发事件会变得不准确,有可能会延迟一段时间后才会执行,当然这可不是Bug,这只是为了能让手机更好的节省电量。但倘若你要求Alarm任务的执行时间必须准确无误,那么你只需将set()方法更改为setExact()方法即可。

4.2Doze模式

Doze模式是Android6.0系统新加入的一种省电模式。该模式下系统会对CPU,网络,Alarm等活动进行限制,从而延长电池的使用寿命。因此这种模式也就极大的影响了我们Alarm任务的执行时间。不过倘若你真的有非常特殊的需求,要求在Doze模式下Alarm任务也要必须正常执行,Android还是提供了解决方案的。我们只需调用AlarmManger的setAndAllowWhileIdle()或setExactAndAllowWhileIdle()方法即可让你的Alarm任务在Doze模式下也能正常执行了。

5.多窗口模式编程

多窗口模式也就是我们现在经常说的分屏模式了。

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

当一个活动进入多窗口模式或横竖屏切换时,该活动会重新创建。多窗口模式下正在与用户交互的活动处于onResume状态,另一个则处于onPause状态。

另外,针对于进入多窗口模式时活动就会被重现创建,如果你想改变这一默认行为,只需在AndoridManifest.xml文件中进行如下配置即可:

1<activity android:name=".MainActivity" 2 android:configChanges="orientation|keyboardHidden|screenSize|screenLayout">

加入了这行配置之后,不管是进入多窗口模式,还是横竖屏切换,活动都不会被重新创建,而是会将屏幕发生改变的事件通知到Activity的onConfigurationChanged()方法当中。

5.2禁用多窗口模式

禁用多窗口模式的方法非常简单,只需在AndroidManifest.xml的< application >或< activity >标签下加入如下属性即可:

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

其中,true表示应用支持多窗口模式,false表示应用不支持多窗口模式,该属性默认为true。

不过上面的方法只能在targetSdkVersion为24以上时才会有用,否则这个属性是无效的。不过Android规定,当targetSdkVersion为24以下,并且活动不允许横竖屏切换,那么该应用也将不支持多窗口模式。配置方法如下:

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

其中,portrait表示活动只支持竖屏,landscap表示活动只支持横屏。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

Android基础知识——你还应该掌握的高级技巧 - HelloWorld