7.x Android traitement Toast BadTokenException

version 7.x de Toast ajouté authentification par jeton, cela est correct, mais l'appel à show () est affiché Toast, s'il est coincé le thread principal opération de temps sur cinq secondes, il lancera une BadTokenException d'exception, et système 8.x départ, Google est menée dans le try-catch. Et le système 7.x est une douleur permanente, ne peut compter que sur notre propre pour réparer le.

 

Un programme de réhabilitation

Agent View, contexte de réflexion, réalisée dans le contexte try-catch, traitement de problème de BadTokenException de Toast

  • BadTokenListener, Toast jeter auditeurs BadTokenException
public interface BadTokenListener {
    /** * 当Toast抛出BadTokenException时回调 * * @param toast 发生异常的Toast实例 */ void onBadTokenCaught(@NonNull Toast toast); } 
  • SafeToastContext, enveloppé utilisation Toast du contexte
public class SafeToastContext extends ContextWrapper { private Toast mToast; private BadTokenListener mBadTokenListener; public SafeToastContext(Context base, Toast toast) { super(base); mToast = toast; } public void setBadTokenListener(@NonNull BadTokenListener badTokenListener) { mBadTokenListener = badTokenListener; } @Override public Context getApplicationContext() { //代理原本的Context return new ApplicationContextWrapper(super.getApplicationContext()); } private class ApplicationContextWrapper extends ContextWrapper { public ApplicationContextWrapper(Context base) { super(base); } @Override public Object getSystemService(String name) { if (Context.WINDOW_SERVICE.equals(name)) { //获取原来的WindowManager,交给WindowManagerWrapper代理,捕获BadTokenException异常 Context baseContext = getBaseContext(); return new WindowManagerWrapper((WindowManager) baseContext.getSystemService(name)); } return super.getSystemService(name); } } private class WindowManagerWrapper implements WindowManager { /** * 被包裹的WindowManager实例 */ private WindowManager mImpl; public WindowManagerWrapper(@NonNull WindowManager readImpl) { mImpl = readImpl; } @Override public Display getDefaultDisplay() { return mImpl.getDefaultDisplay(); } @Override public void removeViewImmediate(View view) { mImpl.removeViewImmediate(view); } @Override public void addView(View view, ViewGroup.LayoutParams params) { //在addView动刀,捕获BadTokenException异常 try { mImpl.addView(view, params); } catch (BadTokenException e) { e.printStackTrace(); if (mBadTokenListener != null) { mBadTokenListener.onBadTokenCaught(mToast); } } } @Override public void updateViewLayout(View view, ViewGroup.LayoutParams params) { mImpl.updateViewLayout(view, params); } @Override public void removeView(View view) { mImpl.removeView(view); } } } 
  • ToastCompat, alternative façade Toast
public class ToastCompat extends Toast {
    private Toast mToast; public ToastCompat(Context context, Toast toast) { super(context); mToast = toast; } public static ToastCompat makeText(Context context, CharSequence text, int duration) { @SuppressLint("ShowToast") Toast toast = Toast.makeText(context, text, duration); setContextCompat(toast.getView(), context); return new ToastCompat(context, toast); } public static Toast makeText(Context context, @StringRes int resId, int duration) throws Resources.NotFoundException { return makeText(context, context.getResources().getText(resId), duration); } public @NonNull ToastCompat setBadTokenListener(@NonNull BadTokenListener listener) { final Context context = getView().getContext(); if (context instanceof SafeToastContext) { ((SafeToastContext) context).setBadTokenListener(listener); } return this; } @Override public void show() { mToast.show(); } @Override public void setDuration(int duration) { mToast.setDuration(duration); } @Override public void setGravity(int gravity, int xOffset, int yOffset) { mToast.setGravity(gravity, xOffset, yOffset); } @Override public void setMargin(float horizontalMargin, float verticalMargin) { mToast.setMargin(horizontalMargin, verticalMargin); } @Override public void setText(int resId) { mToast.setText(resId); } @Override public void setText(CharSequence s) { mToast.setText(s); } @Override public void setView(View view) { mToast.setView(view); setContextCompat(view, new SafeToastContext(view.getContext(), this)); } @Override public float getHorizontalMargin() { return mToast.getHorizontalMargin(); } @Override public float getVerticalMargin() { return mToast.getVerticalMargin(); } @Override public int getDuration() { return mToast.getDuration(); } @Override public int getGravity() { return mToast.getGravity(); } @Override public int getXOffset() { return mToast.getXOffset(); } @Override public int getYOffset() { return mToast.getYOffset(); } @Override public View getView() { return mToast.getView(); } @NonNull public Toast getBaseToast() { return mToast; } /** * 反射设置View中的Context,Toast会获取View的Context来获取WindowManager */ private static void setContextCompat(@NonNull View view, @NonNull Context context) { //7.1.1版本才进行处理 if (Build.VERSION.SDK_INT == 25) { try { Field field = View.class.getDeclaredField("mContext"); field.setAccessible(true); field.set(view, context); } catch (Throwable e) { e.printStackTrace(); } } } } 
  • Au lieu d'utiliser ToastCompat Toast
ToastCompat.makeText(context,"我是Toast的内容", Toast.LENGTH_SHORT) .setBadTokenListener(toast -> Logger.d("Toast:" + toast + " => 抛出BadTokenException异常") ) .show(); 

Réparation Option II

Toast Handler pour être crochet, le remplacement Toast dans l'objet TN pour distribuer des messages DispatchMessage () méthode try-catch

public class SafeToast {
    private static Field sField_TN; private static Field sField_TN_Handler; static { try { //反射获取TN对象 sField_TN = Toast.class.getDeclaredField("mTN"); sField_TN.setAccessible(true); sField_TN_Handler = sField_TN.getType().getDeclaredField("mHandler"); sField_TN_Handler.setAccessible(true); } catch (Exception e) { e.printStackTrace(); } } private SafeToast() { } @SuppressLint("ShowToast") public static void show(Context context, CharSequence message, int duration) { show(context, message, duration, null); } @SuppressLint("ShowToast") public static void show(Context context, CharSequence message, int duration, BadTokenListener badTokenListener) { Toast toast = Toast.makeText(context.getApplicationContext(), message, duration); hook(toast, badTokenListener); toast.setDuration(duration); toast.setText(message); toast.show(); } @SuppressLint("ShowToast") public static void show(Context context, @StringRes int resId, int duration) { show(context, resId, duration, null); } @SuppressLint("ShowToast") public static void show(Context context, @StringRes int resId, int duration, BadTokenListener badTokenListener) { Toast toast = Toast.makeText(context.getApplicationContext(), resId, duration); hook(toast, badTokenListener); toast.setDuration(duration); toast.setText(context.getString(resId)); toast.show(); } private static void hook(Toast toast, BadTokenListener badTokenListener) { try { Object tn = sField_TN.get(toast); Handler originHandler = (Handler) sField_TN_Handler.get(tn); sField_TN_Handler.set(tn, new SafeHandler(toast, originHandler, badTokenListener)); } catch (Throwable e) { e.printStackTrace(); } } /** * 替换Toast原有的Handler */ private static class SafeHandler extends Handler { private Toast mToast; private Handler mOriginImpl; private BadTokenListener mBadTokenListener; SafeHandler(Toast toast, Handler originHandler, BadTokenListener badTokenListener) { mToast = toast; mOriginImpl = originHandler; mBadTokenListener = badTokenListener; } @Override public void dispatchMessage(Message msg) { //对分发Message的处理方法进行try-catch try { super.dispatchMessage(msg); } catch (WindowManager.BadTokenException e) { e.printStackTrace(); if (mBadTokenListener != null) { mBadTokenListener.onBadTokenCaught(mToast); } } } @Override public void handleMessage(Message msg) { //需要委托给原Handler执行 mOriginImpl.handleMessage(msg); } } } 
  • Au lieu d'utiliser SafeToast Toast
SafeToast.show(context,"我是Toast的内容", Toast.LENGTH_SHORT, toast -> Logger.d("Toast:" + toast + " => 抛出BadTokenException异常")); 

Auteur: Il aime écrire du code Sorgho
lien: https://www.jianshu.com/p/256103c59d45

Je suppose que tu aimes

Origine www.cnblogs.com/Android-Alvin/p/12450884.html
conseillé
Classement