How to pass data from a non-activity class to an a

2019-07-21 00:21发布

问题:

I'm building my app and I'm using socket.io to communicate with a webserver. I have java files that take care of that which are not activities and run in the background. So to start them, it will be instantiated in an activity and the sockets will run. Now the webserver triggers messages which I handle in the callback and pass the data to an activity. Now I'm looking for the best way to pass data from a running non-activity class to an activity currently running.

What I did before was using an intent created by the non-activity class which sent the data to the currently running activity. The actvity had to be changed to singleinstance or singletop to avoid the activity from keeping on restarting on itself. The problem is that form my main actvity I can't use single top launchmode because I need the actvity to refresh on itself in some instances.

So I can't get the sockets properly working on the main activity because I can only recieve data if I change my main activity to singletop which is not ideal for the app. I had first tried nameing a function in the acivity that would be called by the non-activity class but it seems that, that's illegal, so I'm pretty stuck here.

@Override
    public void on(String event, IOAcknowledge ack, Object... data) {

        System.out.println("Server may have triggered event '" + event + "'");

        if (event.equals("message")) {
        System.out.println(data[2]);

        Intent newIntent = new Intent(Chat.mContent, Chat.class);
        Bundle extras=new Bundle();
        extras.putString("name", (String)data[1]);
        extras.putString("MSG", (String)data[2]);
        newIntent.putExtras(extras);


        Chat.mContent.startActivity(newIntent);

        }
        if (event.equals("ready")) {
            System.out.println("Received the ready callback");
            try{
            Intent newIntent = new Intent(TabExercise.mContext, TabExercise.class);
            newIntent.putExtra("ready", event);
            TabExercise.mContext.startActivity(newIntent);
            }catch(Exception e){
                System.out.println("Caught an error");
            }


        }
    }

This is the method in the non-activity class where the data is sent.

@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Bundle extras=intent.getExtras();

if (intent.hasExtra("ready")) {
    // Retrieve the message and call getMsg(String)
   connect.starter(SaveSharedPreference.getName(TabExercise.this), SaveSharedPreference.getUserId(TabExercise.this));

}

}

This is the where the intent is caught in the mainactivity. Not ideal.

回答1:

I think what you may find helpful is to use Singletons or perhaps a non-UI Fragment. If you aren't using Fragments already for your UI, you should definitely look into it because it is the de jure standard for modern android apps. What's more, the Android Support Library gives Fragments all the way back to Android 1.6 which is ideal for backwards compat.

You could equally pass data and messages around using Handlers between threads. These basically provide a pipeline which you can post messages to and handleMessage. You would probably start your network stuff in your Application onCreate and perhaps store the thread as a singleton. You would then pass a reference to your UI Handler to this thread which can then communicate directly to your UI by posting Runnables.

An interesting answer for which is 'better' can be found here:

Non-UI Fragment vs Singleton



回答2:

as far as i understood the question, you start your activity, from there you start your CommunicationHandler instance?

then you'll let your activity implement any kind of CallBack interface, instantiate your Handler with the CallBack (means: the activity) and call the CallBacks call method.

see this question and it's answer for some more details on how to use callbacks

sorry if i understood it wrong :-)

edit:

Your MainActivity (the one starting your SocketConnector and receiving the messages) should provide an implementation of a callback interface. the interface could look something like this:

public interface IMessageReceiver {
  public void onMessageReceived(Message m);
}

with your Message class looking like:

public class Message {
  String name;
  String msg;
  //add getter/setter and constructor to fit your needs
}

then your main activity should look like:

public class MainActivity extends Activity implements IMessageReceiver {
  //... main activity code here.
    SocketConnector mySC = new SocketConnector(this);
  //... more main activity code here.
  public void onMessageReceived(Message m) {
    //do something with the message, e.g. display to edit texts, lists etc.
  }
}

and in your SocketConnector you will define the IMessageReceiver as a final member and call the receiver.onMessageReceived(m) - should be like

IMessageReceiver receiver

public SocketConnector(IMessageReceiver receiver) {
  this.receiver = receiver;
}

@Override
public void on(String event, IOAcknowledge ack, Object... data) {
  if (event.equals("message")) {
      System.out.println(data[2]);

      //Intent newIntent = new Intent(Chat.mContent, Chat.class);
      //Bundle extras=new Bundle();
      //extras.putString("name", (String)data[1]);
      //extras.putString("MSG", (String)data[2]);
      //newIntent.putExtras(extras);


      //Chat.mContent.startActivity(newIntent);
      Message m = new Message();
      m.name = (String)data[0];
      m.msg = (String)data[1];
      this.receiver.onMessageReceived(m);
    }
}