Sending data from activity to fragment using set m

2019-07-13 11:23发布

问题:

I've posted a question regarding of passing data from activity to a fragment. And I've learnt that implementing Parcelable to a POJO class is a right way of doing it. After some research I also understand that in order to pass data to a fragment should use Bundle instead of Intent.

My previous question --> Using same fragments but different content in Android

But now, my question is, what should I do in order to display a list of details (name, address, phone) using set methods when the cardview is clicked?

To be clear, what I want is

  • When first restaurant is clicked, the new intent that contains details fragment will be started. Inside the details fragment, it will display the restaurant name, address and phone of the first restaurant.

Can anyone guide me by showing me the code of two set of different details when two different restaurant cardview is clicked?

RestaurantListAdapter.java

I want to use if else statement under onClick, to display different details when different cardview is clicked

public class RestaurantListAdapter extends RecyclerView.Adapter<RestaurantListAdapter.ViewHolder>  {
    List<RestaurantList_Item> items;
    private static ClickListener clickListener;
    private Context context;

    public RestaurantListAdapter(){
        super();
        items = new ArrayList<RestaurantList_Item>();

        // POSITION 1
        RestaurantList_Item restaurant = new RestaurantList_Item();
        restaurant.setrImage(R.mipmap.img_anjappar);
        restaurant.setrName("Anjappar Indian Chettinad Restaurant");
        restaurant.setrCuisine("Indian");
        items.add(restaurant);

        // POSITION 2
        restaurant = new RestaurantList_Item();
        restaurant.setrImage(R.mipmap.img_morganfield);
        restaurant.setrName("Morganfield");
        restaurant.setrCuisine("Western");
        items.add(restaurant);

        // POSITION 3
        restaurant = new RestaurantList_Item();
        restaurant.setrImage(R.mipmap.img_nandos);
        restaurant.setrName("Nando's");
        restaurant.setrCuisine("Western");
        items.add(restaurant);

        // POSITION 4
        restaurant = new RestaurantList_Item();
        restaurant.setrImage(R.mipmap.img_shellout);
        restaurant.setrName("Shellout");
        restaurant.setrCuisine("Seafood");
        items.add(restaurant);

        // POSITION 5
        restaurant = new RestaurantList_Item();
        restaurant.setrImage(R.mipmap.img_beyond);
        restaurant.setrName("Beyond Veggie");
        restaurant.setrCuisine("Vegetarian");
        items.add(restaurant);

        // POSITION 6
        restaurant = new RestaurantList_Item();
        restaurant.setrImage(R.mipmap.img_myelephant);
        restaurant.setrName("My Elephant");
        restaurant.setrCuisine("Thai");
        items.add(restaurant);

        // POSITION 7
        restaurant = new RestaurantList_Item();
        restaurant.setrImage(R.mipmap.img_padangkota);
        restaurant.setrName("Nasi Kandar Padang Kota");
        restaurant.setrCuisine("Mamak");
        items.add(restaurant);

    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {

        View v = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.cardview_restaurant, viewGroup, false);
        ViewHolder viewHolder = new ViewHolder(v);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
        final RestaurantList_Item restaurant = items.get(position);
        viewHolder.resImage.setImageResource(restaurant.getrImage());
        viewHolder.restaurantName.setText(restaurant.getrName());
        viewHolder.cuisine.setText(restaurant.getrCuisine());
        viewHolder.itemView.setOnClickListener( new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Context context = v.getContext();
//                Toast.makeText(context, "Item clicked with position " +position, Toast.LENGTH_LONG).show();
                if(position == 0){
                    Intent i = new Intent(context, Restaurant.class);
                    context.startActivity(i);
                }
            }
        });
    }

    @Override
    public int getItemCount() {
        return items.size();
    }

    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
    }

    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
        public ImageView resImage;
        public TextView restaurantName;
        public TextView cuisine;

        public ViewHolder(final View itemView) {
            super(itemView);
            resImage = (ImageView) itemView.findViewById(R.id.resImage);
            restaurantName = (TextView) itemView.findViewById(R.id.restaurantName);
            cuisine = (TextView) itemView.findViewById(R.id.cuisine);
            itemView.setOnClickListener(this);
        }


        @Override
        public void onClick(View v) {
            clickListener.onItemClick(getAdapterPosition(), v);
        }

    }

    public void setOnItemClickListener (ClickListener clickListener){
        RestaurantListAdapter.clickListener = clickListener;
    }

    public interface ClickListener{
        void onItemClick (int position, View v);
    }
}

RestaurantModel.java

This is the POJO class that contains get set methods, I want to use the set methods to display restaurant details

public class RestaurantModel implements Parcelable{

    //empty constructor
    public RestaurantModel(){}

