【问题标题】:Sending data back to the Main Activity in Android将数据发送回 Android 中的主 Activity
【发布时间】:2010-10-29 13:12:48
【问题描述】:

我有两个活动:主要活动和子活动。
当我在主活动中按下按钮时,将启动子活动。

现在我想将一些数据发送回主屏幕。我使用了 Bundle 类,但它不起作用。它会引发一些运行时异常。

有什么解决办法吗?

【问题讨论】:

  • 另一个技巧在你的主活动中定义一个 ArrayList 并使其成为静态的,这样你就可以在第二个活动中访问它,然后在其中添加你想要发送到主活动的数据,然后你在主活动中访问它
  • Abhishek Yadav,如果您的主要活动要销毁(onDestroy() 回调)怎么办。我认为这不是很好的建议。

标签: android android-intent


【解决方案1】:

使用startActivityForResult()方法调用调用子Activity Intent

这里有一个例子: http://developer.android.com/training/notepad/notepad-ex2.html

在“从屏幕返回结果”中: http://developer.android.com/guide/faq/commontasks.html#opennewscreen

【讨论】:

  • 是的,我同意 cbrulak,文档链接比答案更有帮助。
  • 链接现在显示了一些一般的东西。内容可能会更改,请更新或删除社区的答案
【解决方案2】:

有几种方法可以实现您想要的,具体取决于具体情况。

最常见的场景(听起来就是这样)是子 Activity 用于获取用户输入 - 例如从列表中选择联系人或在对话框中输入数据。在这种情况下,您应该使用 startActivityForResult 来启动您的子 Activity。

这提供了一个管道,用于使用setResult 将数据发送回主 Activity。 setResult 方法接受一个 int 结果值和一个 Intent,该 Intent 被传回调用的 Activity。

Intent resultIntent = new Intent();
// TODO Add extras or a data URI to this intent as appropriate.
resultIntent.putExtra("some_key", "String data"); 
setResult(Activity.RESULT_OK, resultIntent);
finish();

访问调用Activity中返回的数据覆盖onActivityResult。 requestCode对应startActivityForResult调用中传入的整数,resultCode和data Intent是从子Activity返回的。

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  switch(requestCode) {
    case (MY_CHILD_ACTIVITY) : {
      if (resultCode == Activity.RESULT_OK) {
        // TODO Extract the data returned from the child Activity.
        String returnValue = data.getStringExtra("some_key");
      }
      break;
    } 
  }
}

【讨论】:

  • 为了完整起见,应该提到调用 finish() 的最佳位置是什么?专家们可能很清楚,但对于初学者来说,无需参考其他资源就可以了解。
  • @jelmoodjasser 我花了一点时间才弄明白,但基本上当您使用 Intent 开始新活动时,您需要使用 startActivityForResult 函数而不仅仅是 startActivity。一个例子可能是startActivityForResult(myIntent, 2);,其中 2 是结果代码,它可以代替上面 switch 语句中的MY_CHILD_ACTIVITY
  • 当第二个活动完成并返回到第一个活动时,如何在完成之前将 requestCode 设置为第二个活动....用于在 FirstActivity 中的 onActivityResult
  • Intent 是强制性的吗?如果我没有要寄回的东西,我是否需要将空意图寄回?
  • @BagusAjiSantoso 意图是可选的,仅当您有任何东西要发回时才需要。
【解决方案3】:

Activity 1 使用startActivityForResult:

startActivityForResult(ActivityTwo, ActivityTwoRequestCode);

Activity 2 已启动,您可以执行操作,要关闭 Activity,请执行以下操作:

Intent output = new Intent();
output.putExtra(ActivityOne.Number1Code, num1);
output.putExtra(ActivityOne.Number2Code, num2);
setResult(RESULT_OK, output);
finish();

活动 1 - 从上一个活动返回将调用 onActivityResult:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == ActivityTwoRequestCode && resultCode == RESULT_OK && data != null) {
        num1 = data.getIntExtra(Number1Code);
        num2 = data.getIntExtra(Number2Code);
    }
}

