Java 片段间通信

Java 片段间通信,java,android,android-fragments,Java,Android,Android Fragments,MainFragment中有两个片段(ProductDisplayFragment和PaymentFragment)并排通信。MainFragment处于导航活动中。当从ProductDisplayFragment的GridView中选择项目时,它将添加到PaymentFragment ListView中 NavigationActivity充当中间人,将捆绑产品对象从ProductDisplayFragment“发送”到PaymentFragment。它工作得非常好,直到我切换到另一个Navi

MainFragment中有两个片段(ProductDisplayFragment和PaymentFragment)并排通信。MainFragment处于导航活动中。当从ProductDisplayFragment的GridView中选择项目时,它将添加到PaymentFragment ListView中

NavigationActivity充当中间人,将捆绑产品对象从ProductDisplayFragment“发送”到PaymentFragment。它工作得非常好,直到我切换到另一个NavigationActivity片段,然后切换回MainFragment(包含ProductDisplayFragment和PaymentFragment)

我有
List productList
将从ProductDisplayFragment添加的产品列表存储在我的PaymentFragment中。添加项目时,
productList.size()在PaymentFragment中用于分段间通信的那些方法中为>0
getProduct()
updateProductInfo()

但是,当我在除上述两种方法之外的其他方法中重新检查productList.size()时,虽然我在ProductDisplayFragment上单击了项目以将项目添加到PaymentFragment中,但在片段到片段通信中未涉及,
productList.size()=0

为什么会这样?是什么导致了这种奇怪的行为

ProductDisplayFragment.java

public class ProductDisplayFragment extends Fragment {

    private GridView gridView;
    private ProductGridAdapter productAdapter;
    private OnProductSelectedListener sendProduct;

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

    public interface OnProductSelectedListener {
        void onProductSelected(Product product);
    }

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

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

        gridView = (GridView) rootView.findViewById(R.id.gridview);
        productAdapter = new ProductGridAdapter(getActivity(), R.layout.fragment_product_display, getProductList());
        gridView.setAdapter(productAdapter);

        return rootView;
    }

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

        try {
            sendProduct = (OnProductSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(MESSAGE_ERROR_IMPLEMENTATION);
        }
    }
}
public class PaymentFragment extends Fragment {

    public PaymentFragment() {

    }

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

        listView = (ListView) rootView.findViewById(R.id.productList);
        paymentAdapter = new PaymentListAdapter(getActivity(), R.layout.fragment_payment, productList);
        listView.setAdapter(paymentAdapter);

        voidButton = (LinearLayout) rootView.findViewById(R.id.button_void);
        saveButton = (LinearLayout) rootView.findViewById(R.id.button_save);
        noteButton = (LinearLayout) rootView.findViewById(R.id.button_note);
        discountButton = (LinearLayout) rootView.findViewById(R.id.button_discount);
        payButton = (LinearLayout) rootView.findViewById(R.id.button_pay);
        amountSubtotal = (TextView) rootView.findViewById(R.id.amount_subtotal);
        amountDiscount = (TextView) rootView.findViewById(R.id.amount_discount);
        amountTotal = (TextView) rootView.findViewById(R.id.amount_total);

        setDefaultAmount();
        getFirstProduct();
        buttonsOnClick();

        return rootView;
    }

    /*
     * This method retrieves product from fragment and refresh the listview every time a new product is added into listview
     */
    public void getProduct(Product product) {
        updateProductInfo(product);
        updateListView();
    }

    private void updateProductInfo(Product product) {
        // Only add product if it does not exist in hashset, else increment quantity number
        if(productHash.contains(product.getBarcode())) {
            int productIndex = productList.indexOf(product);
            product.setQuantity(product.getQuantity() + 1);
            if(productIndex != -1) {
                productList.set(productIndex, product);
            }
        } else {
            product.setQuantity(1);
            productList.add(0, product);
            productHash.add(product.getBarcode());
        }
    }

    private void getFirstProduct() {
        Bundle arguments = getArguments();
        if (arguments != null) {
            Product product = (Product) arguments.getSerializable(KEY_PRODUCT);
            getProduct(product);
            if(product != null) {
                Log.d(TAG, "Received subsequent product" + product.getName());
            }
        }
    }
}
PaymentFragment.java

