《第一行代码Android》学习总结第十三章 Android编程技巧

一、全局获取Context技巧

        在项目任何地方都轻松获取Context。

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

1、创建一个MyApplication类继承自Application

public class MyApplication extends Application {
    private static Context context;
    @Override
public void onCreate() {
// getApplicationContext()方法得到应用级别的Context
        context = getApplicationContext();
    }

    public static Context getContext(){
        return context;
    }
}

2、在AndroidManifest中的标签下添加android:name属性,告知系统当程序启动时应该初始化MyApplication类。


    ……
    
        ……
    

3、如果想在项目任何地方使用Context,只需调用MyApplication. getContext()即可。

 

二、使用Intent传递对象。

(一)Serializable

        Serializable是序列化的意思,表示将一个对象转换成可储存或可传输的状态。序列化后的对象可以在网络上进行传输,也可以储存到本地,序列化方法只需让该类实现Serializable接口即可。

1、创建Person类,添加name与age字段,并实现Serializable接口。

public class Person implements Serializable {
    private String name;
    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

2、使用时,创建Person实例,然后直接将其传入到putExtra()方法中。

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

3、在SecondActivity中添加。

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

(二)Parcelable

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

1、创建People类,添加name与age字段,并实现Parcelable接口。

public class People implements Parcelable {
    private String name;
    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
//重写describeContents()方法,返回0即可
    @Override
    public int describeContents() {
        return 0;
    }
//重写writeToParcel()方法调用Parcel的writeXxx()方法将People类中的字段一一写出。
    @Override
    public void writeToParcel(Parcel parcel, int i) {
          parcel.writeString(name);
          parcel.writeInt(age);
    }
//创建一个名为CREATOR的常量,并创建一个Parcelable.Creator接口的实现,泛型类型指定为People。
    public static final Parcelable.Creator CREATOR = new Parcelable.Creator(){
//重写createFromParcel()方法调用Parcel的readXxx()方法读取字段,其中读取顺序一定要和写出顺序完全一致。
        @Override
        public People createFromParcel(Parcel parcel) {
           People people = new People();
            people.name = parcel.readString();
            people.age = parcel.readInt();
            return people;
        }
//重写newArray()方法返回size大小数组
        @Override
        public People[] newArray(int size) {
            return new People[size];
        }
    };
}

2、使用时,创建People实例,然后直接将其传入到putExtra()方法中。

        People people = new People();
        people.setName("Jack");
        people.setAge(22);
        Intent intent = new Intent(FirstActivity.this, SecondActivity.this);
        intent.putExtra("people_data", people);
        startActivity(intent);

3、在SecondActivity中添加。

People people = (People) getIntent().getParcelableExtra("people_data");

 

三、定制自己的日志工具

传统日志无法自由控制日志的打印,如当程序处于开发阶段就让日志打印出来,当程序上线则把日志全部屏蔽。

1、定制自己的日志工具,新建LogUtil类。

public class LogUtil {
//定义6个整型常量
    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;
//静态变量level设置打印级别,只有当level的值小于或等于对应日志级别时,才会将日志打印
    public static int level = VERBOSE;

//提供5个日志打印方法
    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);
        }
    }

}

2、使用该日志工具,打印DEBUG级别或WARN级别。

LogUtil.d(“TAG”, “debug log”);
LogUtil.w(“TAG”, “warn log”);

        此时在开发阶段将level指定为VERBOSE,项目上线时将level指定为NOTHING即可。

 

四、创建定时任务

(一)Alarm机制

        Alarm具有唤醒CPU的功能,它可以保证大多数情况下需要执行定时任务时CPU都能正常工作。

用法:

1)getSystemService()方法传入Context.ALARM_SERVICE参数,获取AlarmManager实例。

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

2)调用AlarmManager的set()方法设置一个定时任务。

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

         其中set()方法的第一个参数用于指定AlarmManager的工作类型,第二个参数为定时任务触发的时间,以毫秒为单位。第三个参数为PendingIntent,一般调用getService()或getBroadcast()获取一个服务或广播的PendingIntent。

1、新建一个LongRunningService服务,将触发定时任务的代码写到onStartCommand()中。

public class LongRunningService extends Service {
    @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() {
            }
        }).start();
        AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        int anHour = 60 * 60 * 1000;
        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);
    }
}	

2、启动定时服务时调用如下代码。

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

(二)Doze模式

        Doze模式可以及大幅度地延长电池使用寿命,当用户设备是Android6.0以上时,如果该设备未插接电源,处于静止状态,并且屏幕关闭了一段时间后,就会进入Doze模式,在Doze模式下,系统会对CPU、网络、Alarm等活动进行限制,从而延长电池寿命。系统不会一直处于Doze模式,而是间歇性地退出Doze模式一小段时间。随着设备进入Doze模式的时间越长,间歇性退出Doze模式的时间间隔也会越长。

Doze模式下:

    1)网络访问被禁止。

    2)系统忽略唤醒CPU或屏幕操作

    3)系统不再执行WIFI扫描

    4)系统不再执行同步任务

    5)Alarm任务将会在下次退出Doze模式时执行

 

五、多窗口模式

        多窗口模式允许在同一个屏幕同时打开两个应用程序。

进入多窗口模式:

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

2)打开任意程序,长按Overview,即可进入多窗口模式。

退出多窗口模式:

1)再次长按Overview。

2)将屏幕中央的分割线向屏幕任意一个方向拖动到底。

(一)多窗口模式下的生命周期

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

        进入多窗口模式后活动的大小发生了比较大的变化,此时默认会重新创建活动。

当在AndroidManifest中对活动进行配置:


           ……
        

        此时不管进入多窗口模式,还是横竖屏切换,活动都不会重新创建,而是将屏幕变化的事件通知到Activity的onConfigurationChanged()方法中。

(二)禁用多窗口模式

        在AndroidManifest的标签中加入如下配置:

android:resizeableActivity=[“true” | “false”]

        其中true代表应用支持多窗口模式,false代表应用不支持多窗口模式。

(二)禁用横竖屏切换

        在AndroidManifest的或标签中加入如下配置:

android:screenOrientation=[“portrait” | “landscape”]

        其中portrait代表应用只支持竖屏,landscape代表应用只支持横屏。

你可能感兴趣的:(Android,第一行代码)