【问题标题】:get onActivityResult on Fragment from Activity that called inside RecyclerView.Adapter从在 RecyclerView.Adapter 内部调用的 Activity 中获取 Fragment 上的 onActivityResult
【发布时间】:2016-07-31 08:39:14
【问题描述】:

好的,这是我的问题

  1. 我有一个包含 RecyclerView 的 Fragment,当然还有一个包含内容的适配器(称为 ApprovalCutiCardAdapter)。
  2. ApprovalCutiCardAdapter 里面我在卡片上设置了 OnClickListener,当卡片被点击时,它会启动一个名为 DetailApprovalCuti 的 Activity。这是我启动活动的代码

    ((Activity) MyApplication.getmContext()).startActivityForResult(detailApprovalCutiIntent, 1);
    
  3. DetailApprovalCuti 中,我正在执行finishActivity(1) 以获取onActivityResult 的事件。但是该事件并没有在任何地方被调用(在托管片段的 Activity 和片段中)

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        Log.e("result", "ApprovalIzinCutiFragment");
        super.onActivityResult(requestCode, resultCode, data);
    }
    
  4. 这是我启动活动的代码

    @Override
    public void onBindViewHolder(final CutiViewHolder holder, final int position) {
    ....
    holder.cv.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent detailApprovalCutiIntent = new Intent(MyApplication.getmContext(), DetailApprovalCuti.class);
            Bundle b = new Bundle();
            b.putParcelable("cuti", ApprovalCutiCardAdapter.allCuti.get(position));
            b.putParcelable("process_cuti", ApprovalCutiCardAdapter.allCuti.get(position).getProcessCuti());
            detailApprovalCutiIntent.putExtras(b);
            ((Activity)MyApplication.getmContext()).startActivityForResult(detailApprovalCutiIntent,1);
        }
    });
    
    ....
    }
    
  5. 这是我完成活动的代码

    btnReject.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            new AlertDialog.Builder(DetailApprovalCuti.this)
                    .setTitle("Peringatan")
                    .setMessage("Apakah anda yakin?")
                    .setIcon(android.R.drawable.ic_dialog_alert)
                    .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            setResult(1);
                            finish();
                        }
                    }).setNegativeButton(android.R.string.no, null).show();
        }
    });
    

【问题讨论】:

  • 你的“但那个事件并没有被到处调用”不清楚,你的意思是什么?有什么问题以及期望的行为是什么?
  • 我想听一个在DetailApprovalCuti关闭后调用的事件,这意味着它将回到片段,但片段上的onActivityResult不起作用
  • 您是否收到错误消息?或者您想将 ActivityOnResult 重定向到托管 Fragment 的 Activity?
  • 我没有看到任何错误,onActivityResult 内部的 Log 没有运行,我想从关闭的 Activity 发送数据到持有 RecyclerView 的 Fragment
  • 你在Fragment中定义了onActivityResult吗?

标签: android android-fragments native onactivityresult


【解决方案1】:

问题在于,在下一行中,您从一个可能不是您期望的 Activity 调用 startActivityForResult()

((Activity)MyApplication.getmContext()).startActivityForResult(detailApprovalCutiIntent, 1);

考虑到您的适配器是从Fragment 设置的,您应该将上面的行修改为:

fragment.getActivity().startActivityForResult(detailApprovalCutiIntent, 1);

经验教训

永远不要使用单例,Singletons are Pathological Liars

PS:单实例很好,但单例(如全局变量)是一种糟糕的设计,必须避免。

【讨论】:

    【解决方案2】:

    您的 Activity 应该由 Fragment “for-results”启动,例如:startActivityForResult(detailApprovalCutiIntent, 1); 而不是 ((Activity) MyApplication.getmContext()).startActivityForResult(detailApprovalCutiIntent, 1);- 然后在托管您可以处理的 Fragment 的 Activity onActivityResult - 但是您想将此事件传播到 Fragment。所以你打电话给super.onActivityResult(requestCode, resultCode, data); - 你会得到类似的东西:

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
       super.onActivityResult(requestCode, resultCode, data);   
    }
    

    然后在 Fragment 中你可以处理onActivityResult 回调。

    请查看这些密切相关的问题并尝试选择的答案:

    我希望这能带来一些启发。

    【讨论】:

    • 我不能这样做 startActivityForResult(detailApprovalCutiIntent, 1); 因为它是在适配器内部调用的。 startActivityForResult 不能从适配器调用
    • @LyanDwiPangestu 您可以在适配器内的字段中保留WeakReferenceActivity。虽然我觉得你完成下一个Activity 的方式有问题。您必须先调用 setResult(),然后再调用 finish(),以便适配器的 Activity 调用其 onActivityResult()
    • @Sufian 你能举个例子说明WeakReference 是什么吗?
    • @LyanDwiPangestu 见this。只需在您的适配器中保留Activity 的引用,它应该没问题。正如我之前所说,问题在于你完成下一个活动的方式。
    • @LyanDwiPangestu 也可以看到 WeakReference - stackoverflow.com/questions/299659/…
    【解决方案3】:

    我认为你的设计是不必要的复杂,它把 Activity、Fragment 和 RecyclerView 的适配器耦合得太紧了。

    试试这个:

    • 当适配器检测到卡片上的点击时,让它与它的父级(在本例中为 Fragment)进行通信。
    • 当 Fragment 收到点击通知时,让它通知其父级(Activity)
    • 当 Fragment 通知 Activity 时,让它(Activity)使用 startActivityForResult 启动新的 Activity
    • 当 Activity 在 onActivityResult 上得到结果时,让它对结果做任何它需要的事情。如果 Fragment 需要该结果,则让它将结果传达给 Fragment。

    接下来的问题是如何在 Fragment 和 Activity 之间进行通信。 “标准”的答案是创建一对接口,让Activity实现一个,Fragment实现另一个,然后使用接口方法来回调用。

    这可能很难正确执行,因为 Activity 和 Fragment 必须仔细跟踪彼此的生命周期,以免崩溃。

    我发现更好、更简单的解决方案是使用消息总线(例如 Otto)在它们之间传递消息。这样,Activity 和 Fragment 只需要在准备好时注册和注销总线,就可以完全回避生命周期问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-20
      • 2012-02-08
      • 2013-11-29
      • 2013-06-09
      • 1970-01-01
      • 2020-11-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多