解決android中出現(xiàn)的“android.view.WindowManager$BadTokenException: Unable to add window -- token”問(wèn)題

image.png

Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@2c888438 is not valid; is your activity running?
按照字面上意思是:你的activity活動(dòng)已經(jīng)銷毀了,但是你的Dialog之類的window還在運(yùn)行,因?yàn)檫@些window的運(yùn)行需要依附在activity活動(dòng)上

看log定位錯(cuò)誤信息

image.png

很明顯就是在show Dialog的時(shí)候報(bào)錯(cuò)了

接著查看一下Dialog的代碼

public abstract class BaseAlertDialog extends AlertDialog implements View.OnClickListener {

   protected View.OnClickListener mClickListener;
   protected View.OnClickListener mLeftListener;
   protected View.OnClickListener mRightListener;
   protected Object mDialogTitle;
   protected Object mDialogContent;
   protected Object mSingleBtn;
   protected Object mComplexLeftBtn;
   protected Object mComplexRightBtn;

   public BaseAlertDialog(@NonNull Context context) {
       super(context, R.style.style_dialog);
   }

   /**
    * 設(shè)置布局資源ID
    * @return 布局資源ID
    */
   protected abstract int getLayoutResId();

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setCanceledOnTouchOutside(false);
       if (getLayoutResId() != 0) {
           setContentView(getLayoutResId());
           initView();
       }
   }

   /**
    * 初始化控件
    */
   protected abstract void initView();

   /**
    * 設(shè)置彈框標(biāo)題
    * @param dialogTitle 彈框標(biāo)題內(nèi)容
    */
   public void setDialogTitle(Object dialogTitle) {
       this.mDialogTitle = dialogTitle;
   }

   /**
    * 設(shè)置彈框內(nèi)容
    * @param dialogContent 彈框顯示內(nèi)容
    */
   public void setDialogContent(Object dialogContent) {
       this.mDialogContent = dialogContent;
   }

   public void setDialogContent(Object dialogContent,Object dialogContentStr) {
       this.mDialogContent = dialogContent;
   }

   @SuppressWarnings("unchecked")
   protected  <T extends View> T xFindViewById(int resourceId) {
       return (T) findViewById(resourceId);
   }

   @Override
   public boolean onKeyDown(int keyCode, KeyEvent event) {
       return keyCode == KeyEvent.KEYCODE_BACK || super.onKeyDown(keyCode, event);
   }

   @Override
   public void onClick(View view) {

   }
}

這里只是最基本的Dialog的基類,也沒(méi)什么好說(shuō),接著看它的實(shí)現(xiàn)類

public class SingleBtnDialog extends BaseAlertDialog {

    public SingleBtnDialog(@NonNull Context context) {
        super(context);
    }

    /**
     * 設(shè)置按鈕監(jiān)聽(tīng)
     * @param listener 自定義監(jiān)聽(tīng)
     */
    public void setOnClickListener(View.OnClickListener listener) {
        this.mClickListener = listener;
    }

    /**
     * 設(shè)置按鈕內(nèi)容
     * @param singleBtnObj 按鈕顯示內(nèi)容
     */
    public void setSingleBtn(Object singleBtnObj) {
        this.mSingleBtn = singleBtnObj;
    }

    @Override
    protected int getLayoutResId() {
        return R.layout.dialog_single_btn_layout;
    }

    @Override
    protected void initView() {
        TextView tvDialogTitle = xFindViewById(R.id.tv_dialog_content_title);
        ViewUtils.loadContent(tvDialogTitle, mDialogTitle);
        TextView tvDialogContent = xFindViewById(R.id.tv_dialog_content);
        ViewUtils.loadContent(tvDialogContent, mDialogContent);

        Button btnSingleOption = xFindViewById(R.id.btn_dialog_single_option);
        ViewUtils.loadContent(btnSingleOption, mSingleBtn);
        if (mClickListener != null) {
            btnSingleOption.setOnClickListener(mClickListener);
        } else {
            btnSingleOption.setOnClickListener(this);
        }
    }

    @Override
    public void onClick(View view) {
        this.cancel();
        this.dismiss();
    }
}

好像也看出有什么問(wèn)題,那接下來(lái)就看它的調(diào)用

 public void showFinishActSingleBtnDialog(String content){
        if (singleBtnDialog == null){
            singleBtnDialog = new SingleBtnDialog(getActivity());
        }
        singleBtnDialog.setDialogContent(content);
        singleBtnDialog.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getActivity().finish();
            }
        });
        singleBtnDialog.show();
    }

    public void showFinishActSingleBtnDialog(int contentId){
        showFinishActSingleBtnDialog(getString(contentId));
    }

可以看出沒(méi)有對(duì)activity是否還在運(yùn)行做判斷,修改如下:

 public void showFinishActSingleBtnDialog(String content){
        if (singleBtnDialog != null && singleBtnDialog.isShowing()){
            singleBtnDialog.dismiss();
            singleBtnDialog = null;
        }
        if (!getActivity().isFinishing()){
            final SingleBtnDialog singleBtnDialog = new SingleBtnDialog(getActivity());
            singleBtnDialog.setDialogContent(content);
            singleBtnDialog.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    getActivity().finish();
                }
            });
            singleBtnDialog.show();
        }

//        if (singleBtnDialog == null){
//            singleBtnDialog = new SingleBtnDialog(getActivity());
//        }
//        singleBtnDialog.setDialogContent(content);
//        singleBtnDialog.setOnClickListener(new View.OnClickListener() {
//            @Override
//            public void onClick(View v) {
//                getActivity().finish();
//            }
//        });
//        singleBtnDialog.show();
    }

對(duì)activity是否在運(yùn)行判斷了一下,然后重新賦值就可以了

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容