Java 切换到另一个片段后可以看到黑屏

Java 切换到另一个片段后可以看到黑屏,java,android,android-fragments,fragment,Java,Android,Android Fragments,Fragment,我正在尝试创建一个带有产品列表和产品主控详细信息的简单应用程序。 至于我最初的尝试,我已经使用BottomNavigationView创建了这个应用程序,在底部有一些小图标,你可以通过点击其中一个来切换片段。我目前在底部导航栏上有4个图标,以下是4个图标: 产品(产品碎片) 收藏夹(收藏夹片段) 配置文件(ProfileFragment) 购物车(CartFragment) 这4个片段是我的HomeActivity中的开关,以下是我切换它们的方式: HomeActivity.java @Ov

我正在尝试创建一个带有产品列表和产品主控详细信息的简单应用程序。 至于我最初的尝试,我已经使用BottomNavigationView创建了这个应用程序,在底部有一些小图标,你可以通过点击其中一个来切换片段。我目前在底部导航栏上有4个图标,以下是4个图标:

  • 产品(产品碎片)
  • 收藏夹(收藏夹片段)
  • 配置文件(ProfileFragment)
  • 购物车(CartFragment)
这4个片段是我的HomeActivity中的开关,以下是我切换它们的方式:

HomeActivity.java

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

        bottomNavbar = findViewById(R.id.nav_view);
        bottomNavbar.setOnNavigationItemSelectedListener(navListener);
        homeContainer = findViewById(R.id.homeContainer);
        createSnackbar(homeContainer);
        viewModel = new HomeViewModel();
        viewModel.getCartCounterLiveData().observe(this, CartCounterObserver);
        createBadges(bottomNavbar);
}    

private BottomNavigationView.OnNavigationItemSelectedListener navListener = new BottomNavigationView.OnNavigationItemSelectedListener() {

        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            BaseRTFFragment selectedFragment = null;
            String stackName;

            switch(item.getItemId()) {
                case R.id.nav_home:
                    selectedFragment = new ProductsFragment();
                    break;

                case R.id.nav_favorites:
                    selectedFragment = new FavoritesFragment();
                    break;

                case R.id.nav_profile:
                    selectedFragment = new ProfileFragment();
                    break;

                case R.id.nav_cart:
                    selectedFragment = new CartFragment();
                    break;
            }

            navigateToFragment(selectedFragment);
            return true;
        }
    };

    private void navigateToFragment(BaseRTFFragment selectedFragment) {
        FragmentTransaction fTrans = getSupportFragmentManager().beginTransaction();
        // fTrans.addToBackStack(selectedFragment.getFragmentName());
        fTrans.replace(R.id.nav_host_fragment, selectedFragment).commit();
    }

