欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

不需要再手写 onSaveInstanceState 了,因为你的时间非常值钱

程序员文章站 2022-06-11 18:35:23
如果你是一个有经验的 Android 程序员,那么你肯定手写过许多 以及 方法用来保持 Activity 的状态,因为 Activity 在变为不可见以后,系统随时可能把它回收用来释放内存。 重写 Activity 中的 方法 是 Google 推荐的用来保持 Activity 状态的做法。

如果你是一个有经验的 android 程序员,那么你肯定手写过许多 onsaveinstancestate 以及 onrestoreinstancestate 方法用来保持 activity 的状态,因为 activity 在变为不可见以后,系统随时可能把它回收用来释放内存。重写 activity 中的 onsaveinstancestate 方法 是 google 推荐的用来保持 activity 状态的做法。

google 推荐的最佳实践

onsaveinstancestate 方法会提供给我们一个 bundle 对象用来保存我们想保存的值,但是 bundle 存储是基于 key - value 这样一个形式,所以我们需要定义一些额外的 string 类型的 key 常量,最后我们的项目中会充斥着这样代码:

static final string state_score = "playerscore";
static final string state_level = "playerlevel";
// ...


@override
public void onsaveinstancestate(bundle savedinstancestate) {
    // save the user's current game state
    savedinstancestate.putint(state_score, mcurrentscore);
    savedinstancestate.putint(state_level, mcurrentlevel);

    // always call the superclass so it can save the view hierarchy state
    super.onsaveinstancestate(savedinstancestate);
}

保存完状态之后,为了能在系统重新实例化这个 activity 的时候恢复先前被系统杀死前的状态,我们在 oncreate 方法里把原来保存的值重新取出来:

@override
protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate); // always call the superclass first

    // check whether we're recreating a previously destroyed instance
    if (savedinstancestate != null) {
        // restore value of members from saved state
        mcurrentscore = savedinstancestate.getint(state_score);
        mcurrentlevel = savedinstancestate.getint(state_level);
    } else {
        // probably initialize members with default values for a new instance
    }
    // ...
}

当然,恢复这个操作也可以在 onrestoreinstancestate 这个方法实现:

public void onrestoreinstancestate(bundle savedinstancestate) {
    // always call the superclass so it can restore the view hierarchy
    super.onrestoreinstancestate(savedinstancestate);

    // restore state members from saved instance
    mcurrentscore = savedinstancestate.getint(state_score);
    mcurrentlevel = savedinstancestate.getint(state_level);
}

解放你的双手

上面的方案当然是正确的。但是并不优雅,为了保持变量的值,引入了两个方法 ( onsaveinstancestateonrestoreinstancestate ) 和两个常量 ( 为了存储两个变量而定义的两个常量,仅仅为了放到 bundle 里面)。

为了更好地解决这个问题,我写了 savestate 这个插件:

不需要再手写 onSaveInstanceState 了,因为你的时间非常值钱

在使用了 savestate 这个插件以后,保持 activity 的状态的写法如下:

public class myactivity extends activity {

    @autorestore
    int myint;

    @autorestore
    ibinder myrpccall;

    @autorestore
    string result;

    @override
    protected void oncreate(bundle savedinstancestate) {
        // your code here
    }
}

没错,你只需要在需要保持的变量上标记 @autorestore 注解即可,无需去管那几个烦人的 activity 回调,也不需要定义多余的 string 类型 key 常量。

那么,除了 activity 以外,fragment 能自动保持状态吗?答案是: yes!

public class myfragment extends fragment {

    @autorestore
    user currentloginuser;

    @autorestore
    list<map<string, object>> networkresponse;

    @nullable
    @override
    public view oncreateview(@nonnull layoutinflater inflater, @nullable viewgroup container, @nullable bundle savedinstancestate) {
        // your code here
    }
}

使用方法和 activity 一模一样!不止如此,使用场景还可以推广到 view, 从此,你的自定义 view,也可以把状态保持这个任务交给 savestate

public class myview extends view {

    @autorestore
    string sometext;

    @autorestore
    size size;

    @autorestore
    float[] myfloatarray;

    public mainview(context context) {
        super(context);
    }

    public mainview(context context, @nullable attributeset attrs) {
        super(context, attrs);
    }

    public mainview(context context, @nullable attributeset attrs, int defstyleattr) {
        super(context, attrs, defstyleattr);
    }

}

现在就使用 savestate

引入 savestate 的方法也十分简单:

首先,在项目根目录的 build.gradle 文件中增加以下内容:

buildscript {

    repositories {
        google()
        jcenter()
    }
    dependencies {
        // your other dependencies

        // dependency for save-state
        classpath "io.github.prototypez:save-state:${latest_version}"
    }
}

然后,在 applicationlibrary 模块的 build.gradle 文件中应用插件:

apply plugin: 'com.android.application'
// apply plugin: 'com.android.library'
apply plugin: 'save.state'

万事具备!再也不需要写烦人的回调,因为你的时间非常值钱!做了一点微小的工作,如果我帮你节省下来了喝一杯咖啡的时间,希望你可以帮我点一个 star,谢谢 :)

savestate github 地址:https://github.com/prototypez/savestate