Having trouble passing object between fragments

2019-08-30 08:54发布

问题:

I have been spending my time for several days with this question and getting same error. I have been trying to pass object between fragments which are held in action bar. Please tell me where i make the mistake. Here my code:

package com.restaurantexample.fragment;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;

import com.restaurantexample.adapter.MenuItemAdapter;
import com.restaurantexample.listener.OnMenuItemPressListener;
import com.restaurantexample.main.R;
import com.restaurantexample.menuitems.BaseOfMenuItems;


public class DrinksFragment extends Fragment implements OnItemClickListener {

    private List<BaseOfMenuItems> drinks;
    private BaseOfMenuItems cocaCola, fanta, pepsi, mirinda, sevenUp, juice,
        water, lemonade, mohito;
    private ListView lv;
    private MenuItemAdapter adapter;
    private int layoutId;
    private int productId;
    private int volumeId;
    private int priceId;
    private int imgId;
    private OnMenuItemPressListener menuItemListener;

   @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        View drinksView = inflater.inflate(R.layout.drinks_fragment, container,
            false);
        drinks = new ArrayList<BaseOfMenuItems>();
        cocaCola = new BaseOfMenuItems("Кока кола", "330 мл", 50,
            R.drawable.ic_launcher);
        drinks.add(cocaCola);
        fanta = new BaseOfMenuItems("Фанта", "330 мл", 50,
            R.drawable.ic_launcher);
        drinks.add(fanta);
        pepsi = new BaseOfMenuItems("Пепси", "330 мл", 50,
            R.drawable.ic_launcher);
        drinks.add(pepsi);
        mirinda = new BaseOfMenuItems("Миринда", "330 мл", 50,
            R.drawable.ic_launcher);
        drinks.add(mirinda);
        sevenUp = new BaseOfMenuItems("7 уп", "330 мл", 50,
            R.drawable.ic_launcher);
        drinks.add(sevenUp);
        juice = new BaseOfMenuItems("Сок", "250 мл", 150,
            R.drawable.ic_launcher);
        drinks.add(juice);
        water = new BaseOfMenuItems("Негазированная вода", "500 мл", 40,
            R.drawable.ic_launcher);
        drinks.add(water);
        lemonade = new BaseOfMenuItems("Домашний лимонад", "300 мл", 150,
            R.drawable.ic_launcher);
        drinks.add(lemonade);
        mohito = new BaseOfMenuItems("Мохито безалкогольный", "300 мл", 200,
            R.drawable.ic_launcher);
        drinks.add(mohito);

        layoutId = R.layout.drinks_list;
        productId = R.id.product;
        volumeId = R.id.volume;
        priceId = R.id.price;
        imgId = R.id.imgDrinks;

        lv = (ListView) drinksView.findViewById(R.id.drinkslistview);
        adapter = new MenuItemAdapter(getActivity(), drinks, layoutId,
            productId, volumeId, priceId, 0, imgId);
        lv.setAdapter(adapter);

        return drinksView;
    }

    @Override
    public void onAttach(Activity activity) {
        // TODO Auto-generated method stub
        super.onAttach(activity);
        menuItemListener = (OnMenuItemPressListener) getActivity();
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onActivityCreated(savedInstanceState);

        lv.setOnItemClickListener(this);
    }

    @Override
    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
        // TODO Auto-generated method stub

        **menuItemListener.onMenuItemPressed(drinks.get(arg2));**
    }
}

Here is second fragment:

    package com.restaurantexample.fragment;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;

import com.restaurantexample.adapter.MenuItemAdapter;
import com.restaurantexample.main.R;
import com.restaurantexample.menuitems.BaseOfMenuItems;

public class BasketFragment extends Fragment {

    private List<BaseOfMenuItems> menuItem;
    private ListView lv;
    private MenuItemAdapter adapter;
    private int layoutId;
    private int productId;
    private int portionId;
    private int priceId;
    private int imgId;
    private View basketView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        basketView = inflater.inflate(
                R.layout.basket_fragment, container, false);        

        return basketView;
    }

    @Override
    public void onAttach(Activity activity) {
        // TODO Auto-generated method stub
        super.onAttach(activity);
        setRetainInstance(true);
        layoutId = R.layout.basket_list;
        productId = R.id.basketProduct;
        portionId = R.id.portion;
        priceId = R.id.basketPrice;
        imgId = R.id.imgBasket;
        menuItem = new ArrayList<BaseOfMenuItems>();
        lv = (ListView) activity.findViewById(R.id.basketlistview);

        adapter = new MenuItemAdapter(getActivity(), menuItem, layoutId,
                productId, 0, priceId, portionId, imgId);
        lv.setAdapter(adapter);
    }

    public void setMenuItem(BaseOfMenuItems mi) {

        menuItem.add(mi);

    }
}

And activity class:

    package com.restaurantexample.main;

import com.restaurantexample.main.R;
import com.restaurantexample.menuitems.BaseOfMenuItems;
import com.restaurantexample.fragment.BasketFragment;
import com.restaurantexample.fragment.DiscountFragment;
import com.restaurantexample.fragment.MenuFragment;
import com.restaurantexample.listener.OnMenuItemPressListener;
import com.restaurantexample.listener.RestaurantTabListener;

import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar.Tab;
import android.view.Menu;
import android.view.MenuInflater;

public class RestaurantMainPage extends ActionBarActivity implements OnMenuItemPressListener{

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

