Advanced Trick
全局获取Context的技巧
目前,我们还没有为得不到Context而发愁过,因为我们许多的操作是在activity中进行的,而activity本身就是一个Context对象。但是,当应用程序的架构逐渐开始复杂起来的时候,很多逻辑代码将脱离Activity类,但此时你又恰恰需要使用Context,也许这个时候你就很难受了。
解决方法:
- 传递一个Context进来。
- 利用android提供的Application类。
android提供的application类,每当应用程序启动的时候,系统就会自动将这个类进行初始化。而我们可以制定一个自己的application类,以便于管理程序内一些全局的状态信息,比如全局Context。
比如创建一个Toast工具类(这个是为了模仿kotlin中的扩展函数的(infix function)的:
public class ToastUtil {
public static void showToast(@NotNull String receiver){
Toast.makeText(MyApplicatoin.context,receiver,Toast.LENGTH_SHORT);
}
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ToastUtil.showToast("abc");
}
}
使用Intent传递对象
我们可以借助Intent来启动activity、启动service、发送广播等。在进行上述操作的时候,我们还可以在intent中添加一些附加数据,已达到传值的效果,但是明显传值的数据类型非常有限,但是当你想要传递一些自定义对象的时候,就会发现无从下手。下面学习一下使用intent传递对象的技巧。
使用Intent来传递对象通常有两种实现方式:
- serializable:序列化,表示将一个对象转化成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储在本地。
- parcelable:将一个完整的对象进行分解,而分解后的每一部分都是Intent支持的数据类型,从而实现传递对象的功能。
serializable方式
实现方式:
- 对象所在的类实现Serializable这个接口。
- 调用intent的getSerializableExtra()方法来获取通过参数传递过来的序列号对象,接着再将他向下转型成相应对象。【序列号=>反序列化】
parcelable方式
实现方式,对象所在的类实现Parcelable接口:
- 重写
describeContents()
和writeToParcel()
两个方法 - 实现CREATOR匿名类:重写
createFromParcel()
和newArray()
两个方法。
具体代码如下:
import android.os.Parcel;
import android.os.Parcelable;
public class Person implements Parcelable {
public String name = "";
public int age = 0;
/**
* 反序列化需要的构造函数
* @param in
*/
public Person(Parcel in) {
this.age = in.readInt();
this.name = in.readString();
}
public static final Creator<Person> CREATOR = new Creator<Person>() {
@Override
public Person createFromParcel(Parcel in) {
return new Person(in);
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};
/**
* @return 内容接口描述,默认返回0就可以了
*/
@Override
public int describeContents() {
return 0;
}
/**
* 序列化的函数
* @param dest
* @param flags
*/
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name); // 写入nme
dest.writeInt(age); // 写入age
}
}
定制自己的日志工具
新建一个LogUtil单例类:
/**
* cite:https://blog.csdn.net/huantai3334/article/details/104504208
*
* java中工具类应该写成单例,还是全是静态方法的类?
* 说静态类好的:
* 1. 静态类不用引用就能调用,而单例需要有对象的引用,因此节约资源
* 2.静态类方便,随处可用;而单例必须有引用,需要注入或者Object.getInstance()
*
* 说单例好的:
* 1.单例模式的类是普通的类,它具有面向对象的特性,方便扩展
* 2.对于有配置的工具类,可以轻松的创建多个不同配置的单例对象(想起我主导的另一个项目就存在5-6个redis数据源,如果使用静态类就是灾难)
*
* 因此,我得出以下结论:
* 如果没有配置信息的工具类,当然是静态类好,随处调用,不需引用爽得不要不要的。
* 如果有配置信息的工具类,最好还是使用单例模式。
*
*/
public class LogUtil {
private static final int VERBOSE = 1;
private static final int DEBUG = 2;
private static final int INFO = 3;
private static final int WARN = 4;
private static final int ERROR = 5;
private 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);
}
}
}
深色主题
Android10.0系统中,google引入了深度主题这一特性,从而让夜间模式正式成为了官方支持的功能。具体支持步骤如下:
-
首先在自己的android手机中setting->Display->Dark theme中对深色追进行开启和关闭。
-
对自己编写的程序进行适配【略】
- 最简单的一种适配方式就是使用Force Dark,他是一种能让应用程序快速适配深色主题,并不需要编写额外代码的方式。
- 手动实现 =>AppCompat库内中的主题包含浅色主题和深色主题两类。