更新: 回复 Seenu69 的评论,在活动二中,

int result = Integer.parse(EditText1.getText().toString()) 
           + Integer.parse(EditText2.getText().toString());
output.putExtra(ActivityOne.KEY_RESULT, result);

然后在活动一中,

int result = data.getExtra(KEY_RESULT);

【讨论】:

  • 您好,感谢您回答我的问题。此代码对我来说还不够。我想在第二个活动本身中执行加法,结果应该通过 onActivityResult 方法返回给 MainActivity。例如,Main Activity 中只有一个按钮,单击它会将您带到第二个 Activity,通过 editText 小部件输入两个数字,在第二个 Activity 本身中执行添加逻辑,最后将结果返回给 MainActivity。明白了吗?
  • 在这种情况下,在第二个活动中,您将执行计算并使用 putExtra() 将结果存储在 Intent 中。我已经在上面编辑了我的答案
【解决方案4】:

使用 sharedPreferences 并保存您的数据并从应用程序的任何位置访问它

像这样保存日期

SharedPreferences sharedPreferences = getPreferences(MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.putString(key, value);
    editor.commit();

并接收这样的数据

SharedPreferences sharedPreferences = getPreferences(MODE_PRIVATE);
    String savedPref = sharedPreferences.getString(key, "");
    mOutputView.setText(savedPref);

【讨论】:

  • 如果第二个活动是在应用程序中设置永久更改/设置,这将更合适。
  • 如果我想在 2 个不同的 android 应用程序之间共享数据,这会起作用吗?一个称为库?
  • 这是 SharedPreferences 滥用。
  • 使用此方法仅在两个活动之间传递数据(OP 的原始问题)就像滥用 SharedPreferences。它不是为此而设计的,对于像在两个活动之间传递数据这样的简单任务,系统必须做太多工作(在存储中写入 xml 并再次读取它)。
【解决方案5】:

FirstActivity 使用 startActivityForResult:

Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivityForResult(intent, int requestCode); // suppose requestCode == 2

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 2)
    {
        String message=data.getStringExtra("MESSAGE");
    }
}

在 SecondActivity 调用 setResult() onClick 事件或 onBackPressed()

Intent intent=new Intent();
intent.putExtra("MESSAGE",message);
setResult(Activity.RESULT_OK, intent);

【讨论】:

  • 是requestCode的resultCode吗?
【解决方案6】:

发回数据

它帮助我在上下文中看待事物。这是一个用于发回数据的完整简单项目。这里没有提供 xml 布局文件,而是提供图像。

主要活动

  • 使用startActivityForResult 启动第二个活动,为其提供任意结果代码。
  • 覆盖onActivityResult。当第二个活动完成时调用它。您可以通过检查请求代码确保它实际上是第二个活动。 (当您从同一个主要活动开始多个不同活动时,这很有用。)
  • 从返回的Intent 中提取数据。使用键值对提取数据。

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private static final int SECOND_ACTIVITY_REQUEST_CODE = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    // "Go to Second Activity" button click
    public void onButtonClick(View view) {

        // Start the SecondActivity
        Intent intent = new Intent(this, SecondActivity.class);
        startActivityForResult(intent, SECOND_ACTIVITY_REQUEST_CODE);
    }

    // This method is called when the second activity finishes
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        // Check that it is the SecondActivity with an OK result
        if (requestCode == SECOND_ACTIVITY_REQUEST_CODE) {
            if (resultCode == RESULT_OK) {

                // Get String data from Intent
                String returnString = data.getStringExtra("keyName");

                // Set text view with string
                TextView textView = (TextView) findViewById(R.id.textView);
                textView.setText(returnString);
            }
        }
    }
}

第二个活动

  • 将要发送回上一个活动的数据放入Intent。数据使用键值对存储在Intent 中。
  • 将结果设置为RESULT_OK 并添加保存数据的意图。
  • 致电finish() 关闭第二个活动。

