可以代替 onActivityResult 的办法

1. 代替重写 Activity 的 onActivityResult

项目中比较多的,某一个Activity使用startActivityForResult()Target Actiivty拿一个结果,之前在网上看到一个方案,通过借助一个无视图的Fragment来进行实现,这样没必要重写onActivityResult(),借鉴下思路,改了下代码,用在了项目中,暂时也没发现有什么问题

使用场景:同一个进程的中的两个Activity来使用


1.0 StartForResultManager

/**
 * @author g&c
 * @date 2018/01/15
 * 避免使用 onActivityResult
 * 通过一个没有视图的 Fragment
 * 从 Target Activity 获取数据
 * <p>
 * 暂时考虑不使用单例,用后即焚
 */
public class StartForResultManager {
    private static final String TAG = StartForResultManager.class.getSimpleName();
    private StartCallbackFragment mStartCallbackFragment;

    /**
     * 跳转 Activity 的 Class 对象
     */
    private Class<?> mTargetClass;

    /**
     * 从开始 Activity 传给数据源目标 Activity的数据
     */
    private Bundle mDataBundle;

    public static StartForResultManager get() {
        return new StartForResultManager();
    }

    private StartForResultManager() {
    }

    public StartForResultManager from(Activity activity) {
        mStartCallbackFragment = crateStartCallbackFragment(activity);
        return this;
    }

    public StartForResultManager from(Fragment fragment) {
        this.from(fragment.getActivity());
        return this;
    }

    public StartForResultManager to(Class<?> clazz) {
        this.mTargetClass = clazz;
        return this;
    }


    public StartForResultManager bundle(Bundle bundle) {
        mDataBundle = new Bundle(bundle);
        return this;
    }

    /**
     * 开启目标 Activity
     *
     * @param callback 结果回调
     */
    public void startForResult(@NonNull CallbackAdapter callback) {
        if (mStartCallbackFragment == null) {
            throw new NullPointerException("From activity is null , forget from() ?");
        }
        Activity activity = mStartCallbackFragment.getActivity();
        if (activity == null) {
            // 若为 Activity 为 Null,说明场景不再适合使用 StartForResultManager
            throw new NullPointerException("Surprise , something is error , perhaps this is love");
        }
        if (mTargetClass == null) {
            throw new NullPointerException("mTargetClass is null , forget to() ?");
        }
        Intent intent = new Intent(activity, mTargetClass);
        if (mDataBundle != null) {
            intent.putExtras(mDataBundle);
        }
        fragmentStartForResult(intent, callback.hashCode(), callback);
    }

    /**
     * 创建中间桥梁 Fragment
     *
     * @param activity 启动 Activity :桥梁 Fragment 所依赖的 Activity
     * @return Fragment
     */
    private StartCallbackFragment crateStartCallbackFragment(Activity activity) {
        StartCallbackFragment resultFragment = findStartCallbackFragment(activity);
        if (resultFragment == null) {
            resultFragment = new StartCallbackFragment();
            FragmentManager fragmentManager = activity.getFragmentManager();
            fragmentManager
                    .beginTransaction()
                    .add(resultFragment, TAG)
                    .commitAllowingStateLoss();
            fragmentManager.executePendingTransactions();
        }
        return resultFragment;
    }

    /**
     * 查找中间桥梁 Fragment
     *
     * @param activity 启动 Activity
     * @return Fragment
     */
    private StartCallbackFragment findStartCallbackFragment(Activity activity) {
        return (StartCallbackFragment) activity.getFragmentManager().findFragmentByTag(TAG);
    }

    /**
     * 通过桥梁 Fragment 启动数据源目标 Activity
     *
     * @param intent      Intent
     * @param requestCode 请求码
     * @param callback    结果回调
     */
    private void fragmentStartForResult(Intent intent, int requestCode, CallbackAdapter callback) {
        mStartCallbackFragment.startForResult(intent, requestCode, callback);
    }

    /**
     * 结果回调适配
     */
    public static class CallbackAdapter implements Callback {

        @Override
        public void onResultError() {

        }

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

        }
    }

    /**
     * 结果回调接口
     */
    private interface Callback {

        /**
         * 当拿结果出现错误时
         * 当 Intent data 为 null 时
         */
        void onResultError();

        /**
         * 结果回调
         *
         * @param resultCode 结果码
         * @param data       数据
         */
        void onActivityResult(int resultCode, Intent data);
    }
}

1.1 StartCallbackFragment

无视图的中间桥梁 Fragment

/**
 * @author g&c
 * @date 2018/01/15
 * 桥梁,没有界面
 * 利用 startForResult(),onActivityResult()方法
 * 从目标数据源 TargetActivity 获取数据,返回到启动的 Activity
 */
