Android19-高級技巧

1.全局獲取Context

Android提供了一個Application類,每當(dāng)應(yīng)用啟動的,系統(tǒng)就會自動將這個類進(jìn)行初始化,而我們可以定制一個自己的Application類,以便于管理程序內(nèi)一些全局的狀態(tài)信息,比如全局的Context。


1.自定義Application類

>public class MyApplication extends Application {
    private static Context context;
    @Override
    public void onCreate() {
        //重寫onCreate()方法,獲得context對象
        context = getApplicationContext();
    }
    public static Context getContext() {
        //外界調(diào)用,獲得context
        return context;
    }
}

2.在AndroidManifest.xml文件中指定加載MyApplication

 <application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"

3.外界調(diào)用的時候

Toast.makeText(MyApplication.getContext(), "點(diǎn)擊了頭像", Toast.LENGTH_SHORT).show();

2.使用Intent傳遞對象

Intent使用putExtra()方法傳遞數(shù)據(jù)時,所支持的類型是有限的,當(dāng)需要傳遞一些自定義對象時,就需要使用Serializable或者Parcelablc的方式來實(shí)現(xiàn)了。


一、Serializable方式

Serializable是序列化的意思,表示將一個對象轉(zhuǎn)換成可存儲或可傳輸?shù)臓顟B(tài),序列化后的對象可以在網(wǎng)絡(luò)上進(jìn)行傳輸,也可以存儲到本地,至于序列化的方法也很簡單,只需要讓一個類去實(shí)現(xiàn)Serializable這個接口就可以了。

1.1比如一個Person類,其中包含了name和age兩個字段,想要將它序列化就可以這樣寫:

//整個類中跟定義一個實(shí)體類大致相同,最最重要的是在第一行,讓Person類去實(shí)現(xiàn)Serializable接口。
public class Person implements Serializable {
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

1.2然后需要傳遞對象的activity中:

Intent intent = new Intent(mContext, FruitActivity.class);
 Person person = new Person();
 person.setAge(20);
 person.setName("Tom");
 intent.putExtra("person_data", person);    MyApplication.getContext().startActivity(intent);

1.3在需要獲取對象的acidity中:

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

二、Parcelabele方式

使用Parcelable同樣可以達(dá)到跟Serializable相同的效果,不同的是,Parcelabel方式的實(shí)現(xiàn)原理是將一個完整的對象進(jìn)行分解,而分解后的每一部分都是Intent所支持的數(shù)據(jù)類型。這樣也就實(shí)現(xiàn)傳遞對象的功能了。

2.1和Serializable一樣,需要使Person實(shí)現(xiàn)Parcelable接口。然后重寫describeContents()和writeToParcel()這兩個方法。其中describeContents()方法中直接返回0就可以了。而writeToParcel()需要調(diào)用writeXxx()方法,將Person類中的字段一一寫出。然后還要提供一個名為CREATOR的常量。

public class Person implements Parcelable {
    private String name;
    private int age;
    public int getAge() {
        return age;
    }
    public String getName() {
        return name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void setName(String name) {
        this.name = name;
    }
    //重寫describeContents()方法
    @Override
    public int describeContents() {
        return 0;
    }
    //重寫writeToParcel()方法
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);//寫出name
        dest.writeInt(age);//寫出age
    }
    //定義CREATOR常量
    public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {
        @Override
        public Person createFromParcel(Parcel source) {
            Person person = new Person();
            person.setName(source.readString());//讀取name
            person.setAge(source.readInt());//讀取age
            return person;
        }
        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };
}

2.2在需要傳遞對象的activity中,這跟Serializable是一樣

Intent intent = new Intent(mContext, FruitActivity.class);
 Person person = new Person();
 person.setAge(20);
 person.setName("Tom");
 intent.putExtra("person_data", person);    MyApplication.getContext().startActivity(intent);

2.3在需要獲取對象的activity中

Person person = (Person) getIntent().getParcelableExtra("person_data");

3.定制自己的日志工具

定制日志工具,可以讓程序處于開發(fā)階段的時候就打印日志,處于上線階段的時候就不打印日志,便于后期維護(hù),也防止了私密信息的泄漏。


1.1如下,創(chuàng)建LogUtil類

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);
        }
    }
}

1.2外界調(diào)用的時候直接通過LogUtil打印信息即可。并且當(dāng)我們設(shè)置LogUtil中的level等于VERBOSE就可以把所有日志都打印出來,等于WARN就可以只打印WARN以上級的日志,在發(fā)布之后,將level設(shè)置成NOTHING就可以把所有日志都屏蔽掉了。