public class ProductsFragment extends BaseRTFFragment<FragmentProductsBinding>
        implements Observer<PagedList<Product>>, ProductsAdapter.OnProductClickListener, CategoryAdapter.OnCategoryClickListener {

    ProductsViewModel viewModel;
    ProductsAdapter productsAdapter;
    int selectedCategory;
    String currentSearchText;
    ProductsEventsListener listener;

    private CategoryAdapter categoryAdapter;
    private String fragmentName = "Products";

    @Override
    protected int getFragmentLayout() {
        return R.layout.fragment_products;
    }

    @Override
    public String getFragmentName() { return fragmentName; }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        viewModel = new ProductsViewModel();
        initProductsAdapter();
        initCategoryAdapter();
        initializeSearch();
        loadProducts();
    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        try {
            listener = (ProductsEventsListener) context;
        } catch (ClassCastException castException) {
            throw new Error("The activity does not implement the listener");
        }
    }

    private void initProductsAdapter() {
        productsAdapter = new ProductsAdapter(this);
        dataBinding.productsRecyclerView.setAdapter(productsAdapter);
    }

    private void initCategoryAdapter() {
        Query cQuery = initCategoryQuery();
        cQuery.get().addOnCompleteListener(categoryListener);
    }

    private OnCompleteListener<QuerySnapshot> categoryListener = new OnCompleteListener<QuerySnapshot>() {
        @Override
        public void onComplete(@NonNull Task<QuerySnapshot> task) {
            if(task.isSuccessful()) {
                List<Category> categories = task.getResult().toObjects(Category.class);
                categoryAdapter = getCategoryAdapter(categories);
                dataBinding.categoryRecyclerView.setAdapter(categoryAdapter);
            }
        }
    };

    private CategoryAdapter getCategoryAdapter(List<Category> categories) {
        return new CategoryAdapter(categories, this);
    }

    private Query initCategoryQuery() {
        FirebaseFirestore mFirestore = FirebaseFirestore.getInstance();
        return mFirestore.collection("categories")
                .orderBy("name", Query.Direction.ASCENDING);
    }

    private void loadProducts() {
        viewModel.pagedListLiveData.observe(getViewLifecycleOwner(), this);
    }

    private void reloadProducts() {
        viewModel.replaceSubscription(this, null, 0);
        loadProducts();
    }

    private void loadSearchedProducts(String searchText, int category) {
        viewModel.replaceSubscription(this, searchText, category);
        loadProducts();
    }

    @Override
    public void onChanged(PagedList<Product> products) {
        productsAdapter.submitList(products);
        hideProgressBar();
        // toggleEmptyLayout(products.size());
    }

    private void toggleEmptyLayout(int count) {
        if(count > 0) {
            dataBinding.productsRecyclerView.setVisibility(View.VISIBLE);
            dataBinding.emptyResultLayout.setVisibility(View.GONE);
        } else {
            dataBinding.productsRecyclerView.setVisibility(View.GONE);
            dataBinding.emptyResultLayout.setVisibility(View.VISIBLE);
        }
    }

    private void hideProgressBar() {
        dataBinding.progressBar.setVisibility(View.GONE);
    }

    public int getSelectedCategory() {
        return selectedCategory;
    }

    @Override
    public void onProductClick(Product product) {
        displayProductName(product.getName() + " has been clicked!");
        listener.OnProductClick(product);
    }

    @Override
    public void onAddProductToCart(Product product) {
        // displayProductName(product.getName() + " has been added to cart");
        listener.OnAddProductToCart(product);
    }

    @Override
    public void onFavoriteProduct(Product product) {
        listener.OnFavoriteProduct(product);
    }

    private void displayProductName(String name) {
        Toast.makeText(getActivity(), name, Toast.LENGTH_SHORT).show();
    }

    private void initializeSearch() {
        dataBinding.searchInput.addTextChangedListener(searchTextWatcher);
    }

    private TextWatcher searchTextWatcher = new TextWatcher() {
        @Override
        public void afterTextChanged(Editable searchText) {
            String sText = searchText.toString().toLowerCase();;
            if (sText != currentSearchText) {
                currentSearchText = sText;
                loadSearchedProducts(currentSearchText, selectedCategory);
            }
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start,
                                      int count, int after) {
        }

        @Override
        public void onTextChanged(CharSequence s, int start,
                                  int before, int count) {
        }
    };

    @Override
    public void onCategoryClick(int selectedCategoryId) {
        selectedCategory = selectedCategoryId;
        loadSearchedProducts(currentSearchText, selectedCategory);
    }
}
public abstract class BaseRTFFragment<T extends ViewDataBinding> extends Fragment {
    protected T dataBinding;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle bundle) {
        dataBinding = DataBindingUtil.inflate(inflater, getFragmentLayout(), null, false);
        return dataBinding.getRoot();
    }

    protected abstract int getFragmentLayout();
    public abstract String getFragmentName();

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        dataBinding = null;
    }
}

public class ProductFragment extends BaseRTFFragment<FragmentProductBinding> implements Observer<Product> {

    ProductViewModel viewModel;
    ProductEventsListener listener;
    private String fragmentName = "Product";

    @Override
    protected int getFragmentLayout() {
        return R.layout.fragment_product;
    }

    @Override
    public String getFragmentName() { return fragmentName; }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle bundle) {
        int productId = getArguments().getInt("productId");
        viewModel = new ProductViewModel(productId);
        viewModel.getProduct(productId).observe(getViewLifecycleOwner(), this);
        return super.onCreateView(inflater, container, bundle);
    }

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

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        try {
            listener = (ProductEventsListener) context;
        } catch (ClassCastException castException) {
            throw new Error("The activity does not implement the listener");
        }
    }

    @Override
    public void onChanged(Product product) {
        dataBinding.productTitle.setText(product.getName());
    }

}
因此,这只是对replace()的一个简单调用。在这一点上,它的工作良好,片段之间没有黑屏切换

