1. 代替重写 Activity 的 onActivityResult
项目中比较多的,某一个Activity
使用startActivityForResult()
从Target Actiivty
拿一个结果,之前在网上看到一个方案,通过借助一个无视图的Fragment
来进行实现,这样没必要重写onActivityResult()
,借鉴下思路,改了下代码,用在了项目中,暂时也没发现有什么问题
使用场景:同一个进程的中的两个Activity
来使用
1.0 StartForResultManager
/**
* @author g&c
* @date 2018/01/15
* 避免使用 onActivityResult
* 通过一个没有视图的 Fragment
* 从 Target Activity 获取数据
*
* 暂时考虑不使用单例,用后即焚
*/
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 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()
若使用时,有啥问题,或者遇到不适合使用的场景,请留言指出