LogUtil.d("TAG", "Debug log");

4. 創(chuàng)建定時任務(wù)

Android中的定時任務(wù)一般有兩種實(shí)現(xiàn)方式,一種是使用JavaAPI提供的Timer類,一種是Android的Alarm機(jī)制。兩種方式都能實(shí)現(xiàn)相同的效果,但是Timer有可能在手機(jī)休眠的狀態(tài)下無法正常運(yùn)行,而Alarm則具有喚醒CPU的功能,因此在手機(jī)休眠的狀態(tài)下也能保證定時任務(wù)的正常執(zhí)行。


一、Alarm機(jī)制

Alarm機(jī)制的用法,主要是借助AlarmManager類來實(shí)現(xiàn),這個類和NotificationManager有點(diǎn)類似,都是通過調(diào)用Context的getSystemService()方法傳入?yún)?shù)Context.ALARM_SERVICE來獲取實(shí)例。

1.1獲取AlarmManager實(shí)例

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

1.2調(diào)用AlarmManager的set()方法就可以設(shè)置一個定時任務(wù)了。比如設(shè)定一個任務(wù)在10秒后執(zhí)行

set()方法接收3個參數(shù):
第一個:一個整型參數(shù),用于指定AlarmManager的工作類型,有4種值可選:>>1. RTC_WAKEUP : 表示讓定時任務(wù)的觸發(fā)時間從1970年1月1日0時開始算起,但會喚醒CPU

  1. RTC : 表示讓定時任務(wù)的觸發(fā)時間從1970年1月1日0時開始算起,但不會喚醒CPU
  2. ELAPSED_REALTIME_WAKEUP : 表示讓定時任務(wù)的觸發(fā)時間從系統(tǒng)開機(jī)算起,但會喚醒CPU。
  3. ELAPSED_REALTIME : 表示讓定時任務(wù)的處罰時間從系統(tǒng)開機(jī)算起,但不會喚醒CPU>
    第二個參數(shù):定時任務(wù)出發(fā)的時間,加上第一個參數(shù)設(shè)定值。
    第三個參數(shù):PendingIntent對象。這里一般會調(diào)用getService()方法或者getBroadcast()方法來獲取一個能夠執(zhí)行服務(wù)或廣播接收器的onReceive()方法就可以得到執(zhí)行。
AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
long triggerArTime = SystemClock.elapsedRealtime() + 10*1000;
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerArTime, pendingIntent);

1.3 如果需要實(shí)現(xiàn)一個長時間在后臺定時運(yùn)行的服務(wù),如下代碼,每個一小時就會啟用一次服務(wù)。

public class LongRunningService extends Service {
    public LongRunningService() {
    }
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                //這里執(zhí)行具體的操作邏輯
            }
        });
        AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
        int anHour = 60 * 60 * 1000; //一小時的毫秒數(shù)
        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);
    }
}

1.4 最后只需要在需要啟動服務(wù)的時候調(diào)用

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

注:從Android4.4開始,因?yàn)橄到y(tǒng)在好點(diǎn)性方面的調(diào)整,Alarm使用set()觸發(fā)任務(wù)的時間會變得不準(zhǔn)確,如果需要讓執(zhí)行時間變得準(zhǔn)確無誤,需使用setExact()方法來代替set()方法。

5.多窗口模式的一些設(shè)置

1.當(dāng)應(yīng)用進(jìn)入多窗口模式的時候,活動默認(rèn)會被重新創(chuàng)建,修改這一行為,可以在AndroidManifest.xml中對活動進(jìn)行如下設(shè)置

<activity
  android:name=".FruitActivity"
  android:theme="@style/FruitActivityTheme"
  android:configChanges="orientation|keyboardHidden|screenSize|screenLayout">
</activity>

2.禁用多窗口模式
設(shè)置程序禁用多窗口模式,只需在application中把a(bǔ)ndroid:resizeableActivity設(shè)置為false即可。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.anwser_mac.materialtest">
    <application
        android:resizeableActivity="false"

注:android:resizeableActivity,是在targetSdkVersion大于24才有用的,如果對于一些沒有指定到24的項(xiàng)目,想要禁用多窗口模式,需要設(shè)置活動不允許橫豎屏切換,因?yàn)锳ndroid規(guī)定targetSdkVersion小于24并且活動不允許橫豎屏切換的應(yīng)用也不將不支持多窗口模式。

<activity
  android:screenOrientation="portrait"http://landscape只支持橫屏,portrait為只支持豎屏。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容