顺便说一句,ProductsFragment有一个searchText、category filter按钮和一个分页的recyclerView来显示产品列表。请参阅下面的代码:

ProductsFragment.java

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

        bottomNavbar = findViewById(R.id.nav_view);
        bottomNavbar.setOnNavigationItemSelectedListener(navListener);
        homeContainer = findViewById(R.id.homeContainer);
        createSnackbar(homeContainer);
        viewModel = new HomeViewModel();
        viewModel.getCartCounterLiveData().observe(this, CartCounterObserver);
        createBadges(bottomNavbar);
}    

private BottomNavigationView.OnNavigationItemSelectedListener navListener = new BottomNavigationView.OnNavigationItemSelectedListener() {

        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            BaseRTFFragment selectedFragment = null;
            String stackName;

            switch(item.getItemId()) {
                case R.id.nav_home:
                    selectedFragment = new ProductsFragment();
                    break;

                case R.id.nav_favorites:
                    selectedFragment = new FavoritesFragment();
                    break;

                case R.id.nav_profile:
                    selectedFragment = new ProfileFragment();
                    break;

                case R.id.nav_cart:
                    selectedFragment = new CartFragment();
                    break;
            }

            navigateToFragment(selectedFragment);
            return true;
        }
    };

    private void navigateToFragment(BaseRTFFragment selectedFragment) {
        FragmentTransaction fTrans = getSupportFragmentManager().beginTransaction();
        // fTrans.addToBackStack(selectedFragment.getFragmentName());
        fTrans.replace(R.id.nav_host_fragment, selectedFragment).commit();
    }

public class ProductsFragment extends BaseRTFFragment<FragmentProductsBinding>
        implements Observer<PagedList<Product>>, ProductsAdapter.OnProductClickListener, CategoryAdapter.OnCategoryClickListener {

    ProductsViewModel viewModel;
    ProductsAdapter productsAdapter;
    int selectedCategory;
    String currentSearchText;
    ProductsEventsListener listener;

    private CategoryAdapter categoryAdapter;
    private String fragmentName = "Products";

    @Override
    protected int getFragmentLayout() {
        return R.layout.fragment_products;
    }

    @Override
    public String getFragmentName() { return fragmentName; }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        viewModel = new ProductsViewModel();
        initProductsAdapter();
        initCategoryAdapter();
        initializeSearch();
        loadProducts();
    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        try {
            listener = (ProductsEventsListener) context;
        } catch (ClassCastException castException) {
            throw new Error("The activity does not implement the listener");
        }
    }

    private void initProductsAdapter() {
        productsAdapter = new ProductsAdapter(this);
        dataBinding.productsRecyclerView.setAdapter(productsAdapter);
    }

    private void initCategoryAdapter() {
        Query cQuery = initCategoryQuery();
        cQuery.get().addOnCompleteListener(categoryListener);
    }

    private OnCompleteListener<QuerySnapshot> categoryListener = new OnCompleteListener<QuerySnapshot>() {
        @Override
        public void onComplete(@NonNull Task<QuerySnapshot> task) {
            if(task.isSuccessful()) {
                List<Category> categories = task.getResult().toObjects(Category.class);
                categoryAdapter = getCategoryAdapter(categories);
                dataBinding.categoryRecyclerView.setAdapter(categoryAdapter);
            }
        }
    };

    private CategoryAdapter getCategoryAdapter(List<Category> categories) {
        return new CategoryAdapter(categories, this);
    }

    private Query initCategoryQuery() {
        FirebaseFirestore mFirestore = FirebaseFirestore.getInstance();
        return mFirestore.collection("categories")
                .orderBy("name", Query.Direction.ASCENDING);
    }

    private void loadProducts() {
        viewModel.pagedListLiveData.observe(getViewLifecycleOwner(), this);
    }

    private void reloadProducts() {
        viewModel.replaceSubscription(this, null, 0);
        loadProducts();
    }

    private void loadSearchedProducts(String searchText, int category) {
        viewModel.replaceSubscription(this, searchText, category);
        loadProducts();
    }

    @Override
    public void onChanged(PagedList<Product> products) {
        productsAdapter.submitList(products);
        hideProgressBar();
        // toggleEmptyLayout(products.size());
    }

    private void toggleEmptyLayout(int count) {
        if(count > 0) {
            dataBinding.productsRecyclerView.setVisibility(View.VISIBLE);
            dataBinding.emptyResultLayout.setVisibility(View.GONE);
        } else {
            dataBinding.productsRecyclerView.setVisibility(View.GONE);
            dataBinding.emptyResultLayout.setVisibility(View.VISIBLE);
        }
    }

    private void hideProgressBar() {
        dataBinding.progressBar.setVisibility(View.GONE);
    }

    public int getSelectedCategory() {
        return selectedCategory;
    }

    @Override
    public void onProductClick(Product product) {
        displayProductName(product.getName() + " has been clicked!");
        listener.OnProductClick(product);
    }

    @Override
    public void onAddProductToCart(Product product) {
        // displayProductName(product.getName() + " has been added to cart");
        listener.OnAddProductToCart(product);
    }

    @Override
    public void onFavoriteProduct(Product product) {
        listener.OnFavoriteProduct(product);
    }

    private void displayProductName(String name) {
        Toast.makeText(getActivity(), name, Toast.LENGTH_SHORT).show();
    }

    private void initializeSearch() {
        dataBinding.searchInput.addTextChangedListener(searchTextWatcher);
    }

    private TextWatcher searchTextWatcher = new TextWatcher() {
        @Override
        public void afterTextChanged(Editable searchText) {
            String sText = searchText.toString().toLowerCase();;
            if (sText != currentSearchText) {
                currentSearchText = sText;
                loadSearchedProducts(currentSearchText, selectedCategory);
            }
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start,
                                      int count, int after) {
        }

        @Override
        public void onTextChanged(CharSequence s, int start,
                                  int before, int count) {
        }
    };

    @Override
    public void onCategoryClick(int selectedCategoryId) {
        selectedCategory = selectedCategoryId;
        loadSearchedProducts(currentSearchText, selectedCategory);
    }
}
public abstract class BaseRTFFragment<T extends ViewDataBinding> extends Fragment {
    protected T dataBinding;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle bundle) {
        dataBinding = DataBindingUtil.inflate(inflater, getFragmentLayout(), null, false);
        return dataBinding.getRoot();
    }

    protected abstract int getFragmentLayout();
    public abstract String getFragmentName();

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        dataBinding = null;
    }
}

