如果我从另一个片段返回,如何阻止 recyclerview 刷新 firebase 数据?

发布于 2025-01-10 06:23:24 字数 7339 浏览 0 评论 0原文

我在片段中有一个 recyclerview,它从 firebase 实时数据库中获取数据。如果我从导航抽屉活动中打开另一个片段,然后返回到该片段,recyclerview 会再次刷新数据,这不是一个良好的用户体验。我希望一旦获取数据,它就不应该在返回片段时刷新。下面是我的代码。我们将非常感谢您的回复。谢谢

HomeFragment

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_home, container, false);
clicks = view.findViewById(R.id.clicks);
    zeroClicks = view.findViewById(R.id.zeroClicks);
    userName = view.findViewById(R.id.userName);
    recyclerView = view.findViewById(R.id.dashboardRCV);
LoadData();
    }
    void LoadData() {
        class MyAdapter extends RecyclerView.Adapter<MyAdapter.myViewHolder> {
            Context context;
            ArrayList<ModelClass> modelClass;

            public MyAdapter(Context context, ArrayList<ModelClass> modelClass) {
                this.context = context;
                this.modelClass = modelClass;
            }

            @NonNull
            @Override
            public myViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
                return new myViewHolder(LayoutInflater.from(context).inflate(R.layout.recyclerview_layout, parent, false));
            }
            @Override
            public void onBindViewHolder(@NonNull myViewHolder holder, @SuppressLint("RecyclerView") int position) {
                holder.previewLink.setURL(modelClass.get(position).getGig(), new URLEmbeddedView.OnLoadURLListener() {
                    @Override
                    public void onLoadURLCompleted(URLEmbeddedData data) {
                        holder.previewLink.title(data.getTitle());
                        holder.previewLink.description(data.getDescription());
                        holder.previewLink.host(data.getHost());
                        holder.previewLink.thumbnail(data.getThumbnailURL());
                        holder.previewLink.favor(data.getFavorURL());
                    }
                });
                if (modelClass.get(position).getShowGigCount() == 0){ // This will hide users whoes showgigCount is 0
                    holder.itemView.setVisibility(View.GONE);
                    holder.itemView.setLayoutParams(new RecyclerView.LayoutParams(0, 0));
                }else if (modelClass.get(position).userID.equals(UID)){ // this will hide current online user
                    holder.itemView.setVisibility(View.GONE);
                    holder.itemView.setLayoutParams(new RecyclerView.LayoutParams(0, 0));                   
                }
                holder.previewLink.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {                        dRef.child(modelClass.get(position).userID).child("showGigCount").setValue(modelClass.get(position).getShowGigCount()-1); // this will decrease showgigcount for clicked users
                        if (remainingClicks >= 1) {
                            remainingClicks--;
                            showGigCount ++;
                            clicks.setText(String.valueOf(remainingClicks));
                            UserClicksCounts();
                            UserShowGigCounts();
                            holder.previewLink.setVisibility(View.GONE); // this will hide the link on which user click
                        }else if (remainingClicks == 0){
                            zeroClicks.setVisibility(View.VISIBLE);
                        }
                    }
                });
            }
            @Override
            public int getItemCount() {
                return modelClass.size();
            }
            class myViewHolder extends RecyclerView.ViewHolder {
                URLEmbeddedView previewLink;
                public myViewHolder(@NonNull View itemView) {
                    super(itemView);
                    previewLink =  itemView.findViewById(R.id.uev);
                }
            }
        }
        dRef.addListenerForSingleValueEvent(new ValueEventListener() { // singleValueEvent will only call the firebase database once
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                list = new ArrayList<ModelClass>();
                ArrayList<ModelClass> randomGigs = new ArrayList<ModelClass>();

                for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
                    ModelClass modelClass = dataSnapshot.getValue(ModelClass.class);
                    list.add(modelClass);
                    userKey = dataSnapshot.getKey(); //Get keys
                    modelClass.setUserID(userKey);
                }
                MyAdapter adapter  = new MyAdapter(getContext(), list);
                recyclerView.setAdapter(adapter);
            }
            @Override
            public void onCancelled(@NonNull DatabaseError error) {
            }
        });
        recyclerView.setLayoutManager(new WrapContentLinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
    }

导航抽屉活动

public class NavigationActivity extends AppCompatActivity {

    private AppBarConfiguration mAppBarConfiguration;
    private ActivityNavigationBinding binding;



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
     //   getSupportFragmentManager().beginTransaction().replace(R.id.drawer_layout, new HomeFragment()).commit();

        binding = ActivityNavigationBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        setSupportActionBar(binding.appBarNavigation.toolbar);

        DrawerLayout drawer = binding.drawerLayout;
        NavigationView navigationView = binding.navView;
        // Passing each menu ID as a set of Ids because each
        // menu should be considered as top level destinations.
        mAppBarConfiguration = new AppBarConfiguration.Builder(
                R.id.nav_home, R.id.nav_analytics, R.id.nav_profile, R.id.nav_upgrade, R.id.nav_logout)
                .setOpenableLayout(drawer)
                .build();
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_navigation);
        NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
        BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_navigation_view);
        NavigationUI.setupWithNavController(navigationView, navController);
        NavigationUI.setupWithNavController(bottomNavigationView, navController);
    }

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

    @Override
    public boolean onSupportNavigateUp() {
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_navigation);
        return NavigationUI.navigateUp(navController, mAppBarConfiguration)
                || super.onSupportNavigateUp();
    }


}

