Android 개발 노트: Dialog 사용 상세 정보

9057 단어 AndroidDialog
Dialog는 모든 시스템에 필요한 컨트롤러로 보조 창으로 메시지를 표시하거나 사용자에게 조작을 요청하는 데 사용됩니다.Android에서도 예외는 아닙니다. 기본 사용은 문서를 참조할 수 있습니다.사용 시 주의사항 1.BACK 키는 대화상자 (dismiss) 를 취소할 수 있지만, onOkey와 onCancel 리셋 인터페이스를 터치하지 않습니다. 따라서 대화상자가 어떤 상태를 바꿀 수 있다면 세 번째 방법으로 대화상자를 취소할 수 있습니다.2. Dialog의 경우 모드 대화상자(Model dialog)를 최대한 적게 사용합니다.setCancellable(false)은 프로그램 내부에서 Dismiss를 제외하고는 어떤 키를 눌러도 취소할 수 없는 모드 대화상자가 됩니다.이것은 매우 나쁜 사용자 체험이다. 대화상자 자체가 일종의 방해이기 때문에 더 이상 취소할 수 없으면 사용자를 미치게 할 것이다.따라서 특별히 필요하지 않으면, 어떤 조작을 실행할 때 깨지지 않기를 원할 때, 모드 대화상자를 사용할 수 있다.3. 사용자가 조작을 하거나 선택을 하지 않으면 사용자에게 방해가 된다.일반적인 일반적인 알림은 토스트나 Notification으로 충분합니다.4. 대화상자 스타일의 Activity를 사용하지 마십시오. 즉, Activity를 하나의 대화상자로 만듭니다.이것은 자신이 정의한 레이아웃이기 때문에 시스템 Dialog의 스타일과 일치하지 않을 수 있습니다.가장 심각한 것은 시스템 스타일이 바뀌면 Dialog의 하위 클래스가 변하지만 Activity식 대화상자는 변하지 않는다는 것이다.ICS에서 Activity 대화 상자를 찾으면 OK가 왼쪽이고 ICS에서 시스템 Dialog의 OK가 오른쪽에 있는 것을 발견할 수 있습니다.5. 가능한 한 Dialog 객체가 Activity 라이프 사이클 내에 있는지 확인합니다. 즉, 대부분 onCreate () 와 onDestroy () 사이입니다.6. Activity가 Dialog에 있다는 것을 생각하고 테스트해야 한다.dismiss () 전에 죽은 경우.Activity는 표시되고 있는 Activity 실례에 의존해야 하기 때문에, 표시되고 취소될 때 Activity 실례가 존재해야 합니다. 그렇지 않으면 "Illegal Argument Exception: View not attached to window manager"가 있습니다.

05-15 02:45:26.320: E/AndroidRuntime(1161): java.lang.IllegalArgumentException: View not attached to window manager
05-15 02:45:26.320: E/AndroidRuntime(1161):     at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:355)
05-15 02:45:26.320: E/AndroidRuntime(1161):     at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:200)
05-15 02:45:26.320: E/AndroidRuntime(1161):     at android.view.Window$LocalWindowManager.removeView(Window.java:432)
05-15 02:45:26.320: E/AndroidRuntime(1161):     at android.app.Dialog.dismissDialog(Dialog.java:278)
05-15 02:45:26.320: E/AndroidRuntime(1161):     at android.app.Dialog.access$000(Dialog.java:71)
05-15 02:45:26.320: E/AndroidRuntime(1161):     at android.app.Dialog$1.run(Dialog.java:111)
05-15 02:45:26.320: E/AndroidRuntime(1161):     at android.app.Dialog.dismiss(Dialog.java:268)
05-15 02:45:26.320: E/AndroidRuntime(1161):     at com.hilton.effectiveandroid.app.DialogDemo$1.handleMessage(DialogDemo.java:26)
05-15 02:45:26.320: E/AndroidRuntime(1161):     at android.os.Handler.dispatchMessage(Handler.java:99)
7. Dialog.show()는 주 스레드에서 호출되어야 하지만 Dialog.dismiss () 는 모든 라인에서 호출할 수 있습니다.세 가지 사용 방식 비교 1.부분적인 Dialog 대상을 직접 만드는 장점은 변수가 부분적인 이해와 유지보수가 쉽다는 것이다.단점은 Dialog 객체를 제어하기 어려워 Runtime Exception을 유발하기 쉽다는 것입니다.2. Dialog 객체를 Activity로 변환하는 도메인의 장점은 Dialog 객체를 재사용할 수 있고 Activity는 Dialog가 Activity 라이프 사이클 외부에 표시되지 않도록 제어할 수 있다는 것입니다.추천하는 사용법입니다.3. 액티비티의 방법으로 onCreate Dialog(), show Dialog(), dismiss Dialog()의 장점은 Frameworks가 Dialog를 돌볼 수 있도록 도와준다는 것이다. 대부분의 경우 추천하는 방법이다.그러나 액티비티가 조기 죽는 경우 이 방법은 반드시 Runtime Exception이 있고 피할 수 없다.인스턴스

public class DialogDemo extends Activity {
    private static final int DISMISS_DIALOG = 1;