public final class StartCallbackFragment extends Fragment {
    /**
     * 存放 Callback
     */
    private SparseArray<StartForResultManager.CallbackAdapter> mCallbackArr;

    public StartCallbackFragment() {
        mCallbackArr = new SparseArray<>();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

    /**
     * StartCallbackFragment 开启目标 Activity
     *
     * @param intent      意图
     * @param requestCode 请求码
     * @param callback    回调
     */
    public void startForResult(Intent intent, int requestCode,
                               StartForResultManager.CallbackAdapter callback) {
        mCallbackArr.put(requestCode, callback);
        startActivityForResult(intent, requestCode);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        // Callback 结果回调
        StartForResultManager.CallbackAdapter callback = mCallbackArr.get(requestCode);
        if (callback == null) {
            return;
        }
        // 移除 Callback
        mCallbackArr.remove(requestCode);
        if (data == null) {
            // 回调错误方法
            callback.onResultError();
            return;
        }
        // 结果回调
        callback.onActivityResult(resultCode, data);
    }
}

CallbackAdapter有两个方法,使用时,若不关心拿到不到结果的情况,就没必要重写onResultError()方法,只关心onActivityResult()就可以


2. 使用

2.1 来源Activity

public class StartCallbackActivity extends AppCompatActivity {
    private TextView mTvContent;

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

    private void initView() {
        Button bt = findViewById(R.id.activity_start_callback_bt);
        mTvContent = findViewById(R.id.activity_start_callback_tv);
        bt.setOnClickListener(v -> start("116", "20180116 You happy, You ok"
                , StartCallbackResultActivity.class));

        Button bt2 = findViewById(R.id.activity_start_callback_bt2);
        bt2.setOnClickListener(v -> start("117", "20180116 This is love"
                , StartCallbackResult2Activity.class));
    }

    private void start(String key, String value, Class<?> cla) {
        // 数据
        Bundle b = new Bundle();
        b.putString(key, value);

        // 跳转
        StartForResultManager
                .get()
                .from(StartCallbackActivity.this)
                .to(cla)
                .bundle(b)
                .startForResult(new StartForResultManager.CallbackAdapter() {
                    @Override
                    public void onActivityResult(int resultCode, Intent data) {
                        super.onActivityResult(resultCode, data);
                        String str = data.getStringExtra("text");
                        if (resultCode == Activity.RESULT_OK && !TextUtils.isEmpty(str)) {
                            mTvContent.setText(str);
                        }
                    }

                    @Override
                    public void onResultError() {
                        super.onResultError();
                        String str = "没有返回有效数据";
                        mTvContent.setText(str);
                    }
                });
    }
}

布局就是两个Button,一个TextView,点击一个Button跳转对应的一个Target Activity,然后在Target Activity使用setResult()来返回结果显示在TextView

StartCallbackActivity来源 Activity

StartCallbackResultActivity,StartCallbackResult2Activity为两个不同的 Target Activity


2.1 Target Activity

StartCallbackResultActivity中有一个Button,点击将数据返回

/**
 * @author g&c
 * @date 2018/01/15
 * Target Activity
 * 接收来源 Activity 传递过来的一个字符串
 * 返回给来源 Activity 一个字符串
 */
public class StartCallbackResultActivity extends AppCompatActivity {
    private String mStringData = "-1";

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

    private void getData() {
        Intent intent = getIntent();
        if (intent == null) {
            return;
        }
        Bundle extras = intent.getExtras();
        if (extras == null) {
            return;
        }
        mStringData = (String) extras.get("116");
    }

    private void initView() {
        Button bt = findViewById(R.id.activity_start_result_bt);
        bt.setOnClickListener(v -> {
            Intent intent = new Intent();
            intent.putExtra("text", "12345678");
            setResult(Activity.RESULT_OK, intent);
            finish();
        });

        TextView tv = findViewById(R.id.activity_start_result_tv);
        tv.setText(mStringData);
    }
}

关键就一个setResult()方法


3. 最后

使用说明:

StartForResultManager必须 调用from()指定来源 Activity,使用to()来指定Target Activity,否则StartForResultManager.startForResult()方法中会抛出NullPointerException,可以看一眼代码

来源 Activity需要将数据传递到Target Activity,可以使用bundle()传递一个Bundle,若不需要数据,就没必要调用bundle()


若使用时,有啥问题,或者遇到不适合使用的场景,请留言指出

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,548评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,069评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,985评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,305评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,324评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,030评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,639评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,552评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,081评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,194评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,327评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,004评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,688评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,188评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,307评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,667评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,337评论 2 358