如何修复:“无法将 activity 转换为片段

How to fix :"Cannot cast activity to fragment

我想要设置片段但仍然在 mainactivity 中访问父级activity。

我有 3 个布局 mainActivity M、片段 A 和布局弹出窗口 B,它们在片段 A 上的按钮点击时显示。 我想将数据从布局 B(片段)发送到带有界面的片段 A。 onAttach 程序,设置片段时它不起作用。仍在访问父 activity。此零点的结果。 这里的错误代码位于:

interfaceOnInputListener = (OnInputListener) context;

我尝试用 getActivity().getApplicationContext() 替换上下文。但是还是不行。

这里是 myPopUpWindow 中的完整代码

public class myPopUpWindow extends DialogFragment {

    private static final String TAG = "myPopUpWindow";

    public interface OnInputListener{
        void sendOutput(String output);
    }

    public OnInputListener interfaceOnInputListener;


    @Override
    public View onCreateView(LayoutInflater inflater, 
                             ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.popup_wind,container,false);

        final TextView tbxEdT = (TextView) view.findViewById(R.id.editText);
        Button btnOK = (Button) view.findViewById(R.id.btnOk);
        btnOK.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String strInput = tbxEdT.getText().toString();

                interfaceOnInputListener.sendOutput(strInput);
                getDialog().dismiss();
            }
        });

        return view;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            interfaceOnInputListener = (OnInputListener) context;
        } catch (ClassCastException e) {
            Log.e(TAG, "onAttach: ClassCastException: " + e.getMessage() );
        }
     }
}

这是主要activity代码

   public class MainActivity extends AppCompatActivity {

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

            loadFragment();

        }

        private boolean loadFragment(){
            getSupportFragmentManager().beginTransaction()
                       .replace(R.id.frame_container,new AFragment())
                       .addToBackStack(null)
                       .commit();
           return  true;
       }
   }

此处 xml 包含片段

的框架
<androidx.constraintlayout.widget.ConstraintLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context=".MainActivity">

            <FrameLayout
                android:id="@+id/frame_container"
                android:layout_width="395dp"
                android:layout_height="715dp"
                tools:layout_editor_absoluteX="8dp"
                tools:layout_editor_absoluteY="8dp">

            </FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

我想将数据从 myPopUpWindow 发送到片段 A。但是将 activity 转换为片段时出错。有什么建议吗?

我不确定你是如何管理它的,因为你没有分享 activity 代码。您不应该直接将 context 转换为您的界面。这可能会导致潜在的崩溃以及创建错误的代码,因为您的对话片段依赖于其调用者来实现。尝试使用以下方法。

在您的对话片段中:

public class YourDialogFragment : DialogFragment {
      @Nullable private OnInputListener onInputListener;

      public setInputListener(onInputListener : OnInputListener) {
            this.onInputListener = onInputListener
      }

      //Other codes here
      //Make sure to null check with this code before sending
      // if (this.onInputListener != null) { onInputListener.doSth() }

      @Override
      public void onDestroy {
            this.interfaceOnInputListener = null
            super. onDestroy()
      }

}

然后你可以在创建dialog fragment的时候通过暴露的方法来设置监听器,比如说你的activty中有这个功能

class YourActivity : AppCompatActivity {

    public void showDialog() {
        public final dialogFragment = YourDialogFragment()
        dialogFragment.setInputListener(this) //this can be whatever interface implmenetation you want
        dialogFragment.show(getSupportFragmentManager(), "TAG_HERE")
    }
}

这样即使后面重构逻辑,也不用担心类型转换失败或者context为null。这种方法的另一个好处是片段不再依赖于它的调用者来实现接口,所以它也有利于以后的测试。

经过各种变通,问题终于解决了。但我有意更改它并在 Fragment A 上,在 ActivityResult 上得到它。

弹出对话框中的代码

Intent intent = new Intent();
                intent.putExtra("class",spnSubClass.getSelectedItem().toString());
                intent.putExtra("month",strSelectedMonth);
                getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, intent);
                dismiss();

并在片段 A 中得到它:

@Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case POPUPDIALOG:
                if (resultCode == Activity.RESULT_OK) {
                    //--- get value from dialog
                    Bundle bundle = data.getExtras();
                    strClass = bundle.getString("class");
                    strMonth = bundle.getString("month");                                             
                    } else if (resultCode == Activity.RESULT_CANCELED) {
                //
                }
                break;
        }
    }

interfaceOnInputListener = (OnInputListener) getTargetFragment();

这是一个类似的程序。请参阅此以获得更多理解。

https://github.com/mitchtabian/DialogFragmentToFragment/tree/master/DialogFragmentFragment/app/src/main/java/codingwithmitch/com/dialogfragmentfragment