Android提供了一個Application類,每當應用程式啟動的時候,系統就會自動把這個類進行初始化。我們可客製化一個自己的Application類,用於獲取全域性Context
範例:
1.建立Application的子類物件,提供獲取content的方法
import android.app.Application;
import android.content.Context;
public class MyApplication extends Application {
private static Context context;
@Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
//提供getContext()方法
public static Context getContext(){
return context;
}
}
2.在AndroidManifest.xml檔案的application標籤下指定,告知系統啟動的是MyApplication,而不是預設的Application
<application
android:name=".MyApplication"
......
</application>
問題:為了讓LitePal正常工作,必須要設定
<application
android:name="org.litepal.LitePalApplication"
......
</application>
這樣設定之後,LitePal就可在內部自動獲取到Context了。但是這樣既無法設定MyApplication了,因為一個專案只能設定一個Application
解決辦法:在我們自己的Application中呼叫LitePal的初始化方法就行
public class MyApplication extends Application {
private static Context context;
@Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
LitePal.initialize(context);
}
//提供getContext()方法
public static Context getContext(){
return context;
}
}
平時我們在用Intent傳遞資料時都用的putExtra()方法,但是當我們要傳遞的資料是自定義物件時,無法傳遞。實現方法如下:
序列化的意思,表示吧一個物件轉換成可儲存或可傳輸的狀態,序列化後的物件可以在網路上傳輸,也可儲存到本地
是一個介面,用時直接實現介面就可
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;
}
}
傳送:
Person person = new Person();
person.setAge(12);
person.setName("dag");
Intent intent = new Intent(MainActivity.this,MainActivity2.class);
intent.putExtra("person_data",person);
startActivity(intent);
接收:(注意:與原來的接收不同)
Intent intent = getIntent();
Person person = (Person)intent.getSerializableExtra("person_data");
它的實現原理是將一個完整的物件進行分解,分解後的每一部分都是Intent所支援的資料型別
class people implements Parcelable{
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;
}
//直接返回0
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
//呼叫Parcel的writeXXX方法,吧類中的欄位一一寫出
dest.writeString(name);
dest.writeInt(age);
}
public static final Parcelable.Creator<people> CREATOR = new Parcelable.Creator<people>(){
@Override
public people createFromParcel(Parcel source) {
//讀取剛才寫出的name和age欄位,讀取順序一定要和寫入的完全相同
people people1 = new people();
people1.name = source.readString();
people1.age = source.readInt();
return people1;
}
@Override
public people[] newArray(int size) {
return new people[size];
}
};
}
傳送:
people people1 = new people();
people1.setAge(12);
people1.setName("134455");
Intent intent1 = new Intent(MainActivity.this,MainActivity2.class);
intent.putExtra("people_data",person);
startActivity(intent);
接收:(注意:與原來的接收不同)
Intent intent = getIntent();
people people1 = (people) intent.getParcelableExtra("people_data");
目的:自由的控制紀錄檔的列印
範例:
class LogUtil{
public static final int VERBOSE = 1;
public static final int DEBUG = 2;
public static final int INFO = 3;
public static final int ERROR = 5;
public static final int WARN = 4;
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機制
Timer並不太實用於那些需要長期在後臺執行的定時任務,當長時間時,CPU進入到睡眠狀態,可能導致Timer的定時任務無法正常執行
可以保證大多數情況下需要執行定時任務時CPU都能正常工作
如下是一個長時間在後臺定時執行的服務
public class LongRuningService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
/*
一旦啟動LongRuningService就會在onStartCommand中執行一個定時任務,
這樣一個小時後將在此啟動LongRuningService,形成迴圈
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
//執行具體的操作邏輯
}
}).start();
//獲取AlarmManager物件
AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
int anHour = 60*60*1000;
Long l = System.currentTimeMillis();
//SystemClock.elapsedRealtime()獲取開機至今的毫秒數
//System.currentTimeMillis() 獲取1970年 一月一日0點至今所經歷的毫秒數
Long triggerAtTime = SystemClock.elapsedRealtime()+anHour;
Intent intent1 = new Intent(this,LongRuningService.class);
PendingIntent pendingIntent = PendingIntent.getService(this,0,intent1,0);
//設定定時任務
manager.set(AlarmManager.RTC_WAKEUP,triggerAtTime,pendingIntent);
/*三個引數:
第一個是整型引數用於指定AlarmManager的工作型別
第二個:觸發時間
第三個是 PendingIntent
*/
return super.onStartCommand(intent,flags,startId);
}
}
AlarmManager的工作型別 | 說明 |
---|---|
ELAPSED_REALTIME | 讓定時任務從系統開機開始算起,但不會喚醒CPU |
ELAPSED_REALTIME_WAKEUP | 讓定時任務從系統開機開始算起,喚醒CPU |
RTC | 讓系統任務從1970年一月一日0點開始算起,但不會喚醒CPU |
RTC_WAKEUP | 讓系統任務從1970年一月一日0點開始算起,喚醒CPU |
注:對於不同的工作型別,要選擇不同的時間
如果你要求Alarm任務的執行時間必須準確無誤,應用setExact()方法替換set()方法
當使用者裝置是Android 6.0 或以上系統時,如果未插接電源,且螢幕關閉了一段時間之後就會進入到Doze模式
在該模式下,系統會對CPU,網路,Alarm等活動進行限制,從而延長電池的使用壽命
當然,它不會一直處於該模式,而是會間隙性的退出Doze模式一小段時間,在這段時間中去完成同步操作,Alarm任務
注:Doze模式下,Alarm任務就會變的不準時,解決方案
吧set()方法換成setExactAndAllowWhileIdle()或setAndAllowWhileIdle()方法就可讓定時任務在Doze模式下也可正常執行
即我們常見的分屏操作,在該模式下活動會有一個重新建立的過程,如果操作一個程式,另一個程式會進入暫停狀態(onPause)
如果你想改變進入多視窗模式活動被重新建立,可新增如下設定
<activity android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|screenSize|screenLayout">
.....
</activity>
<application
....
android:resizeableActivity="false">
.....
</application>
true表示支援,false表示不支援,預設是支援
android studio 中的設定
1.app的build檔案下設定好
jackOptions{
enabled true
}
compileOptions{
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
retrolambda {//指定將原始碼編譯的級別,使用下列程式碼,會將程式碼編譯到相容1.6的位元組碼格式
javaVersion JavaVersion.VERSION_1_6
}
2.專案build檔案下也要加上設定
apply plugin: 'me.tatarka.retrolambda'//lambda
dependencies {
classpath 'com.android.tools.build:gradle:3.1.3'
classpath 'me.tatarka:gradle-retrolambda:3.7.0' //lambda
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
剩下的使用和java使用方法一樣
Lambda表示式