I have a recyclerview in a fragment which fetch data from firebase realtime database. If I open another fragment from navigation drawer activity and then return to the fragment, recyclerview refresh the data again which is not a good user experience. I want that once the data is fetched it should not refresh on returning to the fragment. Below is my code. Your response will be highly appreciated. Thank You

HomeFragment

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_home, container, false);
clicks = view.findViewById(R.id.clicks);
    zeroClicks = view.findViewById(R.id.zeroClicks);
    userName = view.findViewById(R.id.userName);
    recyclerView = view.findViewById(R.id.dashboardRCV);
LoadData();
    }
    void LoadData() {
        class MyAdapter extends RecyclerView.Adapter<MyAdapter.myViewHolder> {
            Context context;
            ArrayList<ModelClass> modelClass;

            public MyAdapter(Context context, ArrayList<ModelClass> modelClass) {
                this.context = context;
                this.modelClass = modelClass;
            }

            @NonNull
            @Override
            public myViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
                return new myViewHolder(LayoutInflater.from(context).inflate(R.layout.recyclerview_layout, parent, false));
            }
            @Override
            public void onBindViewHolder(@NonNull myViewHolder holder, @SuppressLint("RecyclerView") int position) {
                holder.previewLink.setURL(modelClass.get(position).getGig(), new URLEmbeddedView.OnLoadURLListener() {
                    @Override
                    public void onLoadURLCompleted(URLEmbeddedData data) {
                        holder.previewLink.title(data.getTitle());
                        holder.previewLink.description(data.getDescription());
                        holder.previewLink.host(data.getHost());
                        holder.previewLink.thumbnail(data.getThumbnailURL());
                        holder.previewLink.favor(data.getFavorURL());
                    }
                });
                if (modelClass.get(position).getShowGigCount() == 0){ // This will hide users whoes showgigCount is 0
                    holder.itemView.setVisibility(View.GONE);
                    holder.itemView.setLayoutParams(new RecyclerView.LayoutParams(0, 0));
                }else if (modelClass.get(position).userID.equals(UID)){ // this will hide current online user
                    holder.itemView.setVisibility(View.GONE);
                    holder.itemView.setLayoutParams(new RecyclerView.LayoutParams(0, 0));                   
                }
                holder.previewLink.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {                        dRef.child(modelClass.get(position).userID).child("showGigCount").setValue(modelClass.get(position).getShowGigCount()-1); // this will decrease showgigcount for clicked users
                        if (remainingClicks >= 1) {
                            remainingClicks--;
                            showGigCount ++;
                            clicks.setText(String.valueOf(remainingClicks));
                            UserClicksCounts();
                            UserShowGigCounts();
                            holder.previewLink.setVisibility(View.GONE); // this will hide the link on which user click
                        }else if (remainingClicks == 0){
                            zeroClicks.setVisibility(View.VISIBLE);
                        }
                    }
                });
            }
            @Override
            public int getItemCount() {
                return modelClass.size();
            }
            class myViewHolder extends RecyclerView.ViewHolder {
                URLEmbeddedView previewLink;
                public myViewHolder(@NonNull View itemView) {
                    super(itemView);
                    previewLink =  itemView.findViewById(R.id.uev);
                }
            }
        }
        dRef.addListenerForSingleValueEvent(new ValueEventListener() { // singleValueEvent will only call the firebase database once
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                list = new ArrayList<ModelClass>();
                ArrayList<ModelClass> randomGigs = new ArrayList<ModelClass>();

                for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
                    ModelClass modelClass = dataSnapshot.getValue(ModelClass.class);
                    list.add(modelClass);
                    userKey = dataSnapshot.getKey(); //Get keys
                    modelClass.setUserID(userKey);
                }
                MyAdapter adapter  = new MyAdapter(getContext(), list);
                recyclerView.setAdapter(adapter);
            }
            @Override
            public void onCancelled(@NonNull DatabaseError error) {
            }
        });
        recyclerView.setLayoutManager(new WrapContentLinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
    }

Navigation Drawer Activity

public class NavigationActivity extends AppCompatActivity {

    private AppBarConfiguration mAppBarConfiguration;
    private ActivityNavigationBinding binding;



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
     //   getSupportFragmentManager().beginTransaction().replace(R.id.drawer_layout, new HomeFragment()).commit();

        binding = ActivityNavigationBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        setSupportActionBar(binding.appBarNavigation.toolbar);

