Android解決dialogとpopupwindowのBadTokenException:Unable to add window


例:今日、会社のプロジェクトBUGを修正しました.アプリのトップページに入る効果があります.アプリはポップアップ広告を出します.広告内容はリアルタイムでサーバーから取得します.ではショーを始めたdialogやpopupwindowにBadTokenExceptionが現れます.
異常情報:android.view.WindowManager&BadTokenException:Unable to add windowこのエラーはreference on a null performanceと言います
       
正しく異常が発生した原因:
        1.dialogとpopupwindowはactivityに依存するため、dialogとpopupwindowはshowの前にactivityのインスタンスが存在し、破棄できない.
        2.スレッドを開いてネットワークに接続するための時間がかかるため、時間がかかる操作が完了してからshowdialogとpopupwindow.ユーザが実際に操作する場合、dialogとpopupwindowがshowの前にページジャンプを行い、前の依存activityインスタンスを破棄する可能性が高い.showdialogで誤報を招いた.
そのため、解決の構想は明らかになった.それはactivityfinishでジャンプしている間にonDestroyの中でkillprogess();すなわち、プロセス下のすべてのスレッドを殺す.
解決方法:1.ネット上でスレッドを殺す方法を見た.多くの人が言っていますos.Process.killProcess(android.os.Process.myPid());この方法は現在のすべてのプロセスとスレッドを殺すことです.直接コードをつけて、ジャンプする时直接全杀して、onDestroyの时にジャンプを実现します.
筆者は、ジャンプ前とジャンプ後にスレッドを殺すにしても、アプリ全体が閉じることを考えただけだからだ.このようにしてこそ、ジャンプの効果を殺すことができる.
しかし、このようにするのはとてもよくありません.第一.ユーザー体験が悪く、ジャンプすると一瞬の黒い画面が表示されます.第二に、ジャンプが完了した後、前に誤殺されたバックグラウンドを走るスレッドの再起動の問題も考えなければなりません.バックグラウンドに長い接続が必要なアプリであれば、性能に影響し、効果が低いので、かなりお勧めしません.まるで人を誤解させるようだ.
         
protected void killprogess() {
		android.os.Process.killProcess(android.os.Process.myPid());
	}

@Override
	protected void onDestroy() {
		super.onDestroy();
		startActivity(new Intent(MainActivity.this, SecondActivity.class));
		finish();
	}
           2
第二の方法は、筆者が総合的に考えた結果、やはり適切だと思う.この方法をお勧めします.主にメインスレッドのhandlerを通じてremoveに行って現在走っているrunnableを落とす.このようにして連帯の影響がなくて、直接コードをつけて、とても簡単で、みんなが理解できると信じています.説明しない
/**
 *           ,          .
 * --------------       ,               ,   APP      ,           ,              ------
 *       ,  activity     ,      
 *        ,   handler.removeCallbacks       
 * @author max
 *
 */
public class MainActivity extends Activity {
	private static final String TAG = "com.max.threadshutdowndemo";
	private Handler mHandler = new Handler();
	Runnable runnable = new Runnable() {
		
		@Override
		public void run() {
			//       dialog
			showAD();
		}
	};
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		//  postdelayed              
		mHandler.postDelayed(runnable, 3000);
		Button button = (Button) findViewById(R.id.first_button);
		//              ,       .        activity   ,   ,        
		button.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				killprogess();
			}
		});
	}

	/**
	 *      ,              
	 */
	protected void killprogess() {
		startActivity(new Intent(MainActivity.this, SecondActivity.class));
		finish();
	}

	/**
	 *     dialog  popupwindow
	 *               thread          
	 *        postDelayed       
	 */
	protected void showAD() {
		//        ,   try catch    ,    ,    remove    ,       .           
		try {
			Dialog dialog = new AlertDialog.Builder(MainActivity.this).create();
			dialog.show();
			dialog.setCanceledOnTouchOutside(false);
			Window window = dialog.getWindow();
			window.setContentView(R.layout.dialog_main);
		} catch (Exception e) {
			Log.e(TAG, e.getMessage());
			e.printStackTrace();
		}
	}

	/**
	 *  ondestroy           
	 */
	@Override
	protected void onDestroy() {
		super.onDestroy();
		//         .
//		android.os.Process.killProcess(android.os.Process.myPid());
		//     ,    finish   ,          ,      .
		//    try catch      crash 
		mHandler.removeCallbacks(runnable);
	}
}

最后にソースコードで、効果は私はスクリーンショットをしないで、こちらは兴味のある童靴があって、ソースコードを降りて自分で浸してもいいです.ソースコードのダウンロードはこちらをクリックしてください.