Android琐碎知识记录

使用最新的API,并支持新的硬件

对于使用接口和平行Activity的具体做法,记录如下:

平行Activity(The parallel Activity pattern)

  private static boolean shinyNewAPIS = 
  android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB;
  
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Intent startActivityIntent = null;
    if(!shinyNewAPIS)
      startActivityIntent = new Intent(this, legacyActivity.class);
    else
      startActivityIntent = new Intent(this, hcActivity.class);
      
    startActivity(startActivityIntent);
  }

接口(The Interfaces for backwards compatibility)

  private static boolean newSensorAPIsSupported = 
    Build,VERSION.SDK_INT >= Build.VERSION_CODES.CUPCAKE;
  boolean gyroExists =
    getPackageManager().hasSystemFeature( PackageManager.FEATURE_SENSOR_GYROSCOPE );
  
  IOrientationSensorListener myListener;
  if ( gyroExists )
    myListener = new GyroOrientationSensorListener();
  else if ( newSensorAPIsSupported )
    myListener = new AccOrientationSensorListener();
  else 
    myListener = new AccOldOrientationSensorListener();
  <activity android:name=".MyActivity">
    <intent-filter>
      <category android:name="android.intent.category.DEFAULT" />
      <category android:name="android.intent.category.BROWSABLE" />
      <data android:scheme="http"
            android:host="mysite.com"
            android:pathPrefix="/news/articles/" />
    </intent-filter>
  </activity>

内存管理( Memory Managerment )

Heap Size

对于Android应用来说,App的运行时可用内存最小是16M,但是真实出厂的设备内存往往高于这个值,比如

可以使用ActivityManager.getMemoryClass() 读取内存信息。

Large Heaps

一般的Android应用都有一个固定的内存上限,但是对一些特殊的设备(比如平板)屏幕尺寸非常大,即使仅仅展示一张图片所占用的内存也是很可观的,所以在Honeycomb开始引入了largeHeap可以为App分配更多的内存。

在 Honeycomb 以上的系统上可以在AndroidManifest.xml中添加 “largeHeap” 选项。

  <application 
    android:name="com.example.foobar"
    android:largeHeap="true"
    ...
  </application>

这样可以申请更多的堆内存,申请更多的内存也会增加内存回收的负担,并且迫使其他的App因内存不足被杀死。

Garbage Collection

在垃圾回收方面,给App分贝更大的内存意味着更长的垃圾回收时间,在Gingerbreak之前,垃圾回收会有如下的弊端

Gingerbread 之后(包含)改进了上面的弊端

Bitmaps

Old way (pre-Honeycomb):

这种方式必须手动调用 recycled 或者 等待垃圾回收才能回收内存。图片占用的内存是在native模块申请的,java对象指向native的内存。Bitmap对象和图片真实内存不再同一个区域。

New way:

Bitmap和图片实际占用的内存都在托管代码部分。

Interpreting Log Message

有木有注意到Logcat中经常打印的信息,比如下面这样的Log 这条log包含了很多信息

D/dalvikvm( 9050 ): GC_CONCURRENT freed 2049K, 65% free 3571K/9991K, external 4703K/5261K, paused 2ms+2ms

Heap Dumps

MAT

MAT是一个Java程序的内存分析工具,使用它可以发现很多内存泄露的问题,在Android界还是很牛逼的。首先有些基本概念需要明确。

在MAT里面是使用 Dominator(支配者) Tree ( closest object on every path to node)来描述Retained heap 的,比如

左边是内存中的引用关系,右边是DominatorTree,所有的对象都是依赖A对象而活着的,但是D对象既可以依赖B也可以依赖C活着,所以它不依赖于B,C,而是依赖于A。

使用MAT查泄漏:

  1. 在DominatorTree视图中,查找RetainedHeap最大的对象,然后找到它的GC-Root (exclude weak reference)。
  2. 在Histogram视图中,查找内存占用最大的对象 => List Objects => GC-Root
  3. 在Histogram视图中查找对象实例的数量,通过数量判断是否溢出

可疑对象

Tips:

Advanced Android audio techniques

Video

AudioTrack Overview

Dalvik Virtual Machine Internals

Video

A JIT Compiler for Android’s Dalvik VM

Video

Overview

nTop 02 April 2015
blog comments powered by Disqus