    //A constructor that initializes the Restaurant object
    public RestaurantModel(String resName, String resAddress, String resPhone, String resCuisine, String resPriceRange){
        this.resName = resName;
        this.resAddress =resAddress;
        this.resPhone = resPhone;
        this.resCuisine = resCuisine;
        this.resPriceRange = resPriceRange;
    }

    //Parcelling the object
    public RestaurantModel(Parcel in){
        String[] data = new String [5];
        in.readStringArray(data);
        this.resName = data[0];
        this.resAddress = data[1];
        this.resPhone = data[2];
        this.resCuisine = data[3];
        this.resPriceRange = data[4];

    }

    // variable main photo
    private int mainImage;

    //variables for details fragment
    private String resName, resAddress, resPhone, resCuisine, resPriceRange;

    //variables for menu fragment
    private int foodPhoto;
    private String foodPrice, foodDescription;

    /*get set methods*/
    public int getMainImage(){
        return mainImage;
    }

    public void setMainImage(int mainImage){
        this.mainImage = mainImage;
    }

    public String getResName(){
        return resName;
    }

    public void setResName(String resName){
        this.resName = resName;
    }

    public String getResAddress(){return resAddress;}

    public void setResAddress(String resAddress){this.resAddress = resAddress;}

    public String getResPhone(){return resPhone;}

    public void setResPhone(String resPhone){this.resPhone = resPhone;}

    public String getResCuisine(){return resCuisine;}

    public void setResCuisine(String resCuisine){this.resCuisine = resCuisine;}

    public String getResPriceRange(){return resPriceRange;}

    public void setResPriceRange(String resPriceRange){this.resPriceRange = resPriceRange;}

    public int getFoodPhoto(){return foodPhoto;}

    public void setFoodPhoto(int foodPhoto){this.foodPhoto = foodPhoto;}

    public String getFoodDescription(){return foodDescription;}

    public void setFoodDescription(String foodDescription){this.foodDescription = foodDescription;}

    public String getFoodPrice(){return foodPrice;}

    public void setFoodPrice(String foodPrice){this.foodPrice = foodPrice;}



    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeStringArray(new String[]{
                this.resName,this.resAddress,this.resPhone, this.resCuisine, this.resPriceRange
        });
    }

    // Creator
    public static final Parcelable.Creator<RestaurantModel> CREATOR = new Parcelable.Creator<RestaurantModel>(){
        @Override
        public RestaurantModel createFromParcel(Parcel source) {
            return new RestaurantModel(source);
        }

        @Override
        public RestaurantModel[] newArray(int size) {
            return new RestaurantModel[size];
        }
    };


}

Restaurant.java

This activity contains the fragments that will be shown when the cardview is clicked

public class Restaurant extends AppCompatActivity {

    private TabLayout tabLayout;
    private ViewPager viewPager;

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

        viewPager = (ViewPager) findViewById(R.id.viewpager);
        setupViewPager(viewPager);

        tabLayout = (TabLayout) findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(viewPager);

    }

    private void setupViewPager(ViewPager viewPager){
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFragment(new details(), "Details");
        adapter.addFragment(new menu(), "Menu");
        adapter.addFragment(new tableBooking(), "Table booking");
        viewPager.setAdapter(adapter);
    }

    class ViewPagerAdapter extends FragmentPagerAdapter{

        private final List<Fragment> fragmentList = new ArrayList<>();
        private final List<String> fragmentTitleList = new ArrayList<>();

        public ViewPagerAdapter(FragmentManager manager){
            super(manager);
        }

        @Override
        public Fragment getItem(int position) {
            return fragmentList.get(position);
        }

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

        public void addFragment (Fragment fragment, String title){
            fragmentList.add(fragment);
            fragmentTitleList.add(title);
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return fragmentTitleList.get(position);
        }
    }
}

Details.java

This class extends fragment that contains restaurant details such as name, address and phone

public class details extends Fragment {

    private TextView resName, resAddress, resPhone, resCuisine, resPriceRange;

    public details() {
        // Required empty public constructor
    }


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

/*        resName = (TextView) getView().findViewById (R.id.resName);
        resAddress = (TextView) getView().findViewById (R.id.resAddress);
        resPhone = (TextView) getView().findViewById (R.id.resPhone);
        resCuisine = (TextView) getView().findViewById (R.id.resCuisine);
        resPriceRange = (TextView) getView().findViewById (R.id.resPriceRange);*/



    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_details, container, false);
    }

}

Homepage.java

public class Homepage extends Activity {

    RecyclerView recyclerView;
    RecyclerView.LayoutManager llm;
    RecyclerView.Adapter adapter;
    private static final String TAG = Homepage.class.getSimpleName();

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

        recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        recyclerView.setHasFixedSize(true);

        llm = new LinearLayoutManager(Homepage.this);
        recyclerView.setLayoutManager(llm);

