不需要结束活动的情况下进行活动间通信

3
我有两个活动:一个是主要的(A),另一个是从A启动的(B)。我使用startActivityForResult(intent, id)启动B。
我知道我可以通过setResult()方法将结果发送回A,但据我所知,在调用finish()之前,结果不会被发送。我需要从B向A发送数据而不关闭B(甚至在关闭之前多次发送)。有没有办法实现这一点?
据我所读,没有很多选项可以实现这一点。我可以使用SharedPreferences,但那样我还需要某种事件来通知A它必须读取一个值!
任何想法都欢迎。
------最终解决方案------
最后,我得到了@Nathaniel Waggoner的建议,谢谢他。这是我做的:
在我的活动中,我声明了BroadcastReceiver的扩展:
class ActivityBroadcast extends BroadcastReceiver {
  @Override
  public void onReceive(final Context context, final Intent intent) {
    final String txt2send = intent.getStringExtra("txt2send");
    if ((txt2send != null) && (!txt2send.isEmpty())) {
      // Do the needed stuff
      ...
    }
  }
}

现在我已经在我的类中声明并初始化了ActivityBroadcast实例:

private static ActivityBroadcast broadcast_signal;
broadcast_signal = new ActivityBroadcast();

我控制onReceive方法的触发只有通过我的IntentFilter来发送SENDTXT2SOCK自定义操作的Intent,例如:

// CustomActions.SENDJOIN2CHAN is just a constant from a customized public class
// where I define my own constants to not interfere with the "official" ones
registerReceiver(broadcast_signal, new IntentFilter(CustomActions.SENDTXT2SOCK));

我的意思是在broadcast_signal中仅注册CustomActions.SENDTXT2SOCK操作,因此将忽略其他任何操作。现在我们只需从所需的活动向该接收器发送信号即可:

final Intent intentResult = new Intent(CustomActions.SENDTXT2SOCK);
intentResult.putExtra("txt2send", "blabla");
sendBroadcast(intentResult);

就是这样,完美地运作了!


1
“我需要在不关闭B的情况下从B向A发送数据(即使在关闭之前多次发送)。“ - 为什么?当Activity B启动并隐藏Activity A时,Activity A将进入停止状态。换句话说,它不再运行,因此无法在该状态下处理反馈给它的任何数据。我认为您误解了“Activity”和“Activity”生命周期的概念。我无法想象任何需要实时数据更新的隐藏/停止的“Activity”的用例。 - Squonk
我会尝试更好地解释:A拥有一个对象,它是一个AsyncTask,它创建了一个socket并在整个应用程序生命周期中执行。在B中,我想通过该socket发送多个数据(无需在每次发送后关闭B),因此我的初始想法是将其发送到A,然后从A发送到AsyncTask,但我没有意识到它实际上处于停止状态...我想其中一个可能的解决方案是将socket对象传递给B。 - nKn
1
哎呀!首先,与普遍观点相反,AsyncTask 不应用于任何类型的长时间运行操作(包括网络或其他操作)。其次,如果您在 Activity A 中使用 AsyncTask 并启动 Activity B,则有可能(虽然不太可能)系统会销毁 Activity A 以释放资源 - 可能的结果是一个孤立的线程(由 doInBackground 使用)。我强烈建议使用带有工作线程的绑定 Service 来执行网络操作。如果需要,它可以从两个活动中访问。 - Squonk
没错,我会将AsyncTask转换为Service。我会尝试上面提到的关于Broadcasts的另一种解决方案,并发布结果。谢谢! - nKn
请将您的解决方案发布为答案,而不是对问题的编辑。 - Donald Duck
4个回答

3

  1. 你不需要扩展广播接收器。你可以在活动中定义它们为私有类。广播几乎总是解决这种通信问题的方法。这并不总是首选方法(出于许多原因,例如服务具有非常好的消息传递(以及更多)机制)。
  2. 你的活动没有停止 - 它可能会停止。我之所以这样说,是因为重要的是要理解,当你的活动失去焦点时,你不会立即被销毁,而是在资源或其他特定情况下才会被销毁。
- Nathaniel D. Waggoner
好的,今天我会尝试,并发布结果。谢谢! - nKn
我也想指出Squonk的评论是正确的——你不应该在异步任务中进行网络操作,使用服务会更加合适。 - Nathaniel D. Waggoner
1
是的,我刚刚阅读了一份非常完整的有关服务的文档,我肯定会将其转换为一个服务。 - nKn
1
它通过广播和意图工作得非常好 :-) 我已经用实现的解决方案编辑了我的原始问题。同时正努力将AsyncTask更改为Service :-P 谢谢! - nKn
显示剩余6条评论

1

和之前的评论一样,但我会检查它,谢谢! - nKn
这个不起作用...没有从不同的活动中调用 - Oscar Méndez

0

你可以使用EventBus简单库。
首先在接收器活动中注册EventBus。

   @Override
    public void onStart() {
       super.onStart();
     EventBus.getDefault().register(this);
    } 

然后设置一个订阅方法

@Subscribe(threadMode = ThreadMode.MAIN)  
public void onMessageEvent(MessageEvent event) {/* Do something */};

然后在其他活动中像这样发布您的实体

EventBus.getDefault().post(new MessageEvent());

0

您可以使用广播和观察者来从一个活动调用另一个活动的方法。您将使用意图从B活动调用广播,然后使用观察者从广播中调用A活动的方法。

例如,如果您想从ActivityB调用ActivityA.someMethod,您可以执行以下操作(不要忘记在ActivityA上实现Observer):

public class ActivityA extends AppCompatActivity implements Observer{
    //This is the method you want to call from ActivityB
    public void someMethod(Intent intent){
        //intent will be the Intent object created in ActivityB, you can pass data to this method by setting extras in the intent
    }

    //Define the observer and broadcast receiver classes
    private static class MyObservable extends Observable{
        private static final MyObservable instance = new MyObservable();
        public void updateValue(Object data){
            synchronized(this){
                setChanged();
                notifyObservers(data);    //This method calls ActivityA.update
            }
        }
    }

    public static class MyBroadcastReceiver extends BroadcastReceiver{
        //This class must be public and static and must be added to the manifest
        //To add this class to the manifest in Android Studio put the cursor on the name of the class, press Alt+Enter and choose "Add to manifest"
        @Override
        public void onReceive(Context context, Intent intent){    //This method will be called when the broadcast is sent from ActivityB
            MyObservable.instance.updateValue(intent);
        }
    }

    //Connect the observer to the activity in the onCreate method
    @Override
    protected void onCreate(Bundle savedInstanceState){
        MyObservable.instance.addObserver(this);
        //Do everything else in onCreate as usual
    }

    //This method will be called when the notifyObservers method is called from the oberver
    @Override
    public void update(Observable observable, Object data){
        this.someMethod((Intent) data);    //Call the method that you need
    }
}

public class ActivityB extends AppCompatActivity{
    public void callSomeMethodOnActivityB(){
        Intent intent = new Intent(this, ActivityA.MyBroadcastReceiver.class);
        //Add some extras to the intent to pass data
        sendBroadcast(intent);    //Calls ActivityA.MyBroadcastReceiver.onReceive
    }
}

本答案的大部分内容基于ilw对“BroadcastReceiver和Activity之间的通信”问题的回答,特此致谢。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接