Android系統(tǒng)原理與源碼分析方案_第1頁
Android系統(tǒng)原理與源碼分析方案_第2頁
Android系統(tǒng)原理與源碼分析方案_第3頁
Android系統(tǒng)原理與源碼分析方案_第4頁
Android系統(tǒng)原理與源碼分析方案_第5頁
已閱讀5頁,還剩12頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

精品文檔-下載后可編輯Android系統(tǒng)原理與源碼分析方案

本文以下就是如何隨心所欲地控制AlertDialog的介紹。

現(xiàn)在我們來看看個需求:如果某個應(yīng)用需要彈出一個對話框。當(dāng)單擊“確定“按鈕時完成某些工作,如果這些工作失敗,對話框不能關(guān)閉。而當(dāng)成功完成工作后,則關(guān)閉對話框。當(dāng)然,無論何程度情況,單擊“取消”按鈕都會關(guān)閉對話框。

這個需求并不復(fù)雜,也并不過分。但使用過AlertDialog的讀者都知道,無論單擊的哪個按鈕,無論按鈕單擊事件的執(zhí)行情況如何,對話框是肯定要關(guān)閉的。也就是說,用戶無法控制對話框的關(guān)閉動作。實際上,關(guān)閉對話框的動作已經(jīng)在AndroidSDK寫死了,并且未給使用者留有任何接口。但我的座右銘是“宇宙中沒有什么是不能控制的”。

既然要控制對放框的關(guān)閉行為,首先就得分析是哪些類、哪些代碼使這個對話框關(guān)閉的。進入AlertDialog類的源代碼。在AlertDialog中只定義了一個變量:mAlert。這個變量是AlertCONtroller類型。AlertController類是Android的內(nèi)部類,在ernal.app包中,無法通過普通的方式訪問。也無法在Eclipse中通過按Ctrl鍵跟蹤進源代碼。但可以直接在Android源代碼中找到AlertController.java。我們再回到AlertDialog類中。AlertDialog類實際上只是一個架子。象設(shè)置按鈕、設(shè)置標(biāo)題等工作都是由AlertController類完成的。因此,AlertController類才是關(guān)鍵。

找到AlertController.java文件。打開后不要感到頭暈哦,這個文件中的代碼是很多地。不過這么多代碼對本文的主題也沒什么用處。下面就找一下控制按鈕的代碼。

在AlertController類的開頭就會看到如下的代碼:

View.OnClickListenermButtonHandler=newView.OnClickListener(){

publicvoidonClick{

Messagem=null;

if {

m=Message.obtain;

}elseif {

m=Message.obtain;

}elseif {

m=Message.obtain;

}

if {

m.sendToTarget();

}

//Postamessagesowedismissaftertheabovehandlersareexecuted

mHandler.obtainMessage

.sendToTarget();

}

};

從這段代碼中可以猜出來,前幾行代碼用來觸發(fā)對話框中的三個按鈕的單擊事件,而的代碼則用來關(guān)閉對話框。

mHandler.obtainMessage

.sendToTarget();

上面的代碼并不是直接來關(guān)閉對話框的,而是通過一個Handler來處理,代碼如下:

privatestATIcfinalclassButtonHandlerextendsHandler{

//ButtonclickshaveMessage.whatastheBUTTON{1,2,3}constant

privatestaTIcfinalintMSG_DISMISS_DIALOG=1;

privateWeakReference《DialogInterface》mDialog;

publicButtonHandler{

mDialog=newWeakReference《DialogInterface》;

}

@Override

publicvoidhandleMessage{

switch {

caseDialogInterface.BUTTON_POSITIVE:

caseDialogInterface.BUTTON_NEGATIVE:

caseDialogInterface.BUTTON_NEUTRAL:

((DialogInterface.OnClickListener)msg.obj)。onClick(mDialog.get(),msg.what);

break;

caseMSG_DISMISS_DIALOG:

((DialogInterface)msg.obj)。dismiss();

}

}

}

從上面代碼的可以找到

((DialogInterface)msg.obj)。dismiss();。在AlertController處理對話框按鈕時會為每一個按鈕添加一個onclick事件。而這個事件類的對象實例就是上面的mButtonHandler。在這個單擊事件中首先會通過發(fā)送消息的方式調(diào)用為按鈕設(shè)置的單擊事件(也就是通過setPositiveButton等方法的第二個參數(shù)設(shè)置的單擊事件),在觸發(fā)完按鈕的單擊事件后,會通過發(fā)送消息的方式調(diào)用dismiss方法來關(guān)閉對話框。而在AlertController類中定義了一個全局的mHandler變量。在AlertController類中通過ButtonHandler類來對象來為mHandler賦值。因此,我們只要使用我們自己Handler對象替換ButtonHandler就可以阻止調(diào)用dismiss方法來關(guān)閉對話框。下面先在自己的程序中建立一個新的ButtonHandler類。

