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

粮草先行——Android折叠屏开发技术点番外篇之运行时变更处理原则

程序员文章站 2022-04-09 18:42:21
上一篇文章中,我们有提到Activity在屏幕尺寸发生变更时的处理方式,总共有两种: 1. 重启APP以适应屏幕改变; 2. 手动处理数据,避免APP重启。 同样,这两种方式也同时适用于改变屏幕方向、更改系统语言、甚至输入法等等。 因此,本文也同样 适用于改变屏幕方向等情况的处理。 或许你会有疑问: ......

上一篇文章中,我们有提到activity在屏幕尺寸发生变更时的处理方式,总共有两种:

  1. 重启app以适应屏幕改变;
  2. 手动处理数据,避免app重启。

同样,这两种方式也同时适用于改变屏幕方向、更改系统语言、甚至输入法等等。
因此,本文也同样适用于改变屏幕方向等情况的处理。
或许你会有疑问:我们该如何选择合适的处理方式呢?
我给你的答案是:选择最合适的。
这么说好像跟没说一样,别急,给大家举个例子就明白了:
比如更改屏幕方向,由竖屏转换为横屏,如果我们只有一套布局,符合按比例缩放仍然显示正常的话,我们大可以选择第2种处理方案。但是如果我们的横竖屏布局是不同的,比如系统中的“设置”应用,那么我们选择第2种处理方案就是不合适的。
下图:
粮草先行——Android折叠屏开发技术点番外篇之运行时变更处理原则
这是一个典型的横竖屏分别采用不同布局的例子。
我们确定要采取那种解决方案后,接下来很可能要面对另一个问题,就是性能瓶颈。
根据前一篇文章的实验结果,在发生横竖屏切换的时候,activity的生命周期通常会按照如下顺序依次执行:

d/mainactivity: onpause
d/mainactivity: onsaveinstancestate
d/mainactivity: onstop
d/mainactivity: ondestroy
d/mainactivity: oncreate
d/mainactivity: onstart
d/mainactivity: onrestoreinstancestate
d/mainactivity: onresume

如果我们在生命周期中做了一些繁重的工作,那么整个activity在重启的过程中就会很慢。
要解决这个问题,首先我们要找fragment帮忙,因为bundle并不是用来传递大型对象的,而且这个对象还需要序列化和反序列化,如此执行起来就更慢了。
当然,如果你只是保存一些整型或者字符串的话,单纯使用bundle而不借助fragment也是可以的,但是这样的场景在实际开发中并不常见。
要借助fragment来中转对象,我们采用下面三步走的方式:

  1. 在fragment类中调用 setretaininstance(true);
  2. 在activity销毁时向fragment类存入数据;
  3. 在activity重建后根据tag检索fragment,并取出之前存入的数据。

下面用具体的代码片来演示:
首先来看fragment类:

public class testfragment extends fragment {

    private mydata data;

    @override
    public void oncreate(bundle savedinstancestate) {
        super.oncreate(savedinstancestate);
        setretaininstance(true);
    }

    public void setdata(mydata data) {
        this.data = data;
    }

    public mydata getdata() {
        return data;
    }
}

我们再来看activity类:

public class myactivity extends activity {

    private testfragment mtestfragment ;

    @override
    public void oncreate(bundle savedinstancestate) {
        super.oncreate(savedinstancestate);
        setcontentview(r.layout.main);
        fragmentmanager fm = getfragmentmanager();
        mtestfragment = (testfragment)fm.findfragmentbytag(“test”);

        if (retainedfragment == null) {
            mtestfragment = new testfragment ();
            fm.begintransaction().add(mtestfragment, “test”).commit();
            mtestfragment.setdata(restoredata());
        }
    }

    @override
    public void ondestroy() {
        super.ondestroy();
        mtestfragment.setdata(savedata());
    }
}

这里还要特别注意一点:在中转对象数据时,不要传入与activity紧密相关的对象,比如view,否则会造成内存泄漏。
至此,就完成了对重启activity方案的性能优化。