如何修复“ java.lang.ClassCastException:活动必须实现片段的回调”

时间:2019-05-24 07:49:26

标签: java android android-fragments callback fragment

我是一名初学者,正在编写包含两个活动的代码。两者都有自己的Fragments。在第一个活动(在其片段中),用户输入一些字段。结果将显示在第二个活动中(在其列表片段中)。

我尝试使用捆绑包手动获取状态。现在,我正在使用callback来做到这一点。但是,我收到一条错误消息java.lang.ClassCastException: Activity must implement fragment's callbacks

第一个活动是:

public class AssetRegistrationInfoPage extends Page {

    public static final String ASSET_TYPE_NAME_KEY = "assetTypeName";
    public static final String ASSET_ID_DATA_KEY = "assetID";
    public static final String PROJECT_CODE_DATA_KEY = "projectCode";
    public static final String REMARK_DATA_KEY = "remark";

    public AssetRegistrationInfoPage(ModelCallbacks callbacks, String title) {
        super(callbacks, title);
    }

    @Override
    public Fragment createFragment() {
        return AssetRegistrationInfoFragment.create(getKey());
    }

    @Override
    public void getReviewItems(ArrayList<ReviewItem> dest) {
        dest.add(new ReviewItem("Nama Asset", mData.getString(ASSET_TYPE_NAME_KEY), getKey(), 0, null));
        dest.add(new ReviewItem("Kode Asset", mData. getString(ASSET_ID_DATA_KEY), getKey(), 0, null));
        dest.add(new ReviewItem("Kode Project", mData.getString(PROJECT_CODE_DATA_KEY), getKey(),0,null));
        dest.add(new ReviewItem("Kondisi Asset", mData.getString(REMARK_DATA_KEY), getKey(), 0, null));
    }

    @Override
    public boolean isCompleted() {
        return (!TextUtils.isEmpty(mData.getString(ASSET_TYPE_NAME_KEY)) &&
                !TextUtils.isEmpty(mData.getString(ASSET_ID_DATA_KEY)) &&
                !TextUtils.isEmpty(mData.getString(PROJECT_CODE_DATA_KEY)) &&
                !TextUtils.isEmpty(mData.getString(REMARK_DATA_KEY)));
    }
}

第一个片段:

public class AssetRegistrationInfoFragment extends Fragment {

    private static final String ARG_KEY = "key";

    private PageFragmentCallbacks mCallbacks;
    private String mKey;
    private AssetRegistrationInfoPage mPage;
    private TextView mAssetID;
    private AutoCompleteTextView mAssetTypeName, mProjectCode;

    private TextView mRemark;

    private Button mTakePicture;
    static final int REQUEST_PICTURE_CAPTURE = 1;
    private String pictureFilePath;
    Bitmap bitmap;
    ImageView mImgView;

    ArrayList<String> projectCodes = new ArrayList<String>();
    ArrayList<String> assetTypeNames = new ArrayList<String>();

    public static AssetRegistrationInfoFragment create(String key) {
        Bundle args = new Bundle();
        args.putString(ARG_KEY, key);

        AssetRegistrationInfoFragment fragment = new AssetRegistrationInfoFragment();
        fragment.setArguments(args);
        return fragment;
    }


    public AssetRegistrationInfoFragment() {
    }

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

        Bundle args = getArguments();
        mKey = args.getString(ARG_KEY);
        mPage = (AssetRegistrationInfoPage) mCallbacks.onGetPage(mKey);

    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        boolean cancel = false;

