歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Android狀態機statemachine詳解

先說兩句題外話,很感謝Android,在這裡能看到很多優秀的代碼。同時也感覺到外面的工程師真的很厲害,都是java人家就能寫出這麼牛的東西。感慨之下就有了些思考:我們絕大多數人只要把那些牛人已經創造出來的牛逼的東西,記住並且弄懂就是一件非常不錯的事情,至少能衣食無憂。:-D 讀書的時候需要經常做題,在理解的基礎上記住解題方法基本就能很牛了,事實上高考中考絕大多數都是已經有過的題型,能做到前面所說的應該能進入不錯的學校。工作後,慢慢也發現很多了不起的技術,都是在國外已經發展的很成熟基礎上學習過來的。作為一個普通人,還是不要天天談創新的好,hold不住,把基礎的東西記住掌握即可。說了一堆,也算聊以自慰。

我們知道類的成員可以分為兩種:方法和屬性。大多數情況下,對於一個狀態,比如某數大於0,類的方法都只能做出一種對應的操作,並且類的本身並不考慮外部狀態。android的狀態機就屬於大多數之後的那一小部分。對於某個事件,或者更准確的說,某一個消息,在不同的狀態下能做出不同的操作。並且android狀態機中的狀態是繼承的,就像數據結構中的樹一樣,如果當前節點(狀態)不能對這個事件做出響應,就會到父節點繼續判斷並且做出響應,在下面的講述中,我們稱這個為狀態路徑,而對於所有狀態稱為狀態樹。這一句話已經從整體上對狀態機進行了概括,記住這些對後面的理解很有好處。

State,狀態機中的狀態封裝類,這個類主要是實現了IState接口。其中有狀態的基本方法,enter,exit以及消息處理方法processMessage。enter方法在狀態機轉入這個狀態中會進行調用,exit方法在狀態機轉出這個方法時候會調用。這裡對於一個很簡單的類,google使用了接口屬性,說說自己的理解。接口中的方法都是公有方法,並且只能聲明常量。將主要方法都放在接口中聲明,一方面限制了方法的定義,一方面也突出了這個類主要就是擁有某種功能。另外在State裡面,聲明了一個protect類型的構造方法,這樣其他類就不可以直接聲明state類的對象。state在狀態機statemachine類裡面是以StateInfo類型使用的,這個基本不影響訪問。

statemachine裡面主要工作都是由SmHandler類來完成的,statemachine本身絕大多數方法都是都是對SmHandler方法的再次封裝。另外為了能夠做到及時響應主線程的消息,又聲明了一個HandlerThread,主要任務都是在這個線程裡面實現的。

現在直接去看SmHandler類吧,其最主要的方法就是handleMessage。該方法的主要是三大模塊,第一個消息處理,或者說是分配到對應的狀態再有對應的狀態進行處理比較合適,第二個狀態的初始化,大概可以理解成執行初始化狀態路徑上每個狀態的enter方法,第三個執行狀態轉移,即更新狀態樹。

            if (mIsConstructionCompleted) {
                /** Normal path */
                processMsg(msg);//第一個消息處理
            } else if (!mIsConstructionCompleted &&
                    (mMsg.what == SM_INIT_CMD) && (mMsg.obj == mSmHandlerObj)) {
                /** Initial one time path. */
                mIsConstructionCompleted = true;
                invokeEnterMethods(0);//第二個狀態的初始化
            } else {
                throw new RuntimeException("StateMachine.handleMessage: " +
                            "The start method not called, received msg: " + msg);
            }
            performTransitions();//第三個執行狀態轉移

首先去看下processMsg方法

                while (!curStateInfo.state.processMessage(msg)) {
                    /**
                    * Not processed
                    */
                    curStateInfo = curStateInfo.parentStateInfo;
                    if (curStateInfo == null) {
                        /**
                        * No parents left so it's not handled
                        */
                        mSm.unhandledMessage(msg);
                        break;
                    }
                    if (mDbg) {
                        Log.d(TAG, "processMsg: " + curStateInfo.state.getName());
                    }
                }

從這段代碼中(!curStateInfo.state.processMessage(msg))就說明了:如果當前狀態執行完processMessage方法返回了false,也就是對當前消息NOT_HANDLED,那麼就會持續調用這個狀態的父狀態執行方法。一般終有一個狀態能夠處理消息的,如果真的沒有處理,會記錄到unhandledMessage方法裡面的。

接下來請看第2頁精彩內容: http://www.linuxidc.com/Linux/2013-08/88700p2.htm

Copyright © Linux教程網 All Rights Reserved