public class ProductFragment extends BaseRTFFragment<FragmentProductBinding> implements Observer<Product> {

    ProductViewModel viewModel;
    ProductEventsListener listener;
    private String fragmentName = "Product";

    @Override
    protected int getFragmentLayout() {
        return R.layout.fragment_product;
    }

    @Override
    public String getFragmentName() { return fragmentName; }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle bundle) {
        int productId = getArguments().getInt("productId");
        viewModel = new ProductViewModel(productId);
        viewModel.getProduct(productId).observe(getViewLifecycleOwner(), this);
        return super.onCreateView(inflater, container, bundle);
    }

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

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        try {
            listener = (ProductEventsListener) context;
        } catch (ClassCastException castException) {
            throw new Error("The activity does not implement the listener");
        }
    }

    @Override
    public void onChanged(Product product) {
        dataBinding.productTitle.setText(product.getName());
    }

}

它只是从前面调用navigateToFragment()方法。但这一次,每次我单击ProductFragment中的back按钮时,它都会呈现一个至少1秒的黑屏,并加载产品列表。我不确定哪里出了问题,因为我只是以与其他片段相同的方式加载片段。我错过了什么吗?还是我的方法错了?我该怎么办?请帮忙。提前感谢。

找到了一个解决方案,在片段的布局中使用android:onClick属性,绑定似乎无法正常工作。因此,我通过在“后退”按钮上设置onClickListener来绑定click事件,从而返回到绑定click事件的旧方法:

DO:

ProductFragment.java

 @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        bindEvents();
    }

    private void bindEvents() {
        dataBinding.backBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                listener.onNavigateBack();
            }
        });
    }
从现在起我再也不会这样做了:

fragment_product.xml

...
<ImageButton
    ....
    android:id="@+id/backBtn"
    android:onClick="onProductClick"
    ... />
...
。。。
...