        mAssetTypeName.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1,
                                          int i2) {
            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            }

            @Override
            public void afterTextChanged(Editable editable) {
                mPage.getData().putString(AssetRegistrationInfoPage.ASSET_TYPE_NAME_KEY,
                        (editable != null) ? editable.toString() : null);
                mPage.notifyDataChanged();
            }

        });


        mAssetID.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1,
                                          int i2) {
            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            }

            @Override
            public void afterTextChanged(Editable editable) {
                mPage.getData().putString(AssetRegistrationInfoPage.ASSET_ID_DATA_KEY,
                            (editable != null) ? editable.toString() : null);
                mPage.notifyDataChanged();
            }
        });

        mProjectCode.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1,
                                          int i2) {
            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void afterTextChanged(Editable editable) {


                mPage.getData().putString(AssetRegistrationInfoPage.PROJECT_CODE_DATA_KEY,
                        (editable != null) ? editable.toString() : null);
                mPage.notifyDataChanged();

            }
        });

        mRemark.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1,
                                          int i2) {
            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            }

            @Override
            public void afterTextChanged(Editable editable) {
                mPage.getData().putString(AssetRegistrationInfoPage.REMARK_DATA_KEY,
                        (editable != null) ? editable.toString() : null);
                mPage.notifyDataChanged();
            }
        });

    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_page_asset_registration_info, container, false);

        ((TextView) view.findViewById(android.R.id.title)).setText(mPage.getTitle());

        getAssetType();
        mAssetTypeName = ((AutoCompleteTextView) view.findViewById(R.id.assetTypeName));
        mAssetTypeName.setText(mPage.getData().getString(AssetRegistrationInfoPage.ASSET_TYPE_NAME_KEY));
        ArrayAdapter<String> assetTypeNameAdapter = new ArrayAdapter<String>
                (getActivity(), android.R.layout.simple_dropdown_item_1line, assetTypeNames);

        mAssetTypeName.setAdapter(assetTypeNameAdapter);


        mAssetID = ((TextView) view.findViewById(R.id.assetID));
        mAssetID.setText(mPage.getData().getString(AssetRegistrationInfoPage.ASSET_ID_DATA_KEY));

        getProjects();

        mProjectCode = ((AutoCompleteTextView) view.findViewById(R.id.projectCode));
        mProjectCode.setText(mPage.getData().getString(AssetRegistrationInfoPage.PROJECT_CODE_DATA_KEY));
        mProjectCode.setThreshold(1);

        ArrayAdapter<String> projectCodeAdapter = new ArrayAdapter<String>
                (getActivity(), android.R.layout.simple_dropdown_item_1line, projectCodes);
        mProjectCode.setAdapter(projectCodeAdapter);

        mRemark =  ((TextView) view.findViewById(R.id.remark));
        mRemark.setText(mPage.getData().getString(AssetRegistrationInfoPage.REMARK_DATA_KEY));

        return view;

    }


    private void getProjects() {

        ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);

        Call<List<Project>> call = apiService.getProjects("");

        call.enqueue(new Callback<List<Project>>() {
            @Override
            public void onResponse(Call<List<Project>> call, Response<List<Project>> response) {

                for (Project project : response.body()) {
                    projectCodes.add(project.getProjectCode());
                }
            }

            @Override
            public void onFailure(Call<List<Project>> call, Throwable t) {
                Toast.makeText(getActivity(), "Unable to fetch Data " , Toast.LENGTH_LONG).show();
            }

        });
    }

    private void getAssetType() {

        ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);

        Call<List<AssetType>> call = apiService.getAssetTypes("");

        call.enqueue(new Callback<List<AssetType>>() {
            @Override
            public void onResponse(Call<List<AssetType>> call, Response<List<AssetType>> response) {
                for (AssetType assetType : response.body()) {
                    assetTypeNames.add(assetType.getName());
                }
            }

            @Override
            public void onFailure(Call<List<AssetType>> call, Throwable t) {
                Toast.makeText(getActivity(), "Unable to fetch Data ", Toast.LENGTH_LONG).show();
            }

        });



    }



    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        if (!(activity instanceof PageFragmentCallbacks)) {
            throw new ClassCastException("Activity must implement PageFragmentCallbacks");
        }

        mCallbacks = (PageFragmentCallbacks) activity;
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mCallbacks = null;
    }


    @Override
    public void setMenuVisibility(boolean menuVisible) {
        super.setMenuVisibility(menuVisible);

        // In a future update to the support library, this should override setUserVisibleHint
        // instead of setMenuVisibility.
        if (  mAssetTypeName != null && mAssetID != null && mProjectCode != null && mRemark != null){
            InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(
                    Context.INPUT_METHOD_SERVICE);
            if (!menuVisible) {
                imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
            }
        }
    }

}

第二页

public class AssetRegConfirmationPage extends Page {

    public static final String ASSET_TYPE_NAME_KEY = "assetTypeName";

    public AssetRegConfirmationPage(ModelCallbacks callbacks, String title) {
        super(callbacks, title);
    }

    @Override
    public Fragment createFragment() {
        return AssetRegConfirmationFragment.create(getKey());
    }

    @Override
    public void getReviewItems(ArrayList<ReviewItem> dest) {
        dest.add(new ReviewItem("Nama Asset", mData.getString(ASSET_TYPE_NAME_KEY), getKey(), 0, null));
    }
}

第二个片段

public class AssetRegConfirmationFragment extends ListFragment implements ModelCallbacks {
    private static final String ARG_KEY = "key";
    private Callbacks mCallbacks;
    private AbstractWizardModel mWizardModel;
    private List<ReviewItem> mCurrentReviewItems;

    private ReviewAdapter mReviewAdapter;