        ActionBar actBar = getSupportActionBar();
        actBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        actBar.setDisplayShowTitleEnabled(true);

        Tab restMenuTab = actBar.newTab();
        restMenuTab.setText("Меню");
        restMenuTab.setTabListener(new RestaurantTabListener<MenuFragment>(this, "menu", MenuFragment.class));
        actBar.addTab(restMenuTab);

        Tab discountTab = actBar.newTab();
        discountTab.setText("%");
        discountTab.setTabListener(new RestaurantTabListener<DiscountFragment>(this, "discount", DiscountFragment.class));
        actBar.addTab(discountTab);

        Tab basketTab = actBar.newTab();
        basketTab.setText("Корзина");
        basketTab.setTabListener(new RestaurantTabListener<BasketFragment>(this, "basket", BasketFragment.class));
        actBar.addTab(basketTab);

        if (savedInstanceState != null) {
            int savedIndex = savedInstanceState.getInt("index", 0);
            getSupportActionBar().setSelectedNavigationItem(savedIndex);
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        // TODO Auto-generated method stub
        super.onSaveInstanceState(outState);
        outState.putInt("index", getSupportActionBar().getSelectedNavigationIndex());       
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.restaurant_main_page, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public void onMenuItemPressed(BaseOfMenuItems mi) {
        // TODO Auto-generated method stub
        BasketFragment bf = (BasketFragment) getSupportFragmentManager().findFragmentById(R.id.basketlistview);
        **bf.setMenuItem(mi);**
    }

}

My custom adapter:

    package com.restaurantexample.adapter;

import java.util.List;

import com.restaurantexample.menuitems.BaseOfMenuItems;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class MenuItemAdapter extends BaseAdapter{

    private Context context;
    private List<BaseOfMenuItems> list;
    private LayoutInflater inflater;
    private int layoutId;
    private int productId;
    private int amountId;
    private int priceId;
    private int portionId;
    private int imgId;

    public MenuItemAdapter(Context context, List<BaseOfMenuItems> list,
            int layoutId, int productId, int amountId, int priceId, int portionId, int imgId) {
        this.context = context;
        this.list = list;
        this.layoutId = layoutId;
        this.productId = productId;
        this.amountId = amountId;
        this.priceId = priceId;
        this.portionId = portionId;
        this.imgId = imgId;
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return list.size();
    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        TextView product, volume, price, portion;
        ImageView img;

        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View itemView = inflater.inflate(layoutId, parent, false);

        volume = (TextView) itemView.findViewById(amountId);
        volume.setText(list.get(position).getAmount());

        product = (TextView) itemView.findViewById(productId);
        product.setText(list.get(position).getProduct());

        price = (TextView) itemView.findViewById(priceId);
        price.setText("" + list.get(position).getPrice());

        img= (ImageView) itemView.findViewById(imgId);
        img.setImageResource(list.get(position).getImage());

        return itemView;
    }

}

I showed lines in bold where i get error. And this the logcat

    10-05 00:40:24.187: E/AndroidRuntime(273): FATAL EXCEPTION: main
10-05 00:40:24.187: E/AndroidRuntime(273): java.lang.NullPointerException
10-05 00:40:24.187: E/AndroidRuntime(273):  at com.restaurantexample.main.RestaurantMainPage.onMenuItemPressed(RestaurantMainPage.java:68)
10-05 00:40:24.187: E/AndroidRuntime(273):  at com.restaurantexample.fragment.DrinksFragment.onItemClick(DrinksFragment.java:104)
10-05 00:40:24.187: E/AndroidRuntime(273):  at android.widget.AdapterView.performItemClick(AdapterView.java:284)
10-05 00:40:24.187: E/AndroidRuntime(273):  at android.widget.ListView.performItemClick(ListView.java:3382)
10-05 00:40:24.187: E/AndroidRuntime(273):  at android.widget.AbsListView$PerformClick.run(AbsListView.java:1696)
10-05 00:40:24.187: E/AndroidRuntime(273):  at android.os.Handler.handleCallback(Handler.java:587)
10-05 00:40:24.187: E/AndroidRuntime(273):  at android.os.Handler.dispatchMessage(Handler.java:92)
10-05 00:40:24.187: E/AndroidRuntime(273):  at android.os.Looper.loop(Looper.java:123)
10-05 00:40:24.187: E/AndroidRuntime(273):  at android.app.ActivityThread.main(ActivityThread.java:4627)
10-05 00:40:24.187: E/AndroidRuntime(273):  at java.lang.reflect.Method.invokeNative(Native Method)
10-05 00:40:24.187: E/AndroidRuntime(273):  at java.lang.reflect.Method.invoke(Method.java:521)
10-05 00:40:24.187: E/AndroidRuntime(273):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
10-05 00:40:24.187: E/AndroidRuntime(273):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
10-05 00:40:24.187: E/AndroidRuntime(273):  at dalvik.system.NativeStart.main(Native Method)

回答1:

In onAttach() function of the first fragment, I have some doubt about initializing the callback menuItemListener. The onAttach() function is called at the very first in the order of sequence of calls to initialize a fragment. getActivity() may not be ready yet to return the associated activity.

Why don't you just initialize like this:

@Override
public void onAttach(Activity activity) {
    // TODO Auto-generated method stub
    super.onAttach(activity);
    menuItemListener = (OnMenuItemPressListener) activity;
}

activity itself is available in the parameter of the function. No need to call another function to get it.