如何从非Activity类中调用startActivityForResult以获取结果

16

有可能从非 Activity 类中调用 startActivityForResult() 方法以获取结果吗?

场景如下:

我有一个名为NonActivity的类(它不从 Activity 派生,因为它不是 UI),该类将运行一堆函数(基本上是步骤)。其中一个步骤需要显示 UI(Activity),然后获取结果(用户输入了什么)。然后能够在接下来的步骤中使用这些数据。

如何在不从 activity 类派生的情况下实现这一点,因为我没有 UI 组件呢? 此外,由于我不想从 activity 类派生,这意味着我无法覆盖OnActivityResult()。 那么结果从哪里来呢?

4个回答

23

startActivityForResult()仅在真正的屏幕活动中才可用,因为它是Activity类的方法。请重新设计您的应用程序,使用户界面由活动驱动。

另一方面,如果您的非Activity类是从屏幕上的Activity中初始化和使用的,则可以将该Activity实例作为参数传递给您的类构造函数,并使用它来启动其他Activity。

但要小心。使用这种方法会增加内存泄漏的风险,因为外部类(例如我的Utils)可能会保留对Activity的引用,即使Activity已经消失。

如果您只想访问数据,则可以尝试将其写入SharedPreferences或数据库或某些文件,然后使用应用程序上下文(再次通过构造函数传递)来读取它。这可以减少内存泄漏的风险,例如:

MyApiClass myApiClass = new MyApiClass(getApplicationContext());

示例代码

主活动:

public class Main extends FragmentActivity {

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

        Utils util = new Utils(this);
        util.startTest();

    }

    @Override
    protected void onActivityResult(int arg0, int arg1, Intent arg2) {
        Toast.makeText(this, "onActivityResult called", Toast.LENGTH_LONG).show();

        super.onActivityResult(arg0, arg1, arg2);
    }

}

Utils类(用于启动结果):

public class Utils {

    Activity activity;

    public Utils(Activity ac) {
        activity = ac;
    }

    public void startTest() {
        Intent i = new Intent(activity, Test.class);
        activity.startActivityForResult(i, 1);

    }

}

测试活动:

public class Test extends FragmentActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Toast.makeText(this, "Test", Toast.LENGTH_LONG).show();

        this.setResult(Activity.RESULT_OK);
        this.finish();

    }

}

startActivityForResult方法无法从非Activity类中工作,因为我们只能在Activity中重写onActivityResult。 - ρяσѕρєя K
感谢您的回复。基本上使用非活动类的原因是我想将整个过程封装到一个类(API)中,然后任何想要使用这个类的人都可以调用它的API。这个API执行一系列步骤,其中一些步骤涉及以活动形式从用户那里获取数据。即使我们忘记了startActivityForResult,我想在非活动类中从活动中获取数据,这种情况在Android中不是有效的吗? - user1950373
2
@RaghavSood:是的,我同意你的观点,我们必须在Activity中重写onActivityResult而不是在非Activity类中,正如OP所询问的那样。 - ρяσѕρєя K
1
是的,我明白你的意思,但我还是加入了我的两分钱。为了更清晰,点赞 +1 :) - codeMagic
谢谢大家的意见。基本上,我想开发一个库来执行某些任务,其中涉及运行某些步骤。其中一个步骤可以涉及启动活动(UI以获取输入)并使用该数据完成该步骤。那么,从Android的角度来看,库启动一个活动是不是一个糟糕的设计?从场景的角度来看,我们应该能够做到这一点,对吧? - user1950373
显示剩余5条评论

7

在没有可见GUI的片段中使用类启动ActivityForResult。您可能会在实用程序类中找到类似于此的内容。

请参见下面的runGetUserAccount。它创建自己的片段并执行startActivityForResult。然后它有自己的onActivityResult。

public class MyGooglePlay {

    private static final int CONNECTION_FAILURE_RESOLUTION_REQUEST = 31502;
    private ActionBarActivity activity;
    private FragmentManager fragManager;