public class ProductDisplayFragment extends Fragment {

    private GridView gridView;
    private ProductGridAdapter productAdapter;
    private OnProductSelectedListener sendProduct;

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

    public interface OnProductSelectedListener {
        void onProductSelected(Product product);
    }

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

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

        gridView = (GridView) rootView.findViewById(R.id.gridview);
        productAdapter = new ProductGridAdapter(getActivity(), R.layout.fragment_product_display, getProductList());
        gridView.setAdapter(productAdapter);

        return rootView;
    }

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

        try {
            sendProduct = (OnProductSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(MESSAGE_ERROR_IMPLEMENTATION);
        }
    }
}
public class PaymentFragment extends Fragment {

    public PaymentFragment() {

    }

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

        listView = (ListView) rootView.findViewById(R.id.productList);
        paymentAdapter = new PaymentListAdapter(getActivity(), R.layout.fragment_payment, productList);
        listView.setAdapter(paymentAdapter);

        voidButton = (LinearLayout) rootView.findViewById(R.id.button_void);
        saveButton = (LinearLayout) rootView.findViewById(R.id.button_save);
        noteButton = (LinearLayout) rootView.findViewById(R.id.button_note);
        discountButton = (LinearLayout) rootView.findViewById(R.id.button_discount);
        payButton = (LinearLayout) rootView.findViewById(R.id.button_pay);
        amountSubtotal = (TextView) rootView.findViewById(R.id.amount_subtotal);
        amountDiscount = (TextView) rootView.findViewById(R.id.amount_discount);
        amountTotal = (TextView) rootView.findViewById(R.id.amount_total);

        setDefaultAmount();
        getFirstProduct();
        buttonsOnClick();

        return rootView;
    }

    /*
     * This method retrieves product from fragment and refresh the listview every time a new product is added into listview
     */
    public void getProduct(Product product) {
        updateProductInfo(product);
        updateListView();
    }

    private void updateProductInfo(Product product) {
        // Only add product if it does not exist in hashset, else increment quantity number
        if(productHash.contains(product.getBarcode())) {
            int productIndex = productList.indexOf(product);
            product.setQuantity(product.getQuantity() + 1);
            if(productIndex != -1) {
                productList.set(productIndex, product);
            }
        } else {
            product.setQuantity(1);
            productList.add(0, product);
            productHash.add(product.getBarcode());
        }
    }

    private void getFirstProduct() {
        Bundle arguments = getArguments();
        if (arguments != null) {
            Product product = (Product) arguments.getSerializable(KEY_PRODUCT);
            getProduct(product);
            if(product != null) {
                Log.d(TAG, "Received subsequent product" + product.getName());
            }
        }
    }
}
NavigationActivity.java

public class NavigationActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener,
        ProductDisplayFragment.OnProductSelectedListener {

@Override
    public void onProductSelected(Product product) {
        PaymentFragment paymentFragment = (PaymentFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_payment_list);
        if(paymentFragment != null) {
            paymentFragment.getProduct(product);
        } else {
            paymentFragment = new PaymentFragment();
            Bundle args = new Bundle();
            args.putSerializable(KEY_PRODUCT, product);
            paymentFragment.setArguments(args);

            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            transaction.replace(R.id.fragment_payment_list, paymentFragment);
            transaction.addToBackStack(null);
            transaction.commit();
            //productQueue.add(product);
            //paymentFragment.getProduct(product);
        }
    }
}

根据我的经验,在片段/活动之间传递大量自定义对象,特别是自定义对象的ArrayList,常常会导致奇怪的bug。这就是为什么我建议您将
列表productList
和所有用于管理产品的逻辑存储在一个单独的单例类中,而不是在片段中移动它。大概是这样的:

public class ProductsManager{
   private static ProductsManager productManager;
   private List<Product> productList;

   private ProductsManager(){
     this.productList = new ArrayList<>();
     //Or init your productList here
   }

   public static getInstance(){
     if(productManager == null){
       productManager = new ProductsManager();
     }
   }

   public List<Product> getProductsList(){
     return productList;
   }

   public Product getProduct(){
     //Some logic
   }

   public Product updateProductInfo(Product product){
     //Some logic
   }

   //Any other method to work with your products
}
ProductsManager.getInstance().getProductsList();