        adapter = new RestaurantListAdapter();
        recyclerView.setAdapter(adapter);

    }
}

EDIT: I'm not sure if I'm doing this correctly. I created multiple arraylist that describes different details for different restaurant. I put the code at onClick methods in RestaurantListAdapter.

  @Override
    public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
        final RestaurantList_Item restaurant = items.get(position);
        viewHolder.resImage.setImageResource(restaurant.getrImage());
        viewHolder.restaurantName.setText(restaurant.getrName());
        viewHolder.cuisine.setText(restaurant.getrCuisine());
        viewHolder.itemView.setOnClickListener( new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Context context = v.getContext();
                RestaurantModel rAnjappar = new RestaurantModel();
                details fragment = new details();
                Intent i = new Intent(context, Restaurant.class);

                // Array List
                ArrayList<RestaurantModel> a1 = new ArrayList<RestaurantModel>();
                rAnjappar.setResName("Anjappar");
                rAnjappar.setResAddress("Bandar Kinrara");
                rAnjappar.setResPhone("03-80807362");
                rAnjappar.setResCuisine("Mamak");
                rAnjappar.setResPriceRange("RM 30 for 2 person");

                ArrayList<RestaurantModel> a2 = new ArrayList<RestaurantModel>();
                rAnjappar.setResName("Morganfield");
                rAnjappar.setResAddress("Bandar Utama");
                rAnjappar.setResPhone("03-80807362");
                rAnjappar.setResCuisine("Western");
                rAnjappar.setResPriceRange("RM 60 for 2 person");

                // action when card view is clicked
                if(position == 0){
                    Bundle b1 = new Bundle();
                    b1.putParcelableArrayList("anjappar", a1);
                    fragment.setArguments(b1);
                    context.startActivity(i);

                }
            }
        });
    }

If this is acceptable, next thing I should do is retrieve the bundle in my fragment code right? But since I will be having multiple bundles, how am I supposed to retrieve all the bundles in a correct way?

回答1:

You can use setArguments() method of the fragment to pass your restaurant model class to new fragment while creating the new instance of it.You can get it back using getArguments() in newly created fragment's onCreate() method. You have to make your resturantModel.java class Serializable.

 public class RestaurantModel implements Serializable{
   ...
 }

Add data:-

   Bundle bundle = new Bundle();
   bundle.putSerializable("restaurant", restaurant);
   Fragment1 frag1 = new Fragment1();
   frag1.setArguments(bundle);

Get data :-

RestauranModel restaurant = (RestauranModel) getArguments().getSerializable("restaurant");

FYI: Difference between Parcelable and Serializable : https://stackoverflow.com/a/3323554/4690731



回答2:

Ok so from as far as i understand you can do following things

1 Add this method in Adapter

public RestaurantList_Item getItem(int pos) {
    return items.get(pos);
}

2. Homepage is your clicklistner activity (Hope so) in it

public void onItemClick(int position, view v) {
        RestaurantList_Item row_object = adapter.getItem(position); 
        Intent i = new Intent(context, Restaurant.class);
        i.putExtra(Common.Data_Object, row_object);
        startActivity(i);

    }

3. Replace code of Restaurant class

public class Restaurant extends AppCompatActivity {

    private TabLayout tabLayout;
    private ViewPager viewPager;
    private RestaurantList_Item row_object;

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

        getIntentData(getIntent());

        viewPager = (ViewPager) findViewById(R.id.viewpager);
        setupViewPager(viewPager);

        tabLayout = (TabLayout) findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(viewPager);

    }

    private void getIntentData(Intent i) {
        if (i != null) {

            row_object = i.getParcelableExtra(Common.Data_Object);
        }
    }

    private void setupViewPager(ViewPager viewPager){
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());

        Fragment f = new details();
        Bundle arguments = new Bundle();
        arguments.putParcelable(Common.Data_Object, row_object);
        f.setArguments(arguments);

        adapter.addFragment(f, "Details");
        adapter.addFragment(new menu(), "Menu");
        adapter.addFragment(new tableBooking(), "Table booking");
        viewPager.setAdapter(adapter);
    }

    class ViewPagerAdapter extends FragmentPagerAdapter{

        private final List<Fragment> fragmentList = new ArrayList<>();
        private final List<String> fragmentTitleList = new ArrayList<>();

        public ViewPagerAdapter(FragmentManager manager){
            super(manager);
        }

        @Override
        public Fragment getItem(int position) {
            return fragmentList.get(position);
        }

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

        public void addFragment (Fragment fragment, String title){
            fragmentList.add(fragment);
            fragmentTitleList.add(title);
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return fragmentTitleList.get(position);
        }
    }
}

4. get object from bundle in Detail fragment

private void getIntentData(Bundle b)
{
    if (b != null)
    {
         detailObject = b.getParcelable(Common.Data_Object);
    }
}

Hope it will help.