classButtonHandlerextendsHandler

{

privateWeakReference《DialogInterface》mDialog;

publicButtonHandler

{

mDialog=newWeakReference《DialogInterface》;

}

@Override

public

voidhandleMessage

{

switch

{

caseDialogInterface.BUTTON_POSITIVE:

caseDialogInterface.BUTTON_NEGATIVE:

caseDialogInterface.BUTTON_NEUTRAL:

((DialogInterface.OnClickListener)msg.obj)。onClick(mDialog

.get(),msg.what);

break;

}

}

}

我們可以看到,上面的類和AlertController中的ButtonHandler類很像,只是支掉了switch語句的一個case子句和相關(guān)的代碼。

由于mHandler是private變量,因此,在這里需要使用Java的反射技術(shù)來為mHandler賦值。由于在AlertDialog類中的mAlert變量同樣也是private,因此,也需要使用同樣的反射技術(shù)來獲得mAlert變量。代碼如下:

先建立一個AlertDialog對象

AlertDialogalertDialog=newAlertDialog.Builder

.setTitle

.setMessage

.setIcon

.setPositiveButton

newOnClickListener()

{

@Override

publicvoidonClick

{

}

})。setNegativeButton()

{

@Override

publicvoidonClick

{

dialog.dismiss();

}

})。create();

上面的對話框很普通,單擊哪個按鈕都會關(guān)閉對話框。下面在調(diào)用show方法之前來修改一個mHandler變量的值,OK,下面我們就來見證奇跡的時刻。

try

{

Fieldfield=alertDialog1.getClass()。getDeclaredField;

field.setAccessible;

//

獲得mAlert變量的值

Objectobj=field.get;

field=obj.getClass()。getDeclaredField;

field.setAccessible;

//

修改mHandler變量的值,使用新的ButtonHandler類

field.set;}

catch{

}

//

顯示對話框

alertDialog.show();

我們發(fā)現(xiàn),如果加上try

catch語句,單擊對話框中的確定按鈕不會關(guān)閉對話框,單擊取消按鈕則會關(guān)閉對話框。如果去了try…catch代碼段,對話框又會恢復(fù)正常了。

以上代碼解決了問題,但需要的代碼還比較多,所以我們采用了另一種方法來阻止關(guān)閉對話框。

這種方法需要用點技巧。由于系統(tǒng)通過調(diào)用dismiss來關(guān)閉對話框,那么我們可以在dismiss方法上做點文章。在系統(tǒng)調(diào)用dismiss方法時會首先判斷對話框是否已經(jīng)關(guān)閉,如果對話框已經(jīng)關(guān)閉了,就會退出dismiss方法而不再繼續(xù)關(guān)閉對話框了。因此,我們可以欺騙一下系統(tǒng),當(dāng)調(diào)用dismiss方法時我們可以讓系統(tǒng)以為對話框已經(jīng)關(guān)閉(雖然對話框還沒有關(guān)閉),這樣dismiss方法就失效了,這樣即使系統(tǒng)調(diào)用了dismiss方法也無法關(guān)閉對話框了。

下面讓我們回到AlertDialog的源代碼中,再繼續(xù)跟蹤到AlertDialog的父類Dialog的源代碼中。找到dismissDialog方法。實際上,dismiss方法是通過dismissDialog方法來關(guān)閉對話框的,dismissDialog方法的代碼如下:

private

voiddismissDialog(){

if  {

if Log.v;

return;

}

if {

if Log.v;

return;

}

mWindowManager.removeView;

mDecor=null;

mWindow.closeAllPanels();

onStop();

mShowing=false;

sendDismissMessage();

}

該方法后面的代碼不用管它,先看if{…}這段代碼。這個mShowing變量就是判斷對話框是否已關(guān)閉的。因此,我們在代碼中通過設(shè)置這個變量就可以使系統(tǒng)認(rèn)為對話框已經(jīng)關(guān)閉,就不再繼續(xù)關(guān)閉對話框了。由于mShowing也是private變量,因此,也需要反射技術(shù)來設(shè)置這個變量。我們可以在對話框按鈕的單擊事件中設(shè)置mShowing,代碼如下:

try

{

Fieldfield=dialog.getClass()

.getSuperclass()。getDeclaredField;

field.setAccessible(true);

//

將mShowing變量設(shè)為false,表示對話框已關(guān)閉

field.set;

dialog.dismiss()

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論