SecondActivity.java

public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
    }

    // "Send text back" button click
    public void onButtonClick(View view) {

        // Get the text from the EditText
        EditText editText = (EditText) findViewById(R.id.editText);
        String stringToPassBack = editText.getText().toString();

        // Put the String to pass back into an Intent and close this activity
        Intent intent = new Intent();
        intent.putExtra("keyName", stringToPassBack);
        setResult(RESULT_OK, intent);
        finish();
    }
}

其他说明

  • 如果您在 Fragment 中,它将不知道 RESULT_OK 的含义。只需使用全名:Activity.RESULT_OK

另见

【讨论】:

  • 这是一个写得很好的明确解释。干得好!
【解决方案7】:

有一些方法可以做到这一点。 1.使用上面答案中很好解释的startActivityForResult()。

  1. 通过在“Utils”类或您自己的任何其他类中创建静态变量。例如,我想将 ActivityB 中的 studentId 传递给 ActivityA。首先我的 ActivityA 正在调用 ActivityB。然后在 ActivityB 中设置 studentId(它是 Utils.class 中的静态字段)。 像这样 Utils.STUDENT_ID="1234";然后在返回 ActivityA 时使用存储在 Utils.STUDENT_ID 中的 studentId。

  2. 通过在应用程序类中创建 getter 和 setter 方法。

像这样:

public class MyApplication extends Application {

    private static MyApplication instance = null;
    private String studentId="";

    public static MyApplication getInstance() {
        return instance;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
    }

    public void setStudentId(String studentID){
        this.studentId=studentID;
    }

    public String getStudentId(){
        return this.studentId;
    }
}

这样你就完成了。当你在 ActivityB 时,只需在里面设置数据,然后返回 ActivityA ,获取数据。

