androidのAPP性能之终端兼容优化笔记

来源:互联网 发布:java.util.base64 类 编辑:程序博客网 时间:2024/06/02 21:00

androidのAPP性能之终端兼容优化笔记

在Android产品开发中,适配方面遇到的几类挑战和解决思路。

如果你希望你的程序能顺利通过手机厂商变态的预装验收测试;如果你希望你的程序能支持十万,百万级以上的日访问量。那么在适配上的要求,绝不仅仅是在各款手机上的功能可用。以下的挑战是在设计和实现时都要重点考虑的:
内存占用小且峰值可控
各种屏幕尺寸上保持好的用户体验
程序包尽量小
功能性能自适应

1.        内存占用
当程序达到一定的复杂程度以后,OutOfMemory是一个头痛的问题,相信很多程序员都遇到过。虽然Java语言支持垃圾收集,但在Android开发中一不小心还是容易引发OutOfMemory异常。这些问题在项目的一开始可能不会引起重视,而当需要适配低端手机的时候,问题就会暴露出来。
解决这类问题的经验来看,首先需要管住内存占用大户,图片,内存缓冲区等,不用的时候要尽早释放。当然内存的使用和用户体验很多时候是需要平衡的,比如一些大量需要下载服务器端图片的程序,用完就丢弃的策略会造成重复下载。这里可以合理使用Java的软引用机制来在内存吃紧时回收图片,而内存富裕时图片保持在内存中供下次直接使用。
2.        各种屏幕尺寸的支持
基础知识前面很多大大的分享已经提到了,核心思想是布局必须自适应各种屏幕;有多套图片资源,供不同的分辨率下选择。这个安卓的UI框架提供了一套机制
上手前先吃透官方的http://developer.android.com/guide/practices/screens_support.html
当然9-pitch背景图片也是必须掌握的利器
多套图片资源会带来增加包的大小的问题,常用的一种方法是只提供一套在各种屏幕下可用资源图片,当然高分辨率下的体验会打折扣;而在程序第一次启动后,或者用到这个功能时从服务端下载更适合的资源。
3.        程序包尽量小
对于手机预置的程序来说,程序包的大小有着十分严厉的限制。
控制包的大小从小地方来说要做到:清理废弃的资源和代码;杜绝拷贝粘贴代码等。从大的地方来说,各模块的设计要尽量高内聚,低耦合。做到可裁剪,必要时需要开发打包工具帮助定制。
因为预置程序一般是针对特定款的手机,有了这些基础,就可以只是打包需要的资源和模块生成最小的包。
4.功能性能自适应
还有一类的适配问题是由手机的特性不同引起的:
比如适应Android某个版本以后的特性的功能,需要向前兼容。
比如需要第三方库支持的功能,需要在缺少这个库的手机上兼容
比如运算能力的差异导致的动画效果在某些手机上性能达不到要求,需要自动关闭动画。

处理这些Case,需要程序在执行功能前,检查先决条件是否满足。条件不满足时,采用备用方案,最低的要求是能自动的隐藏该功能。


