Getting data from fragments on button click in host activity

时间:2016-10-20 19:56:47

标签: android android-fragments

So I'm creating this app that allows users to search for recipes by ingredients, categories, and preparation time.

Initially, I had 3 activities:

  • IngredientActivity, where the user chooses ingredients they have.
  • CategoryActivity, where they can choose multiple food categories from a list.
  • TimeActivity, which allows users to choose maximum preparation time.

However, it was such a hassle this way as I had to pass the data the user chose with an Intent to the next activity with a next button, and it was a mess always getting and adding extras until I got to the last activity, plus I wanted to be able to move freely between the 3 "pages", and not be restricted to going through them one by one.

This didn't seem efficient to me so I decided to change those activities into fragments and use a ViewPager to display them in tabs in a host activity (MainActivity), but it seems it's a different kind of hassle now.

I have a Search button in the MainActivity, and I'm having difficulty getting the data the user chose from all 3 fragments all at once when the Search button is clicked. I read about interfaces, but I'm not sure if it's the solution. I thought maybe I could define an OnSearchClickListener interface in all 3 fragments, but can I implement one interface for 3 fragments, with each fragment returning different data?

Did I make a mistake transitioning to fragments? However, it seemed the most efficient way to do it... How can I get all the data from the fragments when the search button is clicked?

2 个答案:

答案 0 :(得分:1)

Note: updated upon clarifications in comments

I would do the following:

  1. In each of the three fragments, implement method getSearchCriteria, with each returning value specific to that fragment.

  2. Implement one OnClickListener for the search button - at the activity level.

  3. Inside that listener, call getSearchCriteria on each of the fragments - and do whatever you need to do with all the collated results, something like this:

    findViewById(R.id.button_search).setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            List<String> ingredients = ingredientFragment.getSearchCriteria();
            List<String> categories = categoryFragment.getSearchCriteria();
            int maxMinutes = timeFragment.getSearchCriteria();
    
            // now you have all three things together - do what you need to with them
        }
    });
    

答案 1 :(得分:1)

如果每次更新条件时都通知MainActivity,您可以更新各自的标准并在搜索时使用它们(请参阅onSearchClicked)

IngredientFragment.java

public class IngredientFragment extends Fragment {
    EditText editText;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_ingredient, container, false);
        editText = (EditText)view.findViewById(R.id.edit_text);//assuming user type in the criteria in an edit box
        return view;
    }

    public void onClick(View view){//user interaction to signal criteria updated. Replace this with onItemClickListener etc, if you are using ListView
        if (mListener != null) {
            mListener.onIngredientCriteriaUpdated(String.valueOf(editText.getText()));
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnIngredientFragmentListener) {
            mListener = (OnIngredientFragmentListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnIngredientFragmentListener");
        }
    }

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

    public interface OnIngredientFragmentListener {
        // TODO: Update argument type and name
        void onIngredientCriteriaUpdated(String criteria);
    }
}

CategoryFragment.java

public class CategoryFragment extends Fragment {
    EditText editText;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_category, container, false);
        editText = (EditText)view.findViewById(R.id.edit_text);//assuming user type in the criteria in an edit box
        return view;
    }

    public void onClick(View view){//user interaction to signal criteria updated. Replace this with onItemClickListener etc, if you are using ListView
        if (mListener != null) {
            mListener.onCategoryCriteriaUpdated(String.valueOf(editText.getText()));
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnCategoryFragmentListener) {
            mListener = (OnCategoryFragmentListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnCategoryFragmentListener");
        }
    }

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

    public interface OnCategoryFragmentListener {
        // TODO: Update argument type and name
        void onCategoryCriteriaUpdated(String criteria);
    }
}

TimeFragment.java

public class TimeFragment extends Fragment {
    EditText editText;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_category, container, false);
        editText = (EditText)view.findViewById(R.id.edit_text);//assuming user type in the criteria in an edit box
        return view;
    }

    public void onClick(View view){//user interaction to signal criteria updated
        if (mListener != null) {
            mListener.onTimeCriteriaUpdated(String.valueOf(editText.getText()));
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnTimeFragmentListener) {
            mListener = (OnTimeFragmentListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnTimeFragmentListener");
        }
    }

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

    public interface OnTimeFragmentListener {
        // TODO: Update argument type and name
        void onTimeCriteriaUpdated(String criteria);
    }
}

MainActivity.java(部分代码)

public class MainActivity extends AppCompatActivity implements
    IngredientFragment.OnIngredientFragmentListener,
    CategoryFragment.OnCategoryFragmentListener,
    TimeFragment.OnTimeFragmentListener {

    private String ingredientCriteria;
    private String categoryCriteria;
    private String timeCriteria;

    :
    :
    :

    @Override
    public void onIngredientCriteriaUpdated(String criteria) {
        ingredientCriteria = criteria;
    }

    @Override
    public void onCategoryCriteriaUpdated(String criteria) {
        categoryCriteria = criteria;
    }

    @Override
    public void onTimeCriteriaUpdated(String criteria) {
        timeCriteria = criteria;
    }

    public void onSearchClicked(View view){//handler for your search button
        //do search using value of ingredientCriteria + categoryCriteria + timeCriteria
    }
}