如何使用StartActivityForResult()函数

11

在我的应用程序中,我需要向用户请求快速输入

我需要从这个Flash-Activity获取结果,然后回到之前的一个。

我已经了解了StartActivityForResult()方法,但我还不确定如何正确使用它,有什么示例吗?

编辑:

我尝试通过意图(作为结果)传递Player对象,使用我在所有应用程序中应用于此方法的方法:

在我的第二个活动中(我需要从中获取结果的活动):

Intent intent = new Intent();
Player playerKilled = players.get(position);

Bundle bundle = new Bundle();
bundle.putSerializable("PLAYER_KILLED", (Serializable) playerKilled);
intent.putExtras(bundle);

setResult(Activity.RESULT_OK, intent);
finish();

我需要将结果带到的主要活动:

if (resultCode == Activity.RESULT_OK) {

    Intent intent = this.getIntent();
    Bundle bundle = intent.getExtras();
    playerKilled = (Player)bundle.getSerializable("PLAYER_KILLED");

    Toast.makeText(this, playerKilled.getName() + "the " + playerKilled.getCardName() + " has died, and he/she had the ID: " + playerKilled.getId(), Toast.LENGTH_SHORT).show();

2
这里有问题还是您想要关于您自己应用程序的设计意见?如果是后者,那么这不是 StackOverflow 的主题。 - OneCricketeer
1
考虑将此问题转移到code review网站。 - 0x6C38
@Snip3r_bow 如果那样的话,可能需要重述问题。 - 0x6C38
为什么不直接在同一个活动中创建一个简单的对话框来展示呢? - Eenvincible
@Snip3r_bow,我不确定你的问题具体是什么。你想要输入来自对话框,因为你提到你不想让它失去主活动的焦点?你的意思是什么 - 你想在请求输入时仍然能够访问活动的“ListView”(如你所提到的)吗? - Farbod Salamat-Zadeh
显示剩余7条评论
3个回答

21

您可以以多种方式请求用户输入,但如果您想要使用新的 Activity,可以使用 startActivityForResult() 启动新活动并从那里返回输入。

首先,我强烈建议阅读关于如何使用 startActivityForResult()此 Stack Overflow 答案。我将解释如何为您的特定用例实现它。

所以,您需要了解 startActivityForResult() 有两个参数:

  • Intent(用于在活动之间传递数据)
  • 标识您请求的“请求代码”整数

最好使用常量作为您的请求代码,在两个活动中都可以访问。例如,在您的主活动中,您可以添加:

public static final int REQUEST_CODE = 1;

由于它是“public”,所以在这两个活动中都可以访问,并且因为它是一个“int”(整数),所以对于请求代码也有效。

在您的主要活动中,您需要一种操作(例如按钮按下)来启动第二个活动。假设这是一个按钮点击触发此操作:

Button button = (Button) findViewById(R.id.your_button);
button.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        // actions that will happen when the button is pressed:

        Intent intent = new Intent(this, SecondActivity.class);
        startActivityForResult(intent, REQUEST_CODE);
    }
});

基本上,我们正在创建一个意图(Intent),其中指定了我们当前的活动(this)和第二个活动。 我们将意图与之前声明的REQUEST_CODE一起在startActivityForResult()方法中使用。

现在,在我们的第二个活动中,我们需要某些东西来触发返回数据。 根据您先前提出的问题,我假设您希望在单击RecyclerView项时将数据返回到主活动。 这里是我对那个问题的部分回答,已修改以显示如何发送数据回来。

ExampleClickAdapter clickAdapter = new ExampleClickAdapter(yourObjects);
clickAdapter.setOnEntryClickListener(new ExampleClickAdapter.OnEntryClickListener() {
    @Override
    public void onEntryClick(View view, int position) {
        Intent intent = new Intent();
        intent.putExtra("pos", position);
        setResult(Activity.RESULT_OK, intent);
        finish();
    }
});
recyclerView.setAdapter(clickAdapter);

以上将返回从点击RecyclerView的列表项的位置。

看一下IntentputExtra()方法。这就是传递数据的方法。你可以看到在这个方法中我传递了一个字符串"pos"和变量position,但为什么呢:

intent.putExtra("key", object);

IntentputExtra方法总是使用一个字符串键和另一个对象,比如你的整数变量position。当检索此对象时,将再次使用该键(稍后我会向你展示)。

我们使用Activity.RESULT_OK来表示我们正在传递结果,但如果您不想发送结果,可以使用Activity.RESULT_CANCELED - 这在我在开头提到的答案链接中有解释。请注意,如果使用Activity.RESULT_CANCELED,则不需要使用putExtra,因为没有任何内容需要返回。

