`
Teok
  • 浏览: 150741 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Roman Guy的Android Trick系列文章笔记

 
阅读更多

Roman Guy是Android Framework的核心开发人员,从2009年开始,他在他的博客上发表多篇如何更好的开发android软件的文章(需要爬墙)。我的笔记的目的是把他这个系列的文章的核心内容总结起来。

 

第一篇.Faster Screen Orientation Change with Android

    由于Android运行在很多个硬件上不同的设备上,并且的它们的硬件配置在运行时是可以的。例如,你推开手机的键盘,那么屏幕就会从portrait切换到landscape。为了让Android应用开发更容易一些,Android OS自动处理了配置的变化并且用新的配置重启了当前的activity。这是一个默认行为。如果你不了解Android如何处理资源,强烈推荐你看官方说明

    最好不要自行处理这些变化,否则不能保证你的代码在以后的更多的设备中运行。

    文章介绍了一个很有用的Activity的api: onRetainNonConfigurationInstance(). This method can be used to pass an arbitrary object your future self and Android is smart enough to call this method only when needed.

     他给出了两个代码片段:

 

@Override
public Object onRetainNonConfigurationInstance() {
    final LoadedPhoto[] list = new LoadedPhoto[numberOfPhotos];
    keepPhotos(list);
    return list;
}

 然后在新创建的activity里用getLastNonConfigurationInstance()把你保存的object拿回来:

 

private void loadPhotos() {
    final Object data = getLastNonConfigurationInstance();

    // The activity is starting for the first time, load the photos from Flickr
    if (data == null) {
        mTask = new GetPhotoListTask().execute(mCurrentPage);
    } else {
        // The activity was destroyed/created automatically, populate the grid
        // of photos with the images loaded by the previous activity
        final LoadedPhoto[] photos = (LoadedPhoto[]) data;
        for (LoadedPhoto photo : photos) {
            addPhoto(photo);
        }
    }
}

 最后需要注意的是:

Be very careful with the object you pass through onRetainNonConfigurationChange() though. If the object you pass is for some reason tied to the Activity/Context, you will leak all the views and resources of the activity. This means you should never pass a View, a Drawable, an Adapter, etc. Photostream for instance extracts the bitmaps from the drawables and pass the bitmaps only, not the drawables. Finally, remember that onRetainNonConfigurationChange() should be used only to retain data that is expensive to load. Otherwise, keep it simple and let Android do everything.

也就是说,不要把跟Context/Activity绑定的东西传递过去,这样会导致memory leak。

 

示例程序有一个有意思的地方是,图片不是水平放置的,我开始以为ImageView什么的可以支持旋转,后来在源码中找了找,发现了如下的一个工具方法:

 

/**
     * Rotate specified Bitmap by a random angle. The angle is either negative or positive,
     * and ranges, in degrees, from 2.5 to 8. After rotation a frame is overlaid on top
     * of the rotated image.
     *
     * This method is not thread safe.
     *
     * @param bitmap The Bitmap to rotate and apply a frame onto.
     *
     * @return A new Bitmap whose dimension are different from the original bitmap.
     */
    static Bitmap rotateAndFrame(Bitmap bitmap) {
        final boolean positive = sRandom.nextFloat() >= 0.5f;
        final float angle = (ROTATION_ANGLE_MIN + sRandom.nextFloat() * ROTATION_ANGLE_EXTRA) *
                (positive ? 1.0f : -1.0f);
        final double radAngle = Math.toRadians(angle);

        final int bitmapWidth = bitmap.getWidth();
        final int bitmapHeight = bitmap.getHeight();

        final double cosAngle = Math.abs(Math.cos(radAngle));
        final double sinAngle = Math.abs(Math.sin(radAngle));

        final int strokedWidth = (int) (bitmapWidth + 2 * PHOTO_BORDER_WIDTH);
        final int strokedHeight = (int) (bitmapHeight + 2 * PHOTO_BORDER_WIDTH);
 // 宽高都是通过计算放大过的
        final int width = (int) (strokedHeight * sinAngle + strokedWidth * cosAngle);
        final int height = (int) (strokedWidth * sinAngle + strokedHeight * cosAngle);

        final float x = (width - bitmapWidth) / 2.0f;
        final float y = (height - bitmapHeight) / 2.0f;
        
        final Bitmap decored = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        final Canvas canvas = new Canvas(decored);
// 最终的生成一个包含原有图片并且该图片之外的地方都是透明的的图片
        canvas.rotate(angle, width / 2.0f, height / 2.0f);
        canvas.drawBitmap(bitmap, x, y, sPaint);
        canvas.drawRect(x, y, x + bitmapWidth, y + bitmapHeight, sStrokePaint);

        return decored;
    }
 

第二篇:Android Layout Tricks #1

这篇文章主要以一个例子来说明Layout使用不当而导致的浪费。

这个例子是以LinearLayout为例的。我们只要对比一下用RelativeLayout代替示例场景中的LinearLayout后,view tree中产生的变化,如图:

 

很明显,后者节省了一个LinearLayout,如果这个是一个ListView的item的layout的话,那么这个节省就更加可观。

 

另外他提到:

 

The layout pass can be especially expensive when you nest several 
LinearLayout that use the weight parameter, 
which requires the child to be measured twice.

 

 的确,在LinearLayout的源码中有相应的证明,参看LinearLayout#onMeasure(int widthMeasureSpec, int heightMeasureSpec)部分:如果child view的weight大于0,那么这个child view就会额外onMeasure一次。

 

总结语:UI是组织结构,配置的改变很容易引起连锁效应,我想Roman也是想告诉人们,要简单化你的UI,包括该文章后面的评论的一个例子:有人说他写了一个很棒的AbsouluteLayout,然后Roman回复说:

I don’t understand why it was so complicated for you to do this. Just a simple FrameLayout with margins would work fine.

所以对于UI乃至任何事情,复杂永远都是要避免的,否则你可能很轻易的被掉到沟里(试想你并不知道LinearLayout会怎么处理weight参数,而你写了一个有复杂LinearLayout嵌套的view,然后你发现你的view怎么这么慢,而你并不知道android正在努力的onMeasure啊)。

我自己的一个例子是,我之前写了一个组件,自定义UI,自己写了一个view,自己onMeasure,自己onLayout,结果后来,另外一个同事接受我的这个组建,然后他直接给改掉了,所有东西都用android自己的。不管效率问题,首先我这段代码在别人看来,是不好的,至少不易理解。如果我有足够的理由和数据来证明我的实现是OK的,那么我可以保证我的代码有更长的生命周期。

 

3. Android Layout Trick #2: Include to Reuse

 

Android带来了各种各样的widget(small visual construction blocks you can glue together to present the users with complex and useful interfaces)。尽管application经常需要更高级的可视化组件。一个组件可被看作是由多个简单的既有的wdget组成的复杂widget。譬如你可以重用一个包含一个滚动条和一个button的panel,等等。。

 

In Android XML layout files, each tag is mapped to an actual class instance (the class is always a subclass of View.) The UI toolkit lets you also use three special tags that are not mapped to a View instance: <requestFocus />, <merge /> and <include />. The latter, <include />, can be used to create pure XML visual components. 

 

 

在这篇文章的评论处,有人提到使用include的文件和被include的文件之间引用ID的问题,他认为:

问题在于,included的views的id在include它们的文件里是不可见的,这种情况在多个included文件也存在。

Roman答道:

不,它们是可见的。

然后他又问道:

既然如此,那么为什么我引用included views的ID后,在编译的时候会出现:“Unknown resource”。

Roman答道:

IDs的声明和使用必须有正确的顺序。这跟你没有使用include是一样的。如果你要引用included layout里面的ID,那么你要使用@+id或者把把id声明在values/目录内。引用一个included layout外部的id,同样要使用@+id

 

总之include标签可以让layout得到重用,它的一些细节可以用到的时候再仔细看。

 

4. Android Layout Tricks #3: Optimize, Part 1

 

The <merge /> was created for the purpose of optimizing Android layouts by reducing the number of levels in view trees.  文章通过一个示例来解释这个标记的功能。

 

尽管merge标记很有用,但是它仍然受到一些限制:

a)<merge />只能被用作XML layout的root标记。

b)如果你通过Inflater来创建layout的话,你必须指定一个ViewGroup并且必须设置attachToRoot为true(详见inflate()

分享到:
评论

相关推荐

    Trick

    在这个压缩包中,我们看到一系列以 "trick" 开头命名的.gif 图像,比如 "trickb12.gif" 和 "trick3d.gif"。这些可能是展示字体效果的示例图,展示了字体在不同样式或应用场景下的视觉表现,例如薄体("thin")、蓝图...

    Hattrick球场上座率概算

    Hattrick球场上座率概算 Hattrick球场上座率概算

    重修 Slope Trick(看这篇绝对够!).doc

    ### 重修 Slope Trick 技术解析 #### 一、引言 Slope Trick,作为一项优化动态规划(DP)问题的技术手段,在算法竞赛领域里占有重要地位。该技术的核心在于利用函数斜率的变化来简化计算过程,尤其是在面对那些代价...

    python-trick

    Python-trick,上传的事pdf文档

    The Kernel Trick.pdf

    在机器学习中,核技巧(Kernel Trick)是一种非常重要的技术,它允许我们在高维特征空间中有效地进行线性学习算法的操作,而无需显式地计算出高维空间的数据表示。核技巧在诸如支持向量机(SVM)等算法中发挥了重要...

    arp_trick.tar.gz

    在ARP_trick.tar.gz这个压缩包中,我们可以预期包含有关如何执行和防御ARP欺骗的相关资料。可能包括了以下内容: 1. **ARP协议原理**:首先,理解ARP的工作机制至关重要。当主机需要发送数据到某个IP地址时,它会...

    神经网络训练Trick 训练技巧.docx

    ### 神经网络训练Trick详解 #### 引言 神经网络训练是深度学习领域的一个核心环节,其效果的好坏直接影响着模型的性能。在实际应用中,开发者经常会遇到模型训练不佳的情况,这时就需要一系列的技巧(Tricks)来...

    web安全学习笔记.pdf

    "Web 安全学习笔记" Web 安全学习笔记是关于网络安全的综合性学习笔记,涵盖了 Web 安全的基础知识、常见威胁、防御策略等方面的内容。下面将详细介绍该笔记中所涉及的知识点: 一、Web 安全基础 * Web 安全定义...

    Hat_Trick_The Catch Game.unitypackage

    Hat Trick是Unity官方商店提供的5.5.0版本以上的一款游戏Demo。

    list_sticky_scroll_trick

    在Android开发中,"list_sticky_scroll_trick"是一个常见的UI设计技巧,它涉及到ListView的优化和用户体验提升。这个效果通常被称作“吸顶”或者“固定头部”效果,即当用户滚动列表时,某些特定的视图(如标题或...

    db_trick.sql

    db_trick.sql

    linux shell trick

    Linux Shell技巧是Linux系统操作中的重要组成部分,它是一种命令行接口,允许用户通过文本命令与操作系统进行交互。Shell脚本可以极大地提高效率,自动化日常任务,并且是系统管理员的得力工具。...

    trick:特技模拟环境。 Trick提供了一组通用的仿真功能和实用程序,可以自动构建仿真

    由NASA约翰逊航天中心开发的Trick仿真环境是一个功能强大的仿真开发框架,使用户能够为航天器开发的所有阶段构建应用程序。 特里克(Trick)加快了仿真的创建过程,以进行早期飞行器设计,性能评估,飞行软件开发,...

    zoj 2247 Magic Trick.md

    zoj 2247 Magic Trick.md

    vdr-hattrick-开源

    VDR-Hattrick是一款专为视频磁盘录像机(Video Disk Recorder, VDR)设计的开源插件。这款插件的出现,旨在为VDR用户提供一个独特的体验,即在观看电视节目的同时,能够实时查看在线足球游戏“Hattrick”的比赛情况...

    Hattrick Ranking-开源

    Hattrick Ranking,一款专为在线游戏Hattrick设计的CHPP(Hattrick个人程序插件)批准的应用程序,为玩家提供了一个独特的功能,即创建自定义的排名系统,以更深入地对比和分析Hattrick中的各支球队。这款开源软件的...

    android环境搭建地址链接

    ### 一、Android开发环境搭建 #### 1.1 下载代码库 在进行Android环境搭建前,首先需要通过`repo`工具来初始化并同步代码库。这一步骤通常涉及到以下命令: - `repoinit`: 初始化代码库列表。 - 参数:`urocket:...

    Hattrick Organizer Plugins-开源

    《Hattrick Organizer Plugins——开源的力量与Java的魅力》 在当今的数字时代,开源软件已经成为了推动技术进步的重要引擎,而Hattrick Organizer Plugins正是这一趋势的杰出代表。这款基于Java开发的插件集合,为...

    trick-plugin:将Trick整合到Jenkins中

    dev分支是Trick插件的主要开发分支。 从dev克隆以创建功能/主题分支是首选方法。 为插件做贡献 插件源代码托管在。 新功能建议和错误修复应作为提交。 在GitHub上克隆存储库,准备对本地存储库的更改,然后提交拉取...

Global site tag (gtag.js) - Google Analytics