        DrawerLayout drawer = binding.drawerLayout;
        NavigationView navigationView = binding.navView;
        // Passing each menu ID as a set of Ids because each
        // menu should be considered as top level destinations.
        mAppBarConfiguration = new AppBarConfiguration.Builder(
                R.id.nav_home, R.id.nav_analytics, R.id.nav_profile, R.id.nav_upgrade, R.id.nav_logout)
                .setOpenableLayout(drawer)
                .build();
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_navigation);
        NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
        BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_navigation_view);
        NavigationUI.setupWithNavController(navigationView, navController);
        NavigationUI.setupWithNavController(bottomNavigationView, navController);
    }

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

    @Override
    public boolean onSupportNavigateUp() {
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_navigation);
        return NavigationUI.navigateUp(navController, mAppBarConfiguration)
                || super.onSupportNavigateUp();
    }


}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

零度℉ 2025-01-17 06:23:24

我建议的方法可能不是最好的,但可以使用 ViewModel 来解决。

在ViewModel中存储要获取的标志和数据,由于获取的空间是Fragment,因此可以通过将ViewModel的生命周期从属于Activity来解决这个问题。

我在下面举了一个例子。它测试从 HomeFragment 移动到 TwoFragment 以及从 HomeFragment 移动到 OtherActivity 的情况。在两种情况下它只获取一次数据。

// this 'NavigationDrawerActivity' hold only FragmentContainerView 
// And Make ViewModel that would use in HomeFragment

class NavigationDrawerActivity : AppCompatActivity() {
    lateinit var binding: ActivityNavigationDrawerBinding
    lateinit var homeViewModel: HomeViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        homeViewModel = ViewModelProvider(this)[OneViewModel::class.java]
        
        setContentView(binding.root)

    }
}

在 HomeFragment 中。它使用日志检查 fetchedData。

class HomeFragment : Fragment() {

    private var _binding: FragmentOneBinding? = null
    private val binding get() = _binding!!
    private lateinit var viewModel: HomeViewModel

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentOneBinding.inflate(layoutInflater,container, false)
        viewModel = ViewModelProvider(requireActivity())[HomeViewModel::class.java]
        viewModel.fetch()
        viewModel.fetchedData.map { Log.e("FetchedData", it) }

        binding.fragmentButton.setOnClickListener {
            findNavController().navigate(R.id.action_oneFragment_to_twoFragment)
        }

        binding.activityButton.setOnClickListener {
            requireActivity().startActivity(Intent(requireActivity(), OtherActivity::class.java))
        }
        return binding.root
    }

    override fun onDestroy() {
        super.onDestroy()
        _binding = null
    }
}

这是 HomeViewModel


class HomeViewModel: ViewModel() {

    private var _goodToFetch = true
    private var _fetchedData = mutableListOf<String>()
    val fetchedData: List<String> get() = _fetchedData

    fun fetch() {
        Log.e("ViewModel", "fetch() with _goodToFetch = $_goodToFetch")
        if (_goodToFetch) doFetch()
    }

    private fun doFetch() {
        Log.e("ViewModel", "doFetch()" )
        for (i in 0..20) {
            _fetchedData.add(i.toString())
        }
        _goodToFetch = false
    }
}

The method I'm suggesting may not be the best, but it can be solved using a ViewModel.

Store flags and data to be fetched in ViewModel, and since the space you fetch is Fragment, you can solve this by subordinating the life cycle of ViewModel to Activity.

I made one example down below. it test case that move from HomeFragment to TwoFragment and from HomeFragment to OtherActivity. in Two case It fetch data only one time.

// this 'NavigationDrawerActivity' hold only FragmentContainerView 
// And Make ViewModel that would use in HomeFragment

class NavigationDrawerActivity : AppCompatActivity() {
    lateinit var binding: ActivityNavigationDrawerBinding
    lateinit var homeViewModel: HomeViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        homeViewModel = ViewModelProvider(this)[OneViewModel::class.java]
        
        setContentView(binding.root)

    }
}

in HomeFragment. it check fetchedData using log.

class HomeFragment : Fragment() {

    private var _binding: FragmentOneBinding? = null
    private val binding get() = _binding!!
    private lateinit var viewModel: HomeViewModel

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentOneBinding.inflate(layoutInflater,container, false)
        viewModel = ViewModelProvider(requireActivity())[HomeViewModel::class.java]
        viewModel.fetch()
        viewModel.fetchedData.map { Log.e("FetchedData", it) }

        binding.fragmentButton.setOnClickListener {
            findNavController().navigate(R.id.action_oneFragment_to_twoFragment)
        }

        binding.activityButton.setOnClickListener {
            requireActivity().startActivity(Intent(requireActivity(), OtherActivity::class.java))
        }
        return binding.root
    }

    override fun onDestroy() {
        super.onDestroy()
        _binding = null
    }
}

This is HomeViewModel


class HomeViewModel: ViewModel() {

    private var _goodToFetch = true
    private var _fetchedData = mutableListOf<String>()
    val fetchedData: List<String> get() = _fetchedData

    fun fetch() {
        Log.e("ViewModel", "fetch() with _goodToFetch = $_goodToFetch")
        if (_goodToFetch) doFetch()
    }

    private fun doFetch() {
        Log.e("ViewModel", "doFetch()" )
        for (i in 0..20) {
            _fetchedData.add(i.toString())
        }
        _goodToFetch = false
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文