翔子 发表于 2010-10-13 16:52:27

Android系列之二十一 -- track memory allocations

下文来自http://developer.android.com/resources/articles/track-mem.html但需要越墙访问,特摘录在此。
Despite the impressive hardware of the first Android phones (T-Mobile G1 and ADP1) writing efficient mobile applications is not always straightforward. Android applications rely on automatic memory management handled by Dalvik's garbage collector which can sometimes cause performance issues if you are not careful with memory allocations.
In a performance sensitive code path, like the layout or drawing method of a view or the logic code of a game, any allocation comes at a price. After too many allocations, the garbage collector will kick in and stop your application to let it free some memory. Most of the time, garbage collections happen fast enough for you not to notice. However, if a collection happens while you are scrolling through a list of items or while you are trying to defeat a foe in a game, you may suddenly see a drop in performance/responsiveness of the application. It's not unusual for a garbage collection to take 100 to 200 ms. For comparison, a smooth animation needs to draw each frame in 16 to 33 ms. If the animation is suddenly interrupted for 10 frames, you can be certain that your users will notice.
Most of the time, garbage collection occurs because of tons of small, short-lived objects and some garbage collectors, like generational garbage collectors, can optimize the collection of these objects so that the application does not get interrupted too often. The Android garbage collector is unfortunately not able to perform such optimizations and the creation of short-lived objects in performance critical code paths is thus very costly for your application.
To help you avoid frequent garbage collections, the Android SDK ships with a very useful tool called allocation tracker. This tool is part of DDMS, which you must have already used for debugging purposes. To start using the allocation tracker, you must first launch the standalone version of DDMS, which can be found in the tools/ directory of the SDK. The version of DDMS included in the Eclipse plugin does not offer you ability to use the allocation tracker yet.
Once DDMS is running, simply select your application process and then click the Allocation Tracker tab. In the new view, click Start Tracking and then use your application to make it execute the code paths you want to analyze. When you are ready, click Get Allocations. A list of allocated objects will be shown in the first table. By clicking on a line you can see, in the second table, the stack trace that led to the allocation. Not only you will know what type of object was allocated, but also in which thread, in which class, in which file and at which line. The following screenshot shows the allocations performed by Shelves while scrolling a ListView.
Even though it is not necessary, or sometimes not possible, to remove all allocations for your performance critical code paths. the allocation tracker will help you identify important issues in your code. For instance, a common mistake I have seen in many applications is to create a new Paint object on every draw. Moving the paint into an instance field is a simple fix that helps performance a lot. I highly encourage you to peruse the Android source code to see how we reduce allocations in performance critical code paths. You will also thus discover the APIs Android provide to help you reuse objects.

翔子 发表于 2010-10-13 16:53:13

Android系列之二十二 -- 图形系统

http://www.moandroid.com/?p=937中介绍了一些关于Android图形系统的知识。

1 android.view.animation.Interpolator:管理动画过程的速度变化,比如整个动画过程是线性的,加速的,或者减速的,等等。
2 android.widget.Scroller:滚动管理。computeScrollOffset函数计算出当前位置以及是否滚动到边界。
3 android.widget.Gallery:水平方向管理一组child,并可以通过手势来滚动这组child。private class FlingRunnable implements Runnable 具体负责滚动这组child。run()计算当前的位置,并调用trackMotionScroll(delta)更新视图以及设置当前具有焦点的child。
4. Gradient
5. Android的view/widget有两种不同的监听和处理事件的方式。
第一种是对任意一个widget/view, 你都可以通过调用下列函数,setOnClickListener, setOnLongClickListener, setOnFocusChangeListener, setOnKeyListener, setOnTouchListener, setOnCreateContextMenuListener,为其设置一个分别处理click, longClick, focusChange, key, touch, createContextMenu事件的callback函数。

第二种是当派生一个新的widget时,可以重载其父类的事件处理函数,如onKeyDown, onTouchEvent, onFocusChanged等等。

第一种方法好处是无需派生一个新类而增加了widget处理任意事件的能力。


《未完待续》

翔子 发表于 2010-10-13 16:54:37

Android系列之二十三 -- message queue

这两天进一步了解了一下Android的message queue, thread, hander,runnable之间的关系。

每个message queue都会有一个对应的handler。handler会向message queue通过两种方法发送消息:send或post。这两种消息都会插在message queue队尾并按先进先出执行。但通过这两种方法发送的消息执行的方式略有不同:通过send发送的是一个message对象,会被handler的handleMessage()函数处理;而通过post方法发送的是一个runnable对象,则会自己执行。

每个带图形界面的应用启动后,都会创建一个主线程,可称之为GUI线程。这个线程自动就会创建一个message queue,来自于系统的消息都会投放到这个message queue里面,并按先进先出的顺序处理。

GUI线程图形界面中的view可通过post方法向GUI线程的message queue投递一个runnable。

对于除GUI线程以外的其他线程,创建时缺省并没有message queue,下面的示例演示了如何创建一个带有message queue 和handler的线程:

class LooperThread extends Thread
   {
      public Handler mHandler;

   public void run() {
         Looper.prepare();
         mHandler = new Handler() {

            public void handleMessage(Message msg) {
               // process incoming messages here
            }

         };

         Looper.loop();

      }

    }

而对于GUI线程,则可以直接(比如在onCreate)创建一个handler并重载handleMessage,省去创建message queue的过程。

翔子 发表于 2010-10-13 16:56:13

Android系列之二十四 -- home screen

Home screen可以说是一个手机的最重要应用,就像一个门户网站的首页,直接决定了用户的第一印象。下面对home screen做一简要分析。

home screen的代码位于packages/apps/Launcher目录。从文件launcher.xml,workspace_screen.xml可获知home screen的UI结构如下图所示:
<IMG title="Android系列之二十四 -- home screen" name=image_operate_22611271376309450 alt="Android系列之二十四 -- home screen" src="http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif" width=690 height=394 real_src="http://static8.photo.sina.com.cn/middle/5e71b14ft84517031c237&690">

整个homescreen是一个包含三个child view的FrameLayout(com.android.launcher.DragLayer)。

第一个child就是桌面com.android.launcher.Workspace。这个桌面又包含三个child。每个child就对应一个桌面。这就是你在Android上看到的三个桌面。每个桌面上可以放置下列对象:应用快捷方式,appwidget和folder。

第二个child是一个SlidingDrawer控件,这个控件由两个子控件组成。一个是 com.android.launcher.HandleView,就是Android桌面下方的把手,当点击这个把手时,另一个子控件,com.android.launcher.AllAppsGridView就会弹出,这个子控件列出系统中当前安装的所有类型为 category.launcher的Activity。

第三个child是com.android.launcher.DeleteZone。当用户在桌面上长按一个widget时,把手位置就会出现一个垃圾桶形状的控件,就是这个控件。

在虚拟桌面上可以摆放四种类型的对象:
1. ITEM_SHORTCUT,应用快捷方式
2. ITEM_APPWIDGET,app widget
3. ITEM_LIVE_FOLDER,文件夹
4. ITEM_WALLPAPER,墙纸。

类Favorites(LauncherSettings.java)和类LauncherProvider定义了一个content provider,用来存储桌面上可以放置的几个对象,包括shortcut, search和clock等。

类AddAdapter(AddAdapter.java)列出了这四个类型对象。当用户在桌面空白处长按时,下列函数序列被执行:
Launcher::onLongClick -->
Launcher::showAddDialog -->
Launcher::showDialog(DIALOG_CREATE_SHORTCUT); -->
Launcher::onCreateDialog -->
Launcher::CreateShortcut::createDialog:这个函数创建一个弹出式对话框,询问用户是要添加什么(快捷方式,appwidget, 文件夹和墙纸)其内容就来自AddAdapter。

类Favorites(LauncherSettings.java)和类LauncherProvider定义了一个content provider,用来存储桌面上可以放置的几个对象,包括shortcut, search和clock等。

类DesktopItemsLoader负责将桌面上所有的对象从content provider中提取。

线程private ApplicationsLoader mApplicationsLoader负责从包管理器中获取系统中安装的应用列表。(之后显示在AllAppsGridView上)。ApplicationsLoader::run实现:
1)通过包管理器列出系统中所有类型为Launcher,action为MAIN的activity;
2)对每一个Activity,
      a) 将Activity相关元数据信息,如title, icon, intent等缓存到appInfoCache;
      b) 填充到ApplicationsAdapter 中。填充过程中用到了一些小技巧,每填充4(UI_NOTIFICATION_RATE)个activity更新一下相应view。



在Launcher::onCreate中,函数startLoaders被调用。而该函数接着调用loadApplications和loadUserItems,分别获取系统的应用列表,以及显示在桌面上的对象列表(快捷方式,appwidget,folder等)。

Launcher上排列的所有应用图标由AllAppsGridView对象呈现。这个对象是一个GridView。其对应的Adapter是 ApplicationsAdapter,对应的model则是ApplicationInfo数组。数组内容是由ApplicationsLoader 装载的。
private class ApplicationsLoader implements Runnable。

翔子 发表于 2010-10-13 16:57:36

Android系列之二十五 -- aapt的一个bug

工具aapt用来生成apk。然而1.6版本中的aapt有下面一个bug。
假设res/layout目录下,有两个文件:
aaa.xml
bbb.xml

在aaa.xml中可以定义一个widget,假设id = aaa_widget。而在bbb.xml中,可以引用这个widget,不会出现任何错误。

然而,如够颠倒引用顺序,假设bbb.xml中定义了一个widget,id= bbb_widget,然后在aaa.xml中引用这个widget,就会报错:No resource found that matches the given name

其原因就在于aapt在处理xml中的widget resource引用时,竟然不会处理向后索引。第一种情况下,因为aaa.xml排名先于bbb.xml (按字母顺序排序),因此aaa_widget已经被定义,所以不出错。而第二种情况下,因为bbb_widget定义在后面的一个文件bbb.xml,因此在先处理aaa.xml时,这个widget还没有定义,就会报引用出错的错误。

呵呵。
页: 1 2 [3]
查看完整版本: Android 技术专题系列