APP性能之终端兼容优化分享

  说到APP终端兼容,确实不是一件容易的事情,在没有一个合适的兼容性测试平台之前,最多的是靠的是经验,其次靠的是设备测试和用户反馈。而对于开发过一段时间的android应用的鄙人来说,认为有以下几点值得在终端兼容上考虑的:
    1.显示兼容
    2.接口兼容
    3.硬件兼容

    第一部分:显示兼容
    显示兼容,即指的是在同一款软件在不同设备上都有良好的显示效果。显示效果体现在哪里呢?
    (1)常规的布局协调,不会在不同的设备上显示奇形怪状的布局
    解决这个问题的方法很多,大概介绍几种:
    1.常用RelativeLayout,它不仅能解决布局显示的问题,而且对比连续使用LinearLayout来说,程序的运行效率更高。
    2.LinearLayout注意使用layout_weight方法,但不正确的layout_weight方法有可能造成布局的变形。LinearLayout对比RelativeLayout来说,优点是代码量少,缺点是布局的不稳定性和性能上的低效,个人理解上,Relative最常用为主布局,LinearLayout用在小地方,FrameLayout一般用来占位或有时重写,AbsoluteLayout一般不用。
    3.使用9.png和使用各种dpi的图片,我们通常的做法是做出一张xhdpi的高分辨率图片,然后缩放为原来的3/4,1/2,1/4,因为通常的屏幕尺寸是——ldpi是120,mdpi是160,hdpi是240,xhdpi是320。
    4.多使用布局文件的引用和多类型资源
    5.对于常用的变量,习惯于独立定义常量
    6......

    (2)SurfaceView的布局协调,这个比较难,很多游戏都栽在这里,有些干脆直接锁定横竖屏方向和固定显示区域的大小,又或者直接拉伸,总之效果不好。
    1.RelativeLayout的思想。
    2.充分利用资源的多样性。


    第二部分:接口兼容
    现在随着4.0的出现,伴随的一个严重的问题就是,4.0出现了许多很好的接口,能大幅度简化自己的代码并且拥有更好的效果,但是又要考虑到向下兼容,自己又很难割舍。比如4.0的硬件加速功能。那怎么办呢。
    于是,策略模式+反射调用,就变得很常用了。
    举个例子:
    1、2.x版本之前打开恢复出厂设置是必须显式调用,而4.0之后打开恢复出厂可以可以隐式调用(类名又不再是"com.android.settings.MasterClear")时,要兼容可以这样:
    int version = Build.VERSION.SDK_INT;
    if(version <= 10){               
        Intent intent = new Intent();
        intent.setClassName("com.android.settings", "com.android.settings.MasterClear");
        startActivity(intent);
    }else{
        startActivity(new Intent("android.settings.BACKUP_AND_RESET_SETTINGS"));
    }

    2、2.x版本没有硬件加速,而4.0以上又支持了硬件加速,但是我们的应用在4.0上运行需要加载更多的资源以达到更佳效果(又必须是在硬件加速开启的条件下),2.3上则要减少资源的加载,我们可以这么做
    public Object callMethod(Class<?> _class , String methodName, Object args[])
                    throws SecurityException,
                    NoSuchMethodException,
                    IllegalArgumentException,
                    IllegalAccessException,
                    InvocationTargetException
    {
            Method method = _class.getMethod(methodName, new Class[0]);
            Object object = method.invoke(_class, args);
            return object;
    }


    //------------------------------------------
        boolean callSuccess = false;
        try {
                callMethod(View.class, "isHardwareAccelerated" , new Object[0]);
                callSuccess = true;
        } catch (SecurityException e) {
                e.printStackTrace();
        } catch (IllegalArgumentException e) {
                e.printStackTrace();
        } catch (NoSuchMethodException e) {
                e.printStackTrace();
        } catch (IllegalAccessException e) {
                e.printStackTrace();
        } catch (InvocationTargetException e) {
                e.printStackTrace();
        }
        if(callSuccess){
                //do load high texture
        }else{
                //do load low texture
        }
    //-------------------------------------------

    第三部分:硬件兼容
    android的诞生就意味着多硬件支持平台的诞生,多硬件支持。如果我们的应用在有蓝牙的情况下,要做xxx,那我们可以这么做
    if(getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)){
        //do your xxx
    }

 1.组件宽高多用fill_parent和wrap_content去适配,少写死长宽高
2.多用relativeLayout放置布局中的组件,少用线性布局+margin去调整布局

3.若是真要适应各分辨率去微调,可以使用以下代码去操作

int[] screenSize = UmApplication.getScreenSize();
                int screenWidth = screenSize[0]; // 屏幕宽度
                int screenHeight = screenSize[1]; // 屏幕高度
                if (screenWidth >= 480 && screenHeight >= 800) {
                        
                } else if (screenWidth == 320 && screenHeight == 480) {
                
                } else if (screenWidth == 240 && screenHeight == 320) {
                        
                }

4.若是还适应不了屏幕,可以再创建layout-***文件夹,在里面放相应屏幕的xml代码,图片资源同理:drawable-***
5.活用.9 图片,一般一些边框,背景就可以使用.9图片,既可以减少app大小,也可以省去适配的麻烦

6.还是一楼说的,尽量用简单的,嵌套少的的布局去实现你需要的效果,经验和感觉挺重要,上面说的都是最基本的方法。

0 0