从另一个活动调用时为空侦听器

Posted

技术标签:

【中文标题】从另一个活动调用时为空侦听器【英文标题】:Null listener when called from another activity 【发布时间】:2018-07-20 23:41:29 【问题描述】:

android 中,我试图在第二个活动中完成任务时设置回调侦听器。流程如下:

MainActivity 开始 -> 调用第二个 Activity -> 当第二个 Activity 完成时调用监听器 -> 返回到 Main Activity

我已经用下面的代码做到了:

  //// First activity
  Main Activity 


      // Reference to second activity
  private IntroActivity mIntroActivity;

  @Override
  protected void onCreate(Bundle savedInstanceState) 

    /// Listener reference
    mIntroActivity = new IntroActivity();

    Intent i = new Intent(MainActivity.this, IntroActivity.class);
  startActivity(i);


      /// Call back for second activity
    mIntroActivity.setIntroListener(new IntroActivity.IntroListener() 
        @Override
        public void finished() 
          /// When finished do something!
        

    );

  
  


  /// Second Activity

  public class IntroActivity extends AppIntro 

      /// Listener setup

    public interface IntroListener 
        void finished();
    


    public void setIntroListener(IntroListener listener) 
        this.mIntroListen = listener;
    

    public IntroActivity()
        this.mIntroListen = null;
    


    private IntroListener mIntroListen;



      @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) 
      super.onCreate(savedInstanceState);

    

    @Override
  public void onDonePressed(Fragment currentFragment) 
      super.onDonePressed(currentFragment);

      /// Call listenr from MainActivity
      mIntroListen.finished();
  



  

为第二个活动添加一个接口监听器。当这个活动完成时,调用finished() 并返回到MainActivity。

我遇到的问题是 mIntroListen.finished();在第二个活动中为空。

这里的任何想法都会很棒。我在另一个项目中使用相同的接口/侦听器(这是另一个类而不是活动),所以我不确定出了什么问题。

提前致谢!

【问题讨论】:

不完全确定,但这可能是因为当你移动到第二个活动时,android 正在清理资源,而不是这样做,要么使用像 greenrobot/EventBus 这样的事件总线,要么使用本地广播管理器,这样你的代码就解耦了,空指针异常的变化也少了 我现在去看看greenrobot。 【参考方案1】:

我遇到的问题是 mIntroListen.finished();在第二个活动中为空。

您将始终获得null,因为mIntroActivity 实例和您实际运行的IntroActivity 实例不同。

mIntroActivity = new IntroActivity();

以这种方式创建活动不是一个好主意。要启动Activity,您应该始终使用startActivity()

如果您想使用来自IntroActivity 的一些数据返回MainActivity,或者只是在完成呼叫侦听器时返回,您应该在MainActivity 中使用startActivityForResult(intent)。此方法将为您提供设置您在IntroActivity 中找到的结果的选项,您可以通过onActivityResult() 方法在MainActivity 中使用这些结果。

对于您的情况,请使用startActivityForResult(intent) 启动您的IntroActivity,并在完成呼叫侦听器时完成IntroActivity 然后onActivityResult() 方法将在MainActivity 中调用。在onActivityResult()做你想做的事

查看这个官方链接Getting a Result from an Activity也可以查看这个answer

【讨论】:

【参考方案2】:

您实际上并没有通过调用 new 来初始化第二个活动,这甚至不是一个好主意。

我相信有更好的方法来使用处理程序来完成你的工作,如下所示:

    MainActivity 中声明一个处理程序并像下面这样简单地实例化它:

    private Handler = new Handler()
      public void handleMessage(Message message)
            // Do your jobs
      
    

    使用Messenger 将带有您意图的处理程序发送到第二个活动:

    Intent intent = new Intent(this, SecondActivity.class);
    intent.putExtra("key_handler", new Messenger(handler));
    startActivity(intent);`
    

    SecondActivity.class 中获取意图,并从中提取信使,当您的第二个活动完成其工作时,只需调用messenger.send(message) 将消息发送回主活动。

    Intent intent = getIntent();
    Messenger messenger = intent.getExtras("key_handler");
    // Do jobs .....
    // When done, call send method on messenger, maybe you want sth to sent             back to main activity, just use bundle.
    Message message = Message.obtainMessage();
    Bundle bundle = new Bundle();
    // Put sth in the bundle, then call setData()
    message.setData(bundle);
    messenger.send(message)`
    

    返回handleMessage(Message message) 获取您的信息。

请注意,上面的内容只是为了更简单的答案而被忽略,您必须自己进行一些搜索才能正确使用。

【讨论】:

【参考方案3】:

如果您仔细研究以下代码部分,您会发现当您创建 Intent 时,您传递的是 IntroActivity.class。这意味着您只是传递了一个Classreference,而不是该类的实例化对象。因此,当活动启动时,它不会引用您实例化的mIntroActivity。所以,显然introListener 也将是null。这是预期的行为。

/// Listener reference
mIntroActivity = new IntroActivity();

Intent i = new Intent(MainActivity.this, IntroActivity.class);
startActivity(i);

/// Call back for second activity
mIntroActivity.setIntroListener(new IntroActivity.IntroListener() 
    @Override
    public void finished() 
      /// When finished do something!
    
);

要从已启动的活动中获取结果,您必须使用startActivityForResult(Intent intent)。请查看documentation 了解更多信息。

修改后的代码如下所示。

主要活动

private static final int INTRO_ACTIVITY_REQUEST_CODE = 771;

@Override
protected void onCreate(Bundle savedInstanceState) 

  Intent i = new Intent(MainActivity.this, IntroActivity.class);
  startActivityForResult(i, INTRO_ACTIVITY_REQUEST_CODE);


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)

    if (requestCode == INTRO_ACTIVITY_REQUEST_CODE) 
        if (resultCode == RESULT_OK) 
            String resultValue = data.getStringExtra("KEY");
        
    

介绍活动

@Override
public void onDonePressed(Fragment currentFragment) 
  super.onDonePressed(currentFragment);

    Intent resultIntent = new Intent();
    resultIntent.putExtra("KEY", "VALUE");
    setResult(RESULT_OK, resultIntent); // RESULT_OK means success
    finish();

【讨论】:

【参考方案4】:

查看startActivityForResult(Intent, Key)的文档

您应该使用它从另一个活动中获取结果。

使用new() 实例化活动是错误的。

【讨论】:

以上是关于从另一个活动调用时为空侦听器的主要内容,如果未能解决你的问题,请参考以下文章

如何在 OnDestroy 中删除此 firebase 侦听器以减少内存泄漏?

Java:从另一个类扩展侦听器方法的功能

位置监听器 - 不是从服务启动,而是从活动开始

活动到活动回调监听器

在 tabhost 中重新加载一个活动

活动到活动回调监听器