    public AssetRegConfirmationFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mReviewAdapter = new ReviewAdapter();
    }

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

        TextView titleView = (TextView) rootView.findViewById(android.R.id.title);
        titleView.setText(R.string.review);
        titleView.setTextColor(getResources().getColor(R.color.colorPrimaryOld));

        ListView listView = (ListView) rootView.findViewById(android.R.id.list);
        setListAdapter(mReviewAdapter);
        listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        return rootView;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        if (!(activity instanceof Callbacks)) {
            throw new ClassCastException("Activity must implement fragment's callbacks");
        }

        mCallbacks = (Callbacks) activity;

        mWizardModel = mCallbacks.onGetModel();
        mWizardModel.registerListener(this);
        onPageTreeChanged();
    }

    @Override
    public void onPageTreeChanged() {
        onPageDataChanged(null);
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mCallbacks = null;

        mWizardModel.unregisterListener(this);
    }

    @Override
    public void onPageDataChanged(Page changedPage) {
        ArrayList<ReviewItem> reviewItems = new ArrayList<ReviewItem>();
        for (Page page : mWizardModel.getCurrentPageSequence()) {
            page.getReviewItems(reviewItems);
        }
        Collections.sort(reviewItems, new Comparator<ReviewItem>() {
            @Override
            public int compare(ReviewItem a, ReviewItem b) {
                return a.getWeight() > b.getWeight() ? +1 : a.getWeight() < b.getWeight() ? -1 : 0;
            }
        });
        mCurrentReviewItems = reviewItems;

        if (mReviewAdapter != null) {
            mReviewAdapter.notifyDataSetInvalidated();
        }
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        mCallbacks.onEditScreenAfterReview(mCurrentReviewItems.get(position).getPageKey());
    }

    public interface Callbacks {
        AbstractWizardModel onGetModel();
        void onEditScreenAfterReview(String pageKey);
    }

    private class ReviewAdapter extends BaseAdapter {
        @Override
        public boolean hasStableIds() {
            return true;
        }

        @Override
        public int getItemViewType(int position) {
            return 0;
        }

        @Override
        public int getViewTypeCount() {
            return 1;
        }

        @Override
        public boolean areAllItemsEnabled() {
            return true;
        }

        @Override
        public Object getItem(int position) {
            return mCurrentReviewItems.get(position);
        }

        @Override
        public long getItemId(int position) {
            return mCurrentReviewItems.get(position).hashCode();
        }

        @Override
        public View getView(int position, View view, ViewGroup container) {
            LayoutInflater inflater = LayoutInflater.from(getActivity());
            View rootView = inflater.inflate(R.layout.list_item_review, container, false);

            ReviewItem reviewItem = mCurrentReviewItems.get(position);
            String value = reviewItem.getDisplayValue();
            if (TextUtils.isEmpty(value)) {
                value = "(None)";
            }
            ((TextView) rootView.findViewById(android.R.id.text1)).setText(reviewItem.getTitle());
            ((TextView) rootView.findViewById(android.R.id.text2)).setText(value);
            return rootView;
        }

        @Override
        public int getCount() {
            return mCurrentReviewItems.size();
        }
    }

    public static AssetRegConfirmationFragment create(String key) {
        Bundle args = new Bundle();
        args.putString(ARG_KEY, key);

        AssetRegConfirmationFragment fragment = new AssetRegConfirmationFragment();
        fragment.setArguments(args);
        return fragment;
    }
}

我不知道该怎么做。

这是Page源代码:

public abstract class Page implements PageTreeNode {
    /**
     * The key into {@link #getData()} used for wizards with simple (single) values.
     */
    public static final String SIMPLE_DATA_KEY = "_";

    protected ModelCallbacks mCallbacks;

    /**
     * Current wizard values/selections.
     */
    protected Bundle mData = new Bundle();
    protected String mTitle;
    protected boolean mRequired = false;
    protected String mParentKey;


    protected Page(ModelCallbacks callbacks, String title) {
        mCallbacks = callbacks;
        mTitle = title;
    }



    public Bundle getData() {
        return mData;
    }

    public String getTitle() {
        return mTitle;
    }

    public boolean isRequired() {
        return mRequired;
    }

    void setParentKey(String parentKey) {
        mParentKey = parentKey;
    }

    @Override
    public Page findByKey(String key) {
        return getKey().equals(key) ? this : null;
    }

    @Override
    public void flattenCurrentPageSequence(ArrayList<Page> dest) {
        dest.add(this);
    }

    public abstract Fragment createFragment();

    public String getKey() {
        return (mParentKey != null) ? mParentKey + ":" + mTitle : mTitle;
    }

    public abstract void getReviewItems(ArrayList<ReviewItem> dest);

    public boolean isCompleted() {
        return true;
    }

    public Bitmap getPicture() {
        return  mData.getParcelable(getKey() + "_" + getTitle().trim());
    }

    public void resetData(Bundle data) {
        mData = data;
        notifyDataChanged();
    }

    public void notifyDataChanged() {
        mCallbacks.onPageDataChanged(this);
    }

    public Page setRequired(boolean required) {
        mRequired = required;
        return this;
    }
}

1 个答案:

答案 0 :(得分:0)

second fragment中查看以下代码:

if (!(activity instanceof Callbacks)) {
    throw new ClassCastException("Activity must implement fragment's callbacks");
}

您使用activity的{​​{1}}应该实现second fragment接口,例如:

Callbacks