    public MyGooglePlay(ActionBarActivity activity) {
        this.activity = activity;
        this.fragManager = activity.getSupportFragmentManager();
    }


     /**
     * Starts an activity in Google Play Services so the user can pick an
     * account
     */
    private String mEmail = "";
    static final int REQUEST_CODE_PICK_ACCOUNT = 1000;    
    public void runGetUserAccount() {
        if (TextUtils.isEmpty(mEmail)) {
            // run this code in gui less fragment so we can pickup the 
            // on activity result from inside the mygoogleplay class.
            Fragment f = new Fragment() {
                @Override
                public void onAttach(Activity activity) {
                    super.onAttach(activity);
                    String[] accountTypes = new String[] { "com.google" };
                    Intent intent = AccountPicker.newChooseAccountIntent(null,
                            null, accountTypes, false, null, null, null, null);
                    startActivityForResult(intent, REQUEST_CODE_PICK_ACCOUNT);
                }

                @Override
                public void onActivityResult(int requestCode, int resultCode,
                        Intent data) {
                    if (requestCode == REQUEST_CODE_PICK_ACCOUNT) {
                        if (resultCode == Activity.RESULT_OK) {
                            set_Email(data
                                    .getStringExtra(AccountManager.KEY_ACCOUNT_NAME));
                            // getUsername();
                        }
                    super.onActivityResult(requestCode, resultCode, data);
                }

                //this is to verify the fragment has been removed.
                //you can log or put a breakpoint to verify
                @Override public void onDestroy(){
                    super.onDestroy();
                }
            };
            FragmentTransaction fragmentTransaction = this.fragManager
                    .beginTransaction();
            fragmentTransaction.add(f, "getusername");
            fragmentTransaction.commit();
        }
    }

    /**
     * @param mEmail
     *            the mEmail to set
     */
    private void set_Email(String mEmail) {
        this.mEmail = mEmail;
        if (!TextUtils.isEmpty(mEmail)) {
            // TODO notify caller email is ready;
            // activity.onEmailReady(mEmail);
        }
        //we are done with the "getusername" fragment
        Fragment f = fragManager.findFragmentByTag("getusername");
        if (f!=null) {
            fragManager.beginTransaction().remove(f).commit();
        }
    }
}

1
但是您在构造函数中传递了一个活动,而操作者希望在没有活动的情况下执行它。 - Yash
只是使用活动来获取片段管理器,没有什么特别的魔法发生。实际上,我从一个片段中调用了这段代码,并在调用之前将其转换为活动。由于有一个以片段为输入的类,我无法从活动中调用它,因此它无法重复使用。否则,当您只从片段调用getActivityForResult时,结果会返回到主活动。也许现在已经修复了,我们现在处于第N个版本。也许使用这种方法可以帮助您。祝你好运。 - danny117

0

你应该将上下文作为Activity传递,然后你会得到解决方案。尝试使用以下代码,它会起作用:

在非Activity类中:

public class nonActivity {

public static void method(Activity activity)
 {
     Intent intent = new Intent(activity, SecondActivity.class);
     activity. startActivityForResult(intent, REQUEST_CODE);
 }
}

在SecondActivity中
 Intent intent = getIntent();
 intent.putExtra("data", "data");   //here u can pass data to previous activity
 setResult(RESULT_OK, intent);
 finish();

在第一个Activity中

protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    try {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {
            String status = data.getStringExtra("data");
            //Do what u want with data
        }
    } catch (Exception e) {
        System.out.println("=====Exception=====" + e.toString());
    }
}

-1

如果您想将活动返回结果到普通类,假设它是一个带有自定义适配器的类。

  1. 您无法使用startActivityForResult,因为您不在活动中。
  2. 我所做的是从类中使用意图启动活动。然后我计算或执行必要操作。从这个活动中,我用MainActivity.the_method()方法向主类发送信息,然后在主活动中,我使用适配器对象调用adapter.getItem(position)来更改自定义适配器或执行必要操作。

希望这能给您提供一个想法。


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