【问题标题】: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。

标签: java android nullpointerexception listener


【解决方案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 来初始化第二个活动,这甚至不是一个好主意。

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

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

      private Handler = new Handler(){
        public void handleMessage(Message message){
              // Do your jobs
        }}
      
    2. 使用Messenger 将带有您意图的处理程序发送到第二个活动:

      Intent intent = new Intent(this, SecondActivity.class);
      intent.putExtra("key_handler", new Messenger(handler));
      startActivity(intent);`
      
    3. 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)`
      
    4. 返回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() 实例化活动是错误的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-12-10
          • 1970-01-01
          • 2023-03-08
          • 2020-07-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多