Adapter启动ViewEvent后,HomeFragment的onActivityResult未触发如何解决?
这个问题我之前也碰到过,核心原因是你在Adapter里调用了Activity的startActivityForResult(),但宿主Activity没有把返回结果转发给对应的Fragment,或者说,你应该让Fragment自己来启动这个Activity,这样结果会直接回调到Fragment的onActivityResult()方法里。下面给你几个可行的解决方案:
方案一:让宿主Activity转发结果给Fragment
如果不想改动太多Adapter的代码,可以在HomeFragment所在的Activity中重写onActivityResult(),手动把结果传递给HomeFragment:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // 找到你的HomeFragment实例(这里需要替换成你实际的Fragment容器ID或Tag) HomeFragment homeFragment = (HomeFragment) getSupportFragmentManager() .findFragmentById(R.id.fragment_container); if (homeFragment != null) { // 把结果转发给Fragment homeFragment.onActivityResult(requestCode, resultCode, data); } }
这种方式简单直接,但缺点是耦合性比较高,Activity需要知道Fragment的存在。
方案二:让Fragment负责启动Activity(更推荐)
更好的做法是让Fragment来处理Activity的启动逻辑,避免Adapter直接操作Activity。可以通过接口回调的方式实现:
第一步:在Adapter中定义点击回调接口
修改EventListAdapter,添加一个回调接口来通知Fragment处理点击事件:
public class EventListAdapter extends ArrayAdapter<WorkdayEvent> { private Context mContext; private OnEventClickListener mClickListener; // 定义回调接口 public interface OnEventClickListener { void onEventItemClicked(WorkdayEvent event); } // 修改构造方法,传入回调实例 public EventListAdapter(@NonNull Context context, int resource, @NonNull List<WorkdayEvent> objects, OnEventClickListener listener) { super(context, resource, objects); mContext = context; mClickListener = listener; } @NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { setupImageLoader(); LayoutInflater inflater = LayoutInflater.from(mContext); convertView = inflater.inflate(R.layout.event_list_layout, parent, false); WorkdayEvent event = getItem(position); convertView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 调用回调,让Fragment处理启动逻辑 mClickListener.onEventItemClicked(event); } }); return convertView; } }
第二步:在HomeFragment中实现回调并启动Activity
让HomeFragment实现刚才定义的接口,然后在回调里用Fragment的startActivityForResult()启动ViewEvent:
public class HomeFragment extends Fragment implements EventListAdapter.OnEventClickListener { // ... 其他已有代码 // 创建Adapter的时候传入当前Fragment作为回调 private void setupAdapter() { EventListAdapter eventListAdapter = new EventListAdapter(getContext(), 0, events, this); eventListView.setAdapter(eventListAdapter); } @Override public void onEventItemClicked(WorkdayEvent event) { Bundle bundle = new Bundle(); bundle.putSerializable("EVENT", event); Intent intent = new Intent(getContext(), ViewEvent.class); intent.putExtra("EVENTBUNDLE", bundle); // 使用Fragment的startActivityForResult,结果会直接回调到当前Fragment startActivityForResult(intent, DELETE_EVENT); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == DELETE_EVENT && resultCode == Activity.RESULT_OK) { // 处理逻辑 EventListAdapter eventListAdapter = new EventListAdapter(getContext(), 0, events); eventListView.setAdapter(eventListAdapter); } } }
这样修改后,ViewEvent结束时的结果会直接传递到HomeFragment的onActivityResult(),不需要Activity中转。
方案三:使用最新的Activity Result API(推荐,适配AndroidX)
如果你的项目使用AndroidX,建议直接使用Activity Result API代替已废弃的startActivityForResult(),这种方式更简洁也更可靠:
在HomeFragment中注册结果回调
public class HomeFragment extends Fragment { private ActivityResultLauncher<Intent> mViewEventLauncher; private List<WorkdayEvent> events; private ListView eventListView; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 注册Activity结果回调 mViewEventLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == Activity.RESULT_OK) { // 这里处理返回结果,替代原来的onActivityResult EventListAdapter eventListAdapter = new EventListAdapter(getContext(), 0, events); eventListView.setAdapter(eventListAdapter); } } ); } // 实现Adapter的点击回调(同方案二) @Override public void onEventItemClicked(WorkdayEvent event) { Bundle bundle = new Bundle(); bundle.putSerializable("EVENT", event); Intent intent = new Intent(getContext(), ViewEvent.class); intent.putExtra("EVENTBUNDLE", bundle); // 用launcher启动Activity mViewEventLauncher.launch(intent); } }
这种方式不需要重写onActivityResult(),代码结构更清晰,也避免了转发问题。
内容的提问来源于stack exchange,提问作者Marcus Birkeland

