日韩欧美自拍在线观看-欧美精品在线看片一区二区-高清性视频一区二区播放-欧美日韩女优制服另类-国产精品久久久久久av蜜臀-成人在线黄色av网站-肥臀熟妇一区二区三区-亚洲视频在线播放老色-在线成人激情自拍视频

Android系統(tǒng)原理與源碼分析方案

出處:awey 發(fā)布于:2011-09-03 20:44:44

  本文以下就是如何隨心所欲地控制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)在Android SDK寫死了,并且未給使用者留有任何接口。但我的座右銘是“宇宙中沒有什么是不能控制的”。

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

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

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

  View.OnClickListener mButtonHandler = new View.OnClickListener() {

  public void onClick{

  Message m = null;

  if  {

  m = Message.obtain;

  } else if  {

  m = Message.obtain;

  } else if  {

  m = Message.obtain;

  }

  if  {

  m.sendToTarget();

  }

  // Post a message so we dismiss after the above handlers are executed

  mHandler.obtainMessage

  .sendToTarget();

  }

  };

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

  mHandler.obtainMessage

  .sendToTarget();

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

  private stATIc final class ButtonHandler extends Handler {

  // Button clicks have Message.what as the BUTTON{1,2,3} constant

  private staTIc final int MSG_DISMISS_DIALOG = 1;

  private WeakReference《DialogInterface》 mDialog;

  public ButtonHandler {

  mDialog = new WeakReference《DialogInterface》;

  }

  @Override

  public void handleMessage {

  switch  {

  case DialogInterface.BUTTON_POSITIVE:

  case DialogInterface.BUTTON_NEGATIVE:

  case DialogInterface.BUTTON_NEUTRAL:

 ?。ǎ―ialogInterface.OnClickListener) msg.obj)。onClick(mDialog.get(), msg.what);

  break;

  case MSG_DISMISS_DIALOG:

 ?。ǎ―ialogInterface) msg.obj)。dismiss();

  }

  }

  }

  從上面代碼的可以找到

 ?。ǎ―ialogInterface) 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類。

  class ButtonHandler extends Handler

  {

  private WeakReference《DialogInterface》 mDialog;

  public ButtonHandler

  {

  mDialog = new WeakReference《DialogInterface》;

  }

  @Override

  public

  void handleMessage

  {

  switch

  {

  case DialogInterface.BUTTON_POSITIVE:

  case DialogInterface.BUTTON_NEGATIVE:

  case DialogInterface.BUTTON_NEUTRAL:

 ?。ǎ―ialogInterface.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對象

  AlertDialog alertDialog = new AlertDialog.Builder

  .setTitle

  .setMessage

  .setIcon

  .setPositiveButton

  new OnClickListener()

  {

  @Override

  public void onClick

  {

  }

  })。setNegativeButton()

  {

  @Override

  public void onClick

  {

  dialog.dismiss();

  }

  })。create();

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

  try

  {

  Field field = alertDialog1.getClass()。getDeclaredField;

  field.setAccessible;

  //

  獲得mAlert變量的值

  Object obj = 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

  void dismissDialog() {

  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

  {

  Field field = dialog.getClass()

  .getSuperclass()。getDeclaredField;

  field.setAccessible(true);

  //

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

  field.set;

  dialog.dismiss();

  }

  catch

  {

  }

  將上面的代碼加到哪個按鈕的單擊事件代碼中,哪個按鈕就再也無法關(guān)閉對話框了。如果要關(guān)閉對話框,只需再將mShowing設(shè)為true即可。要注意的是,在一個按鈕里設(shè)置了mShowing變量,也會影響另一個按鈕的關(guān)閉對話框功能,因此,需要在每一個按鈕的單擊事件里都設(shè)置mShowing變量的值。



  
關(guān)鍵詞:Android

版權(quán)與免責(zé)聲明

凡本網(wǎng)注明“出處:維庫電子市場網(wǎng)”的所有作品,版權(quán)均屬于維庫電子市場網(wǎng),轉(zhuǎn)載請必須注明維庫電子市場網(wǎng),http://www.hbjingang.com,違反者本網(wǎng)將追究相關(guān)法律責(zé)任。

本網(wǎng)轉(zhuǎn)載并注明自其它出處的作品,目的在于傳遞更多信息,并不代表本網(wǎng)贊同其觀點或證實其內(nèi)容的真實性,不承擔(dān)此類作品侵權(quán)行為的直接責(zé)任及連帶責(zé)任。其他媒體、網(wǎng)站或個人從本網(wǎng)轉(zhuǎn)載時,必須保留本網(wǎng)注明的作品出處,并自負(fù)版權(quán)等法律責(zé)任。

如涉及作品內(nèi)容、版權(quán)等問題,請在作品發(fā)表之日起一周內(nèi)與本網(wǎng)聯(lián)系,否則視為放棄相關(guān)權(quán)利。

廣告
OEM清單文件: OEM清單文件
*公司名:
*聯(lián)系人:
*手機(jī)號碼:
QQ:
有效期:

掃碼下載APP,
一鍵連接廣大的電子世界。

在線人工客服

買家服務(wù):
賣家服務(wù):
技術(shù)客服:

0571-85317607

網(wǎng)站技術(shù)支持

13606545031

客服在線時間周一至周五
9:00-17:30

關(guān)注官方微信號,
第一時間獲取資訊。

建議反饋

聯(lián)系人:

聯(lián)系方式:

按住滑塊,拖拽到最右邊
>>
感謝您向阿庫提出的寶貴意見,您的參與是維庫提升服務(wù)的動力!意見一經(jīng)采納,將有感恩紅包奉上哦!