最后,您需要在主活动中添加一些内容,以处理从第二个活动接收到的结果:

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

    if (requestCode == REQUEST_CODE) {

        if (resultCode == Activity.RESULT_OK) {
            int result = data.getIntExtra("pos");
            // do something with the result

        } else if (resultCode == Activity.RESULT_CANCELED) {
            // some stuff that will happen if there's no result
        }
    }
}

我们使用onActivityResult方法来实现这个功能。

在这个方法的开头,我们会检查requestCode是否与我们之前定义的一个公共常量REQUEST_CODE相同。

如果是,我们就继续检查返回结果的resultCode。如果有数据被返回(Activity.RESULT_OK),我们可以使用getIntExtra()方法获取其值,因为position是一个整数(如果返回的是字符串,则可以使用getStringExtra()方法)。然后你就可以对返回的数据进行操作。但是,如果没有数据被返回(正如我们之前提到的Activity.RESULT_CANCELED),那么你可以执行其他操作。

希望这能帮助你实现你的想法,但是通过Google搜索也可以找到我上面提到的答案(这里是链接),其中清楚地解释了如何使用startActivityForResult()方法。其他回答也很好地解释了这个问题,但也许你需要指导如何在你的用例中实现它(即与你之前提出的问题的代码结合起来),这就是我提供上面的解释的原因。

你还可以阅读Android文档的从Activity获取结果,以及startActivityForResult()方法Intent的Android文档。


嘿,我想将Player对象作为值传递,但是我的方法(我已经更新了我的问题)似乎不起作用,有什么想法吗? - FET
@Snip3r_bow 如果要传递对象,我建议你让你的Player对象实现Parcelable而不是使用Serializable。这里有一个很好的答案解释如何做到这一点here。在修改了Player对象之后,我会使用putParcelable("PLAYER_KILLED", playerKilled) - 在这里你不需要将其转换为任何东西。同样,在你的主活动中,你应该使用getParcelable而不是getSerializable。这里也有官方文档 - Farbod Salamat-Zadeh
谢了,我暂时解决了这个问题,在MainActivity中传递位置并获取玩家对象。但是我肯定会在未来的更新中尝试实现Parcelable,因为据我所知,在某些情况下它比Serializable更好。 - FET
嘿,伙计,可以请你看一下这个问题吗?这里。我觉得你是唯一一个真正能理解并提供帮助的人。 - FET
@Snip3r_bow 我明天会去看看 - 这是你的问题吗? - Farbod Salamat-Zadeh
显示剩余2条评论

2
如果我理解您的问题正确,我相信您需要这个解决方案:
startActivityForResult(intent, REQUEST_CODE);

只需使用项目列表(RecyclerView?)创建您的活动,然后启动它以获取结果,基本上创建您的意图并调用上述方法即可。

Intent intent = new Intent(this, SecondActivity.class);
startActivityForResult(intent, SOME_UNIQUE_CODE);

现在,在您进入列表活动后,当用户选择项目时,请执行以下操作:
intent = new Intent();
intent.putExtra("id", "Some Value Here to return");
setResult(RESULT_OK, intent);
finish();

因此,当用户从列表中点击一个项目时,您可以使用以下代码传回您的值并关闭此列表活动。

最后,要实际接收传递的值,您只需要覆盖 onActivityResult() 方法。

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
    if (requestCode == REQUEST_CODE){
        if (resultCode == RESULT_OK){

            id = data.getExtras().getString("id");
        }
    }
}

这就是你需要的全部!我认为即使只做一件事情 - 显示一个项目列表,创建一个活动也完全可以。希望这能帮到你!祝你好运,编码愉快!


0
你可以弹出一个看起来像对话框的活动。
在清单文件中声明活动时,包含一个对话框主题:
<activity
    android:name="com.myapp.DialogActivity"
    android:theme="@android:style/Theme.Holo.Light.Dialog"
    ...
</activity>

然后可以像平常一样调用活动,并根据需要返回结果:

Intent i = new Intent(this, DialogActivity.class);
startActivityForResult(i, REQUEST_CODE);

嗯,这个对话框主题的活动在关闭后会让我回到之前的活动吗? - FET
是的,它会将您带回调用它的上一个活动 - 当我需要更强大的东西时,我自己使用它而不是对话框类。 - SQLiteNoob
嗯,我在文档上看到需要使用CursorLoader,是吗?看一下:https://developer.android.com/training/basics/intents/result.html - FET
好的,我明白了,我现在会尝试将其应用到我的应用程序中,如果成功或失败,我会在这里告诉你 :) - FET
嘿,我怎么可以编辑布局?我的意思是,对话框的布局。 - FET
显示剩余10条评论

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