    private ProgressDialog mBetterDialog;
    private Handler mMainHandler = new Handler() {
 @Override
 public void handleMessage(Message msg) {
     switch (msg.what) {
     case DISMISS_DIALOG:
  Dialog dialog = (Dialog) msg.obj;
  dialog.dismiss();
  break;
     default:
  break;
     }
 }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.dialog_demo);

 final Button sucking = (Button) findViewById(R.id.sucking);
 sucking.setOnClickListener(new View.OnClickListener() {
     public void onClick(View v) {
  final Activity activity = DialogDemo.this;
  final ProgressDialog dialog = new ProgressDialog(activity);
  dialog.setTitle("Worst dialogging");
  dialog.setMessage("This is the worst dialogging scheme, NEVER use it. This dialog is easy to " +
   "run out of its attached activity, yielding WindowManager#BadTokenException if the activity is gone when dismissing");
  dialog.setIndeterminate(true);
  dialog.setCancelable(true);
  // You MUST do the show in main thread anyway
  dialog.show();
  new Thread(new Runnable() {
      public void run() {
   SystemClock.sleep(10000);
   /*
    * IllegalArgumentException: View not attached to window manager
    * If the activity showing the dialog was killed before dismiss() out of rotation or locale changed,
    * the dialog will gone with activity, but when dismiss() yields "IllegalArgumentException: View not attached to
    * window manager".
    * Checking isShowing() won't help.
    * Checking activity.isFinishing() won't help, either.
    * Dismiss it in main thread also won't give any help.
    */
   // THIS WON't WORK
//   if (dialog.isShowing()) {
//       dialog.dismiss();
//   }
//   if (!activity.isFinishing()) {
//       dialog.dismiss();
//   }
   Message msg = Message.obtain();
   msg.what = DISMISS_DIALOG;
   msg.obj = dialog;
   mMainHandler.sendMessage(msg);
      }
  }).start();
     }
 });

 final Button better = (Button) findViewById(R.id.better);
 better.setOnClickListener(new View.OnClickListener() {
     public void onClick(View v) {
  mBetterDialog = new ProgressDialog(DialogDemo.this);
  mBetterDialog.setTitle("Better dialogging");
  mBetterDialog.setMessage("This dialogging can be used. The dialog object is a field of its activity, so activity can" +
    " control it to make sure dialog only lives within activity lifecircle");
  mBetterDialog.setIndeterminate(true);
  mBetterDialog.setCancelable(true);
  // You MUST do the show in main thread anyway
  mBetterDialog.show();
  new Thread(new Runnable() {
      public void run() {
   SystemClock.sleep(10000);
   /*
    * This is much better, mBetterDialog is a field of its activity, so activity can take care of it in order
    * to make sure dialog only live within activity's life circle, to avoid any unexpected exceptions.
    */
   // THIS really works
       if (mBetterDialog != null && mBetterDialog.isShowing()) {
           mBetterDialog.dismiss();
       }
      }
  }).start();
     }
 });

 final Button optional = (Button) findViewById(R.id.optional);
 optional.setOnClickListener(new View.OnClickListener() {
     @SuppressWarnings("deprecation")
     public void onClick(View v) {
  showDialog(0);
  new Thread(new Runnable() {
      public void run() {
   SystemClock.sleep(10000);
   /*
    * This way works best for most of time, except if activity died before dismissing, exception must be
    * thrown: "IllegalArgumentException: View not attached to window manager".
    * Although activity takes care of its belonging dialog, there is no way to operate it manually any more.
    * First you do not have reference to dialog object and second, any manual operation only interferences
    * and breaks state maintained by frameworks.
    */
   dismissDialog(0);
      }
  }).start();
     }
 });
    }
    @Override
    protected Dialog onCreateDialog(int id) {
 ProgressDialog d = new ProgressDialog(this);
 d.setTitle("Optional dialogging");
 d.setMessage("This dialogging scheme works best for most times, the dialogs are all taken care of by activitys and frameworks" +
   ". Except for activity being killed during dialog showing");
 d.setIndeterminate(true);
 d.setCancelable(true);
 return d;
    }
    @Override
    protected void onDestroy() {
 super.onDestroy();
 // Activity is dying, all its belonging dialogs should be dismissed, of course.
 if (mBetterDialog != null && mBetterDialog.isShowing()) {
     mBetterDialog.dismiss();
     mBetterDialog = null;
 }
 // For dialogs showed via showDialog(int), no way to stop it in onDestroy()
// dismissDialog(0); // cause "IllegalArgumentException: no dialog with id 0 was ever shown via Activity#showDialog"
       // This is because Activity has to manage its dialog during onPause() and onResume() to restore
                   // dialogs' state. So if you manually dismiss it in onDestroy(), it will cause JE.

// removeDialog(0);// cause "IllegalArgumentException: no dialog with id 0 was ever shown via Activity#showDialog", when
   // dismissing in thread.
               // This is because Activity has to manage its dialog during onPause() and onResume() to restore
                     // dialogs' state. So if you manually dismiss it in onDestroy(), it will cause JE.
    }
}

좋은 웹페이지 즐겨찾기