Titanium 删除或自定义启动画面

来源:互联网 发布:广西网络广电局 编辑:程序博客网 时间:2024/06/04 19:57

原文: http://blog.csdn.net/u012859646/article/details/16802391

一 .  引子 

    在Titanium里(本文只以Alloy模式为例),通过对 app/assets/iphone 或 app/assets/android里的相关文件进行修改, 可以修改启动画面. 在iphone下,启动画面是不能少的, 不然你通不过苹果的审核. 网上也有不少讨论, 如何在iphone下去掉启动画面, 苹果官方的文档里有介绍一个trick, 就是用一张和你app首屏一样的画面来做为启动画面, 这样会让的app"看起来"没有启动画面, 感觉上能更快一些. 但是, 这本质上还是存在一个启动画面, 鉴于IOS的这种要求, 本文主要讨论的是Android下的相关事宜.

      你可能会问, 在android下,修改app/assets/android/default.png不就可以了, 其它还有什么文章可做. 本文想解决有的几个问题

  1.  更复杂的画面控制, 如使用动画效果
  2.  更少的内存占用. 下面会提到, titanium里, 目前的启动画面实现上有些问题, 会带来多余的内存消耗
  3.  控制启动画面显示的时间  

二.  titanium安卓启动画面的实现分析

        首先说说内存不合理占用的问题. 从理论上来说用Ti开发的项目会比原生的多些内存消耗, 一堆的Proxy对象, 加上对原生对象的一些封装, 会在内存中留下更多的东西来. 所以, 在Ti的开发中对于内存的使用更应该是要很谨慎. 特别是做一些内存消耗较大的app,如图片相关的应用. 一不小心, 很快就会out of memory.
 
       而Ti中对于启动画面的实现是不太"科学"的, 会导致启动的图片一直驻留在内存中. 我们可以通过android SDK中的monitor工具, 使用DUMP HPRO file, 导出app的内存映像, 再用SDK tools里提供的hprof-conv 工具转化成"Eclipse Memory Analyzer"能够读取的格式. 就能够对一个app的内存消耗一探究竟了. 下面一个例子.


图1 . 一个app的内存映象

      这里给出内存占用的前三名. 第一是主要是一些系统库和资源相关. 第二名是图片的LRU cache, 根据实现的源代码, 图片的cache最大会为一个app可用内存空间的1/8, 这是代码是写死的, 不过在内存不足或不在前台时, 可能会清空cache. 

       第三名就是我们需要特别关注的了, 这是一个Bitmap对象, 大小是2.4M, 这个内存占用对一个app来说可是不小. 我们可以从Bitmap的属性看出, 这个图的大小是 640*960, 这个刚好是我测试机的分辨率. 我们可以进一步做, 将这个对象下的bytes,即具体数据全部导出成文件(这是一个raw RGBA格式). 然后用GIMP打开, 这个图正是app的启动画面. 而且这个Bitmap会一直常驻内存, 占用着2M多的空间. 你在Ti的JS代码里也没办法将其释放掉.  而占据的空间和屏幕分辨率直接相关, 如果是更高分辨率的屏幕, 这个内存占用会更大.

      我们需要找出其实现方式 . 开始以为启动画面会在源代码里的实现, 翻了半天没看到相关的线索. 用"default.png"做为关键字也找不到结果, 走了不少弯路. 回到问题之初, 考虑, 这个default.png会不会在apk的包里被改名了呢? 解开apk, 果然, 这个文件会被复制成background.png. 于是, 根据这个线索我们在apk中的一个文件中找到了感兴趣的内容. 具体是在res/values/theme.xml文件中. 文件 内容如下.

<?xml version="1.0" encoding="utf-8"?><resources><style name="Theme.Titanium" parent="android:Theme">    <item name="android:windowBackground">@drawable/background</item></style></resources>
图2 theme.xml

       看到这儿, 大概就明白, 原来是用theme来实现的.  这个可以通过生成的AndroidManifest.xml文件来证实(build目录下). 其片段如下.
<activity  android:label="@string/appname" android:name=".YourActivity" android:theme="@style/Theme.Titanium"><intent-filter><action android:name="android.intent.action.MAIN"/><category android:name="android.intent.category.LAUNCHER"/></intent-filter></activity>
图3 AndroidManifest.xml 片段
其中YourActivity就是你的主Activity, 它会一直存在, 所以它的背景,那个占用不少空间的Bitmap会一直存在.


三 具体方案

      了解了其实现, 方案就有很多了. 你可以自定义theme, 也可以使用其它theme. 以下用的方案是比较简单的一个. 修改主activity的theme.
      

3.1  去掉启动画面.

       可以将theme直接改成系统自带的透明主题"@android:style/Theme.Translucent", 这样连自己定都不需要了. 你需要修改的是tiapp.xml. 在其<android>下的<manifest>下的<application>下, 加上你的activity的说明. 修改其theme,如下.

<activity  android:label="@string/appname" android:name=".YourActivity" android:theme="@android:style/Theme.Translucent"><intent-filter><action android:name="android.intent.action.MAIN"/><category android:name="android.intent.category.LAUNCHER"/></intent-filter></activity>

图4 tiapp.xml片段


      能过上面的修改,你可去掉android的默认启动画面, 在app的内存中也不会留下任何启动画面bitmap的足迹了.  这里顺便说下, 简单地把default.png去掉, 你的启动画面还是存在的,Ti会给你一张默认的有Ti标志的图. 

3.2 自定义启动画面的实现

      接下来的事就简单了, 我们直接显示一张图, 然后把窗口close掉就行了. 这样一方面启动画面还是有的, 另外, 显示完以后就释放了空间, 没有多余的内存占用. 在alloy.js中(以alloy的实现为例, 如果用的classic的, 也差不多.)
var splashWin = Ti.UI.createWindow({fullscreen : true,navBarHidden : true,tabBarHidden : true,backgroundImage : "default.png"});splashWin.open();setTimeout(function(){splashWin.close();splashWin = null;}, 5000);


图5 alloy.js片段

        以上的代码其实只是显示一个窗口,然后5秒后关掉. 这样还不能完全控制启动画面的显示时间 , 因为当你的index被创建时这个图片可能就看不到了. 为了让启动画面多显示一会,你可以让你的index延迟open. 一个setTimeout就可以了.

setTimeout(function(){$.index.open();}, 2500);
图6 index.js片段
       
        这样, 我们就实现了自定义且节省内存版本的启动画面, 同时可以控制显示的时间 .

3.3 其它扩展

       如果要实现一些动画效果fade in之类的, 只要在splashWin上加点代码就行了.  如果要显示多张图, 可以在窗口上放个ImageView, 通images来放. 其它扩展在这个基础上做起来就都很直观了.


四 小结

      个人角度来看, 节省内存是我最关注的, 因为一个app能用的内存空间毕竟不多. Ti应该实现一个用户更可控的启动画面的方案,以节省那些不必要的消耗. 其它一些功能,在了解了theme的实现后, 都是很容易理解并优化的.

--EnD--