【讨论】:

    【解决方案8】:

    在第一个活动中,您可以使用startActivityForResult() 发送意图,然后在第二个活动完成后使用setResult 获取结果。

    MainActivity.class

    public class MainActivity extends AppCompatActivity {
    
        private static final int SECOND_ACTIVITY_RESULT_CODE = 0;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
        // "Go to Second Activity" button click
        public void onButtonClick(View view) {
    
            // Start the SecondActivity
            Intent intent = new Intent(this, SecondActivity.class);
            // send intent for result 
            startActivityForResult(intent, SECOND_ACTIVITY_RESULT_CODE);
        }
    
        // This method is called when the second activity finishes
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
    
            // check that it is the SecondActivity with an OK result
            if (requestCode == SECOND_ACTIVITY_RESULT_CODE) {
                if (resultCode == RESULT_OK) {
    
                    // get String data from Intent
                    String returnString = data.getStringExtra("keyName");
    
                    // set text view with string
                    TextView textView = (TextView) findViewById(R.id.textView);
                    textView.setText(returnString);
                }
            }
        }
    }
    

    SecondActivity.class

    public class SecondActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_second);
        }
    
        // "Send text back" button click
        public void onButtonClick(View view) {
    
            // get the text from the EditText
            EditText editText = (EditText) findViewById(R.id.editText);
            String stringToPassBack = editText.getText().toString();
    
            // put the String to pass back into an Intent and close this activity
            Intent intent = new Intent();
            intent.putExtra("keyName", stringToPassBack);
            setResult(RESULT_OK, intent);
            finish();
        }
    }
    

    【讨论】:

      【解决方案9】:

      我创建了简单的演示类供您更好地参考。

      FirstActivity.java

       public class FirstActivity extends AppCompatActivity {
      
          private static final String TAG = FirstActivity.class.getSimpleName();
          private static final int REQUEST_CODE = 101;
          private Button btnMoveToNextScreen;
      
          @Override
          protected void onCreate(@Nullable Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              btnMoveToNextScreen = (Button) findViewById(R.id.btnMoveToNext);
              btnMoveToNextScreen.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
                      Intent mIntent = new Intent(FirstActivity.this, SecondActivity.class);
                      startActivityForResult(mIntent, REQUEST_CODE);
                  }
              });
          }
      
          @Override
          protected void onActivityResult(int requestCode, int resultCode, Intent data) {
              super.onActivityResult(requestCode, resultCode, data);
      
              if(resultCode == RESULT_OK){
                  if(requestCode == REQUEST_CODE && data !=null) {
                      String strMessage = data.getStringExtra("keyName");
                      Log.i(TAG, "onActivityResult: message >>" + strMessage);
                  }
              }
      
          }
      }
      

      这里是 SecondActivity.java

      public class SecondActivity extends AppCompatActivity {
      
          private static final String TAG = SecondActivity.class.getSimpleName();
          private Button btnMoveToPrevious;
          private EditText editText;
      
          @Override
          protected void onCreate(@Nullable Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_second);
      
              editText = (EditText) findViewById(R.id.editText);
      
              btnMoveToPrevious = (Button) findViewById(R.id.btnMoveToPrevious);
              btnMoveToPrevious.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
      
                      String message = editText.getEditableText().toString();
      
                      Intent mIntent = new Intent();
                      mIntent.putExtra("keyName", message);
                      setResult(RESULT_OK, mIntent);
                      finish();
      
                  }
              });
      
          }
      }
      

      【讨论】:

      • 很好解释!
      【解决方案10】:

      只是我认为上述答案中缺少的一个小细节。

      如果您的子活动可以从多个父活动中打开,那么您可以根据您的活动是由startActivity 还是startActivityForResult 打开的,来检查您是否需要做setResult。您可以使用getCallingActivity() 来实现此目的。更多信息here

      【讨论】:

        【解决方案11】:

        所有这些答案都在说明您的第二个活动需要在发送数据后完成的场景。

        但如果您不想完成第二个活动并希望将数据发送回第一个活动,那么您可以使用 BroadCastReceiver。

        在第二个活动中 -

        Intent intent = new Intent("data");
        intent.putExtra("some_data", true);
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
        

        在第一个活动中-

        private BroadcastReceiver tempReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                // do some action
            }
        };
        

        在onCreate()中注册接收者-

         LocalBroadcastManager.getInstance(this).registerReceiver(tempReceiver,new IntentFilter("data"));
        

        在 onDestroy() 中取消注册

        【讨论】:

          【解决方案12】:

          另一种实现预期结果的方法可能更好,具体取决于您的情况,即创建一个监听器接口。

          通过让父活动侦听由子活动触发的接口,同时将所需数据作为参数传递,可以创建一组类似的情况

          【讨论】:

            【解决方案13】:

            2021 年 3 月更新

            Activity v1.2.0Fragment v1.3.0 一样,引入了新的Activity Result APIs

            活动结果 API 提供了用于注册结果、启动结果以及在系统分派结果后处理结果的组件。

            所以不再需要使用startActivityForResultonActivityResult

            为了使用新的 API,您需要在源 Activity 中创建一个 ActivityResultLauncher,指定目标 Activity 完成并返回所需数据时将运行的回调:

            private val intentLauncher =
                registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            
                    if (result.resultCode == Activity.RESULT_OK) {
                        result.data?.getStringExtra("key1")
                        result.data?.getStringExtra("key2")
                        result.data?.getStringExtra("key3")
                    }
                }
            

            然后,在您需要时启动您的意图:

            intentLauncher.launch(Intent(this, YourActivity::class.java))
            

            要从目标 Activity 返回数据,您只需添加一个带有返回值的意图即可返回到 setResult() 方法:

            val data = Intent()
            data.putExtra("key1", "value1")
            data.putExtra("key2", "value2")
            data.putExtra("key3", "value3")
            
            setResult(Activity.RESULT_OK, data)
            finish()
            

            如需更多信息,请参考Android Documentation

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-12-28
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-07-16
              • 1970-01-01
              相关资源
              最近更新 更多