Search code examples
javaandroidmultithreadingandroid-activitycommunication

How to communicate between Activity and Threads created by other Actvity


When you have 2 activities ( A and B ) and A is the MainActivity, now you start your App and A starts B. B is a activity with a Dialog interacting with the user, creating a Bluetooth Connection and 2 Threads, 1 Receiving and one Sending. Now, what is the best way to send the Information from A to the threads of B and the other way round? Look here.

First I used a static WeakReference, but I heard this causes a lot of problems, so I want to ask for a more common solution.

Please keep in mind, when starting an Activity from another Activity, you can only pass Serializable Objs and simple data. So it is not possible to use a Handler that way.

Here is the static WeakReference I used:

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;
}

}

Here is a way to look for a running Thread in the stack:

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

Also possible solution:

public class example extends Thread {
    private static example instance;

  private example() {
  }

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

    return instance;
  }
}

Solution

  • A WeakReference probably isn't what you want, here. That is, presuming that your Thread object either does not terminate, or somehow maintains some information useful to Activity A after Activity B has stopped. If you use a WeakReference, it might become "null" as soon as Activity B ends, and the thread terminates. Just use regular old strong references. It'll ensure T1, and the information contains, continues to exist until you're done with it.

    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.
            }
        }
    }