但是子线程中真的不能间接表示Toast吗?

  

  谜底是:固然大要。

  

  那理当怎么垄断呢?在之后线程中先初始化一个Looper便可!

  

  Looper.prepare();

  

  Toast.makeText(getBaseContext(), "text", Toast.LENGTH_LONG).show();

  

  Looper.loop();

  

  为甚么在子线程中把持Toast必要初始一个Looper呢? 咱们看看源代码:

  

  public static Toast makeText(Context context, CharSequence text, @Duration int duration) {

  

  return makeText(context, null, text, duration);

  

  }

  

  public static Toast makeText(@NonNull Context context, @Nullable Looper looper,

  

  @NonNull CharSequence text, @Duration int duration) {

博客  

  Toast result=new Toast(context, looper);

  

  ...

  

  return result;

  

  }

  

  以上是咱们把持Toast时调用的动态方法,大要看到第2个方法有个参数Looper,诚然咱们日常平凡用的时分都传入的是null,那这个Looper究竟后果有甚么用呢?咱们看看Toast的布局函数:

  

  public Toast(@NonNull Context context, @Nullable Looper looper) {

  

  mContext=context;

  

  mTN=new TN(context.getPackageName(), looper);

  

  }

  

  大要看出这个Looper其实是TN在用,咱们看看它的布局函数:

  

  TN(String packageName, @Nullable Looper looper) {

  

  if (looper==null) {

  

  // Use Looper.myLooper() if looper is not specified.

  

  looper=Looper.myLooper();

  

  if (looper==null) {

  

  throw new RuntimeException(

  

  "Can"t toast on a thread that has not called Looper.prepare()");

  

  }

  

  }

  

  }

  

  以上代码有简化。大要看出当Looper为null的时分,会通过Looper.myLooper得到一个之后的Looper。咱们知道在主线程中琐屑曾经为咱们初始化了一个mainLooper,所以咱们集体不必管。但是当咱们子线程中如果不有初始化Looper,这里调用Looper.myLooper就得到不到一个Looper,则会抛出极其。所以当咱们在子线程中把持Toast,把持Looper.prepare()方法初始化一个Looper并用Looper.loop()让它发动起来便可。

  

  所以咱们大要封装一个大要在任何线程把持的Toast。

  

  private static Toast toast=null;

  

  public static void showToast(Context context, String text) {

  

  Looper myLooper=Looper.myLooper();

  

  if (myLooper==null) {

  

  Looper.prepare();

  

  myLooper=Looper.myLooper();

  

  }

  

  if (toast==null) {

  

  toast=Toast.makeText(context, text, Toast.LENGTH_LONG);

  

  toast.setGravity(Gravity.CENTER, 0, 0);

  

  }

  

  toast.show();

  

  if ( myLooper !=null) {

  

  Looper.loop();

  

  myLooper.quit();

  

  }

  

  }

  

  咱们初始化Toast畴昔先果断之后线程的looper可否为空,为空则初始化一个新的myLooper,此后在调用Toast的show方法之后让looper发动起来便可。因为Looper的loop()方法是无量循环的,为了灌注贯注Looper壅闭线程,导致内存透露理当实时加入Looper。

  

  写在末端

  

  在子线程中直接使用 Toast 及其原理

  

  更多存眷微信公众号:jiuwenwang