• Android UI 优化-使用theme 预加载

    http://www.oschina.net/question/54100_34081

    在很多时候,我们需要给一个Layout设置一个背景。例如,我们下下面的layout中使用了这样一个背景:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?xml version=”1.0″ encoding=”utf-8″?>
    <LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”    android:orientation=”vertical”
    android:layout_width=”fill_parent”
    android:layout_height=”fill_parent”
    android:background=”@drawable/antelope_canyon”>
    <TextView android:text=”@+id/TextView01″
    android:id=”@+id/TextView01″
    android:layout_width=”wrap_content”
    android:layout_height=”wrap_content” >
    </TextView>
    </LinearLayout>

    其中的LinearLayout使用了 背景图片antelope_canyon。

    如果仔细观察程序的运行过过程,我们首先看到了黑色的activity背景,然后才看到背景图被加载,那是因为在activity start以后,我们才能调用setContentView设置我们的layout,然后才绘制我们在layout中放置的背景图。而在此之前,程序中绘 制的是android中默认黑色背景。 这样会给用户感觉我们的activity启动较慢。
    然而,如果将背景图定义在一个主题中,如下:

    1
    2
    3
    4
    5
    6
    7
    <?xml version=”1.0″ encoding=”utf-8″?>
    <resources>
    <style name=”Theme.Droidus” parent=”android:Theme”>
    <item name=”android:windowBackground”>@drawable/antelope_canyon</item>
    <item name=”android:windowNoTitle”>true</item>
    </style>
    </resources>

    然后在activity中使用这个主题 :

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <?xml version=”1.0″ encoding=”utf-8″?>
    <manifest xmlns:android=”http://schemas.android.com/apk/res/android”
    package=”com.droidus”
    android:versionCode=”1″
    android:versionName=”1.0″>
    <application android:icon=”@drawable/icon” android:label=”@string/app_name”>
    <activity android:name=”.SpeedUpStartupActivity”
    android:label=”@string/app_name”
    android:theme=”@style/Theme.Droidus”
    >
    <intent-filter>
    <action android:name=”android.intent.action.MAIN” />
    <category android:name=”android.intent.category.LAUNCHER” />
    </intent-filter>
    </activity>
    </application>
    <uses-sdk android:minSdkVersion=”4″ />
    </manifest>

    运行程序,可以看到背景图马上显示了,没有再看到黑色的背景图。

    为什么会有这样的现象呢?那是因为 程序的主题是在程序启动的时候加载的,而不是在activity启动之后加载!
    而如果在layout使用背景,背景图是在activity启动之后才加载,故而会让用户看到一个黑色背景闪动的过程。

  • Android 布局优化

    布局优化
    --------
    1. setContentView调用花费的时间取决于布局的复杂性:资源数据越大解析越慢,而更多的类也让布局实例化变慢
    2. 调用setContentView()几乎占用了从onCreate()开始到onResume()结束之间所有时间的99%
    3. 要节约时间,大多数基于同样的原则:减少创建对象的数量。消除不必要的对象,或者推迟创建对象
    4. 采用嵌套的线性布局会深化布局层次,从而导致布局和按键处理变慢。
    5. 合并布局。另一种减少布局层次的技巧是用<merge />标签来合并布局。
        Android布局的父视图是一个FrameLayou,如果你的布局的最上层也是一个FrameLayout,就可以用<merge />标签代替它,减少一层布局
    6. 重用布局,Android支持在XML布局中使用<include /> 标签,用来包含另一个布局。
        <include /> 标签可用于两个目的:
        1) 多次使用相同的布局
        2) 布局有一个通用的组成部分,或有部分依赖于设置配置(例如,屏幕方向纵向或横向)
    7. ViewStub
        推迟初始化是个方便的技术,可以推迟实例化,提高性能,还可能会节省内存(如果对象从未创建过)
        ViewStub是轻量级且不可见的视图,当需要时,在自己的布局中可以用它来推迟展开布局。
         下次遇到相关代码后,将代码整理在这里
    布局工具
    --------
    1. hierarchyviewer  用来查看布局的
    2. layoutopt  用于检测布局文件质量的
  • 基本界面控件

    五、基本界面控件

    大多数的界面控件都在android.view和android.widget包中,android.view.View为他们的父类,还有Dialog系列,android.app.Dialog为父类,等等。

    Android的原生控件,一般是在res/layout下的 xml文件中声明。然后在Activity通过使用super.setContentView(R.layout.某布局layout文件名)来加载 layout。在Activity中获取控件的引用需要使用super.findViewById(R.id.控件的ID),接着就可以使用这个引用对控 件进行操作,例如添加监听,设置内容等。当然也可以通过代码动态的使用控件。

     

    View子类结构图:

     

     

    TextView子类结构:

     

     

    ViewGroup子类结构图:

     

     

    FrameLayout子类结构:

     

     

    android.app.Dialog子类结构:

     

    第一部分,基本控件

    1.文本类:

    http://limingnihao.iteye.com/blog/851386

    TextView、EditText、AutoCompleteTextView、MultAutoCompletTextView 、(TextSwitcher) 、(DigitalClock)

     

    ExtractEditText、CheckedTextView、Chronometer

     

    2.按钮类:

    http://limingnihao.iteye.com/blog/851396

    Button、CheckBox、RadioButton(RadioGroup) 、ToggleButton 、(ImageButton )

     

    CompoundButton

     

    缩放按钮:

    ZoomButton、ZoomControls

     

    3.图片类:

    http://limingnihao.iteye.com/blog/851408

    ImageView、ZoomButton、ImageButton、(ImageSwitcher )

     

    QuickContactBadge

     

    4.时间控件:

    http://limingnihao.iteye.com/blog/852493

    DigitalClock、AnalogClock、TimePicker、DatePicker

     

    5.进度显示:

    http://limingnihao.iteye.com/blog/852498

    ProgressBar、AbsSeekBar、SeekBar、RatingBar

     

    6.导航:

    TabHost、TabWidget。

     

    7.视频媒体:

    VideView、MediaController

     

    8.Dialog对话框

    CharacherPickerDialog、AlertDialog、DatePickerDialog、ProgressDialog、TimePickerDialog

     

    第二部分,布局类

    1.布局类:

    AbsoluteLayout、LinearLayout、RadioGroup 、TableLayout、 TableRow、RelativeLayout、FrameLayout

     

    2.需要适配器的布局类:

    AdapterView、AbsListView、GridView、ListView、AbsSpinner、Gallery Spinner

     

    3.滚动条:

    HorizontalScrollView、ScrollView

     

    第三部分,其他

    网页:

    WebView

     

    动画:

    ViewAimator、ViewFilpper、ViewSwitcher、ImageSwitcher、TextSwitcher

     

    其他:

    KeyboardView

    SurfaceView(照相时会使用) GLSurfaceView

    ViewStub DialerFilter TwolineListItem SlidingDrawer GestureOverlayView

     

    其中:

    ListView一般与ListActivity一一起使用。TabActivity: http://limingnihao.iteye.com/

    TabHost、TabWidget一般与TabActivity一起使用。ListActivity: http://limingnihao.iteye.com/

  • setContentView

    http://android-developers.blogspot.in/2009/03/android-layout-tricks-3-optimize-with.html

    Android中visibility属性VISIBLE、INVISIBLE、GONE的区别

    在Android开发中,大部分控件都有visibility这个属性,其属性有3个分别为“visible ”、“invisible”、“gone”。主要用来设置控制控件的显示和隐藏。有些人可能会疑惑Invisible和gone是有什么区别的???那 么,我们带着这个疑问看下面:

    其在XML文件和Java代码中设置如下:

     

     

    可见(visible)

    XML文件:android:visibility=”visible”

    Java代码:view.setVisibility(View.VISIBLE);

     

    不可见(invisible)

    XML文件:android:visibility=”invisible”

    Java代码:view.setVisibility(View.INVISIBLE);

     

    隐藏(GONE)

    XML文件:android:visibility=”gone”

    Java代码:view.setVisibility(View.GONE);

     

     

    为了区别三者,我建了一个Dome进行演示,先上Dome的代码,演示后就知道它们的区别:

    XML文件:

    1. <?xml version=“1.0” encoding=“utf-8”?>
    2. <LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”
    3.     android:layout_width=“fill_parent”
    4.     android:layout_height=“fill_parent”
    5.     android:orientation=“vertical”>
    6.     <LinearLayout
    7.         android:layout_width=“fill_parent”
    8.         android:layout_height=“wrap_content”
    9.         android:orientation=“horizontal”
    10.         android:layout_marginBottom=“20dip” >
    11.         <TextView
    12.             android:layout_width=“wrap_content”
    13.             android:layout_height=“wrap_content”
    14.             android:layout_weight=“1”
    15.             android:background=“#F00”
    16.             android:text=“TextView1”
    17.             android:textSize=“23sp”
    18.             android:visibility=“visible” />
    19.         <TextView
    20.             android:id=“@+id/mainTV2”
    21.             android:layout_width=“wrap_content”
    22.             android:layout_height=“wrap_content”
    23.             android:layout_weight=“1”
    24.             android:background=“#00F”
    25.             android:text=“TextView2”
    26.             android:textSize=“23sp”
    27.             android:visibility=“visible” />
    28.     </LinearLayout>
    29.     <Button
    30.         android:id=“@+id/mainBtn1”
    31.         android:layout_width=“fill_parent”
    32.         android:layout_height=“wrap_content”
    33.         android:text=“TextView2为VISIBLE”
    34.         android:onClick=“mianOnClickListener”/>
    35.     <Button
    36.         android:id=“@+id/mainBtn2”
    37.         android:layout_width=“fill_parent”
    38.         android:layout_height=“wrap_content”
    39.         android:text=“TextView2为INVISIBLE”
    40.         android:onClick=“mianOnClickListener”/>
    41.     <Button
    42.         android:id=“@+id/mainBtn3”
    43.         android:layout_width=“fill_parent”
    44.         android:layout_height=“wrap_content”
    45.         android:text=“TextView2为GONE”
    46.         android:onClick=“mianOnClickListener”/>
    47. </LinearLayout>

    后面三个Button只要是控制TextView的visibility的属性

    Java代码:

    1. package com.chindroid.visibility;
    2. import android.app.Activity;
    3. import android.os.Bundle;
    4. import android.view.View;
    5. import android.widget.TextView;
    6. public class MainActivity extends Activity {
    7.     /** TextView2 */
    8.     private TextView mainTV2 = null;
    9.     @Override
    10.     public void onCreate(Bundle savedInstanceState) {
    11.         super.onCreate(savedInstanceState);
    12.         setContentView(R.layout.main);
    13.         //初始化数据
    14.         initData();
    15.     }
    16.     /** 初始化控件的方法 */
    17.     private void initData() {
    18.         mainTV2 = (TextView)findViewById(R.id.mainTV2);
    19.     }
    20.     /**
    21.      * MainActivity中响应按钮点击事件的方法
    22.      * 
    23.      * @param v
    24.      */
    25.     public void mianOnClickListener(View v){
    26.         switch (v.getId()){
    27.             case R.id.mainBtn1:{    //按钮1的响应事件
    28.                 //设置TextView2可见
    29.                 mainTV2.setVisibility(View.VISIBLE);
    30.                 break;
    31.             }
    32.             case R.id.mainBtn2:{    //按钮2的响应事件
    33.                 //设置TextView2不可见
    34.                 mainTV2.setVisibility(View.INVISIBLE);
    35.                 break;
    36.             }
    37.             case R.id.mainBtn3:{    //按钮3的响应事件
    38.                 //设置TextView2隐藏
    39.                 mainTV2.setVisibility(View.GONE);
    40.                 break;
    41.             }
    42.             default:
    43.                 break;
    44.         }
    45.     }
    46. }

    由于程序一启动两个TextView都是可见的

    当我们点击第1个按钮,把TextView2visibility属性设置为INVISIBLE时,程序如下如下图所示:

    当我们点击第3个按钮,把TextView2visibility属性设置为GONE时,程序如下如下图所示:

    当我们再点击第1个按钮,把TextView2visibility属性设置为VISIBLE时,TextView2又呈现出来了,如下图所示:

     

    由上面的演示可知

    VISIBLE:设置控件可见

    INVISIBLE:设置控件不可见

    GONE:设置控件隐藏

     

    而INVISIBLE和GONE的主要区别是:当控件visibility属性为INVISIBLE时,界面保留了view控件所占有的空间;而控件属性为GONE时,界面则不保留view控件所占有的空间。

     

  • Java条件编译

    http://www.mamicode.com/info-detail-650763.html

     

    学习过C语言或者C++语言的同学都知道它们支持条件编译,那么今天我们来学习下在Java语言中如何实现条件编译。Java语言本身没有提供条件编译,但是Java编译器对.java文件编译为.class文件做了优化,下面通过一个例子给大家详细讲解。

    下面先给出HelloWorld.java文件:

     1 package com.test;
     2 
     3 /**
     4  * Test Demo
     5  */
     6 public class HelloWorld {
     7 
     8     public static void main(String[] args) {
     9         if (BuildConfig.FLAG) {
    10             System.out.println("Hello World");
    11         } else {
    12             System.out.println("Java条件编译测试");
    13         }
    14     }
    15 
    16 }

    再来看看BuildConfig.java文件:

    package com.test;
    
    /**
     * Created by Administrator on 2015/5/24.
     */
    public final class BuildConfig {
    
        public static final boolean FLAG = false;
    }

     

    再来看看该.java文件被转化为.class文件的内容:

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by Fernflower decompiler)
    //
    
    package com.test;
    
    public class HelloWorld {
        public HelloWorld() {
        }
    
        public static void main(String[] args) {
            System.out.println("Java条件编译测试");
        }
    }

    可以知道的是BuildConfig.FLAG永远都为false,if块内的代码当然也不会被执行,这部分代码就不会被编译到.class文件中。

    如果FLAG是字符串会怎么样?字符串之间如果使用equals进行比较,在转化为.class文件时不会得到优化。

    HelloWorld.java文件:

    package com.test;
    
    /**
     * Test Demo
     */
    public class HelloWorld {
    
        public static void main(String[] args) {
            if (BuildConfig.FLAG.equals("false")) {
                System.out.println("Hello World");
            } else {
                System.out.println("Java条件编译测试");
            }
        }
    
    }

    HelloWorld.class文件:

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by Fernflower decompiler)
    //
    
    package com.test;
    
    public class HelloWorld {
        public HelloWorld() {
        }
    
        public static void main(String[] args) {
            if("false".equals("false")) {
                System.out.println("Hello World");
            } else {
                System.out.println("Java条件编译测试");
            }
    
        }
    }

    如果真的需要字符串比较,实现条件编译的话可以使用 “==”。

    HelloWorld.java文件:

    package com.test;
    
    /**
     * Test Demo
     */
    public class HelloWorld {
    
        public static void main(String[] args) {
            if (BuildConfig.FLAG == "false") {
                System.out.println("Hello World");
            } else {
                System.out.println("Java条件编译测试");
            }
        }
    
    }

    HelloWorld.class文件:

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by Fernflower decompiler)
    //
    
    package com.test;
    
    public class HelloWorld {
        public HelloWorld() {
        }
    
        public static void main(String[] args) {
            System.out.println("Hello World");
        }
    }

     

  • Handler and Activity’s life cycle, take care about orphan threads!!

    http://android2ee.blogspot.com/2011/11/handler-and-activity-life-cycle-take.html

    Handler and Activity’s life cycle, take care about orphan threads!!

    Hello,

    You have an Activity which uses a Handler. You create your handler and overwrite the handleMessage method, you launch the handler’s thread and that’s it for the handler management… Most of us do such a thing and it’s a huge mistake!!! What happens to your thread when your activity pauses and resumes and worst when it dies and (re)creates?
    You thread becomes an orphan thread !
    So you have written something like that :

    (BAD CODE EXAMPLE DO NOT USE)

    /**

    * The handler

    */

    private final Handler slowDownDrawingHandler;

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

    // handler definition

    slowDownDrawingHandler = new Handler() {

    /** (non-Javadoc)*/

    @Override

    public void handleMessage(Message msg) {

    super.handleMessage(msg);

    redraw();

    }

    };

    // Launching the Thread to update draw

    Thread background = new Thread(new Runnable() {

    /**

    * The message exchanged between this thread and the handler

    */

    Message myMessage;

    // Overriden Run method

    public void run() {

    try {

    while (true) {

    // Sleep

    Thread.sleep(100);

    // Do something

    myMessage = slowDownDrawingHandler.obtainMessage();

    // then send the message

    slowDownDrawingHandler.sendMessage(myMessage);

    }

    }

    } catch (Throwable t) {

    // just end the background thread

    }

    }

    });

    // start the thread

    background.start();

    Using such a code, when your activity pauses or dies your thread is still alive and become an orphan thread. Nothing can stop it, neither inter-acts with it and it continues to run. This is a big fail.

    What is the right way to do it: You have to manage your thread state according to your activity state. In other words, when your activity pauses, you have to pauses your thread, when it resumes you have to resume your thread, when your activity dies, you thread must die….

    A simple way to do that is to use two atomic Booleans (synchronized boolean), isPausing and isStopping, change their value in the onResume, onPause, onCreate and onDestroy methods of your activity and use that boolean to pause or stop your thread.

    So the right code should look like that:
    Good Code Example CAN BE USED

    /** * The handler  */

    private final Handler slowDownDrawingHandler;

    /** * An atomic boolean to manage the external thread’s destruction */

    AtomicBoolean isRunning = new AtomicBoolean(false);

    /** * An atomic boolean to manage the external thread’s destruction */

    AtomicBoolean isPausing = new AtomicBoolean(false);

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

    // handler definition

    slowDownDrawingHandler = new Handler() {

    @Override

    public void handleMessage(Message msg) {

    super.handleMessage(msg);

    redraw();

    }

    };

    // Launching the Thread to update draw

    Thread background = new Thread(new Runnable() {

    /**

    * The message exchanged between this thread and the handler

    */

    Message myMessage;

    // Overriden Run method

    public void run() {

    try {

    while (isRunning.get()) {

    if(isPausing.get()) {

    Thread.sleep(2000);

    }else {

    // Sleep

    Thread.sleep(100);

    // Do something

    myMessage = slowDownDrawingHandler.obtainMessage();

    // then send the message

    slowDownDrawingHandler.sendMessage(myMessage);

    }

    }

    }

    } catch (Throwable t) {

    // just end the background thread

    }

    }

    });

    // Initialize the threadSafe booleans

    isRunning.set(true);

    isPausing.set(false);

    background.start();

    }

    /*(non-Javadoc) */

    @Override

    protected void onPause() {

    //and don’t forget to stop the thread

    isPausing.set(true);

    super.onPause();

    }

    /*(non-Javadoc) */

    @Override

    protected void onResume() {

    //and don’t forget to relaunch the thread

    isPausing.set(false);

    super.onResume();

    }

    /*(non-Javadoc) */

    @Override

    protected void onDestroy() {

    //and don’t forget to kill the thread

    isRunning.set(false);

    super.onDestroy();

    }
    So, Thanks who?
    Thanks, Android2ee, the Android Programming Ebooks :o)

    Mathias Séguy
    mathias.seguy.it@gmail.com
    Auteur Android2EE
    Ebooks to learn Android Programming.

    Retrouvez moi sur Google+
    Suivez moi sur Twitter
    Rejoignez mon réseau LinkedIn ou Viadeo

  • Android Activity Launch Mode

    Activity的launchMode:singleTop,singleTask与singleInstance

     

    相关内容,可以参见官方网址:http://developer.android.com/guide/components/tasks-and-back-stack.html

    如图所示,如果ABC三个Activity的launchMode都是standard,那么按照图示顺序调用后,堆栈为ABCBB;
    而如果界面ActivityB的launchMode为singleTop,同样的调用关系下,堆栈为ABCB,栈顶的B,被复用了。

    singleTop模式,适合于与用户交互时保持信心更新的界面Activity,比如联系人的搜索界面界面等;

    singleTop仅作为栈顶Activity时才可能被复用,同一个Activity在系统中,还是会存在多个的现象。
    singleTasksingleInstance,在整个系统中,仅会有一个对象存在,以节省内存开销。
    如果运行模式不是默认的standard模式,那么,该Activity需要重载onNewIntent的函数。
    standard和singleTop,对它的调用,不会引起任务切换;而singleTask和singleInstance,则相反。
    换句话说,而singleTask和singleInstance,其Activity的对象,仅可作为任务的根Activity而存在,
    而standard和singleTop,其Activity的对象,则可能存在Activity堆栈的任何位置。

    如图所示,当B的运行模式为singleTask和singleInstance时,所有对B的调用,
    都会跳转到以B为根的任务中进行,而与调用Activity所在的任务,毫无关联。

    singleTask和singleInstance唯一的区别是:
    singleInstance,其所在的任务中,包含且只包含一个该Activity的对象,不会再有其他的Activity对象;
    而singleTask,其任务中,则可能包含多个其他相关的Activity对象。

    singleTask和singleInstance适用于消耗内存较多的单实例界面,比如浏览器和音乐播放器等。

    摘自《Android开发精要》

  • dnstap

    http://dnstap.info/slides/dnstap_nanog61.pdf

     

    dnstap

     –  What  is  it?

    • High  speed  DNS  logging  without  packet  capture
    • Encoding  uses  Protocol  Buffers
    • Binary  clean
    • Efficient  encoding
    • Extendable
    • Implementa6ons  available  for  many  programming
  • HTTP PROXY 协议

    https://imququ.com/post/web-proxy.html

     

    HTTP 代理存在两种形式,分别简单介绍如下:

    第一种是 RFC 7230 – HTTP/1.1: Message Syntax and Routing(即修订后的 RFC 2616,HTTP/1.1 协议的第一部分)描述的普通代理。这种代理扮演的是「中间人」角色,对于连接到它的客户端来说,它是服务端;对于要连接的服务端来说,它是客户端。它就负责在两端之间来回传送 HTTP 报文。

    第二种是 Tunneling TCP based protocols through Web proxy servers(通 过 Web 代理服务器用隧道方式传输基于 TCP 的协议)描述的隧道代理。它通过 HTTP 协议正文部分(Body)完成通讯,以 HTTP 的方式实现任意基于 TCP 的应用层协议代理。这种代理使用 HTTP 的 CONNECT 方法建立连接,但 CONNECT 最开始并不是 RFC 2616 – HTTP/1.1 的一部分,直到 2014 年发布的 HTTP/1.1 修订版中,才增加了对 CONNECT 及隧道代理的描述,详见 RFC 7231 – HTTP/1.1: Semantics and Content。实际上这种代理早就被广泛实现。