Activity与其他Activity创建的线程之间如何通信

Posted

技术标签:

【中文标题】Activity与其他Activity创建的线程之间如何通信【英文标题】:How to communicate between Activity and Threads created by other Actvity 【发布时间】:2019-12-11 16:52:18 【问题描述】:

当您有 2 个活动( A 和 B )并且 A 是 MainActivity 时,现在您启动您的应用程序并且 A 启动 B。 B 是一个 Dialog 与用户交互的活动,创建一个蓝牙连接和 2 个线程,1 个接收和一个发送。 现在,将信息从 A 发送到 B 的线程的最佳方式是什么,反之亦然?

一开始我用的是静态的WeakReference,但是听说这会导致很多问题,所以想求一个更通用的解决方案。

请记住,当从另一个 Activity 启动一个 Activity 时,您只能传递 Serializable Objs 和简单数据。所以不可能那样使用Handler。

这是我使用的静态 WeakReference:

public class T1 extends Thread
private static WeakReference<T1> weak_T1;


public void T1 ()
weak_T1 = new WeakReference<T1> (This);


public static WeakReference getWeakReverence() 
    return weak_T1;



这是一种在堆栈中查找正在运行的线程的方法:

for (Thread thread : Thread.getAllStackTraces().keySet())  
    if (thread.getName().equalsIgnoreCase("T1")) 
    T1A =thread; 
     else if (thread.getName().equalsIgnoreCase("T2")) 
     T2A =thread; 
      

也可能的解决方案:

public class example extends Thread 
    private static example instance;

  private example() 
  

  public static example getIsntance()
    if(instance == null)
      instance = new example();
    

    return instance;
  

【问题讨论】:

只是好奇,如何防止系统在 Activity B 显示时破坏 Activity A? @greeble31 A 是 B 的父级,所以 A 只是 onPause 而不是 onDestroy。或者也许我不明白你的问题,但为什么 A 应该被破坏? @greeble31 明确一点,线程启动后,活动 B 完成,A 再次处于前台。 我的意思是,你不能保证活动 A 保持在“暂停”状态(或者实际上是“停止/隐藏”,在这种情况下,状态)任何长度时间。正如docs 中提到的,停止的活动“......当其他地方需要内存时,通常会被系统杀死”。尝试与屏幕外 Activity 进行通信是不行的。您需要将线程结果保存在某处(例如 Service 甚至静态引用),然后让 Activity A 在恢复后获取该信息。 您如何看待“get Thread in Stack”解决方案?风险是得到一个空指针异常,但我想不出其他问题。 【参考方案1】:

WeakReference 可能不是您想要的,在这里。也就是说,假设您的 Thread 对象要么没有终止,要么在 Activity B 停止后以某种方式维护一些对 Activity A 有用的信息。如果您使用WeakReference,它可能会在活动 B 结束后立即变为“null”,并且线程终止。只需使用常规的旧强引用。它将确保 T1 和包含的信息继续存在,直到您完成它为止。

public class ActivityB extends Activity

    private T1 t1;
    @Override
    public void onCreate(Bundle savedInstanceState)
    
        super.onCreate(savedInstanceState);
        t1 = startMyThread();
    

    @Override
    public void onBackPressed()
    
        ActivityA.tempT1 = t1;

        //This technique presumes that Activity A is guaranteed to resume after a 
        //back button press, based on the arrangement of your backstack, etc. If
        //Activity A is started via some other means (e.g., an explicit startActivity(),
        //finish(), etc.), then this reference will have to be set prior to
        //that call, as well, in order to establish the appropriate "happens before" relationship.
        //If you fail to ensure that Activity A resumes after this point, you will
        //risk a memory leak.

        super.onBackPressed();
    


public class ActivityA extends Activity

    public static T1 tempT1 = null;
    private T1 t1;

    @Override
    public void onResume()
    
        super.onResume();
        if(tempT1 == null)
        
            //Apparently, Activity B hasn't executed yet. Provide the user with a button to start it.
        
        else
        
            t1 = tempT1;
            tempT1 = null;     //To avoid a memory leak

            //We just retrieved the reference that Activity B left for us.
            //Now, change UI states so that the user can see information about t1.
        
    

【讨论】:

由于每个活动都通过 onResume() 我们可以通过这种方式在活动之间传递几乎所有内容吗?例如处理程序。 是的,我个人从不这样做(我使用Service b/c,因为其他原因需要它)但只要你能建立“发生在之前”的关系,这是安全的。 感谢您的帮助。祝你有美好的一天。 只是为了完成这个:如果我们在 Manifest 中设置一个 ParentActivity,我们可以确定,在 Activity B 完成后,哪个 Activity 将被启动(恢复或创建)。 look at android:parentActivityName 您能否添加一个示例,如何从 A 创建后台服务(任何扩展 Service.class)以及如何将 A 和 B 绑定到它?我知道你已经回答了这个问题,但这真的很有帮助:)

以上是关于Activity与其他Activity创建的线程之间如何通信的主要内容,如果未能解决你的问题,请参考以下文章

Android四大组件之Activity(活动)及其布局的创建与加载布局

Android开发之Activity的创建跳转及传值

Android 插件化Hook 插件化框架 ( Hook Activity 启动流程 | 主线程创建 Activity 实例之前使用插件 Activity 类替换占位的组件 )

Android开发之Activity的创建跳转及传值

Activity四种启动模式

7) 十分钟学会android--Activity的生命周期之暂停与恢复