简体   繁体   中英

Passing data from Activity to a method of a Fragment already attached

I've been researching this issue and, even though I found information, it looks like there are some details that I'm not grasping. I want to pass information from an Activity to a Fragment, which is already attached. This is the current code:

SearchActivity.java

public class SearchActivity extends AppCompatActivity {

    private static final int FRAG_USERS = 0;
    private static final int FRAG_MESSAGES = 1;
    private int currentFrag = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);
        setupActionBar();
        setupViewPager();
    }

    private void setupActionBar() {
        ActionBar actionBar = this.getSupportActionBar();
        actionBar.setTitle("");
        actionBar.setDisplayHomeAsUpEnabled(true);
    }

    private void setupViewPager() {
        ViewPager2 searchVP2 = findViewById(R.id.searchVP2);
        searchVP2.setAdapter(new SearchPagerAdapter(this));

        TabLayout searchTL = findViewById(R.id.searchTL);
        TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(searchTL, searchVP2, (tab, position) -> {
            switch (position) {
                case 0: {
                    tab.setText(R.string.users);
                    break;
                } case 1: {
                    tab.setText(R.string.messages);
                    break;
                }
            }
        });
        tabLayoutMediator.attach();

        searchTL.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                currentFrag = searchTL.getSelectedTabPosition();
            }
            @Override
            public void onTabUnselected(TabLayout.Tab tab) { }
            @Override
            public void onTabReselected(TabLayout.Tab tab) { }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_searchable, menu);
        SearchView searchView = (SearchView) menu.findItem(R.id.searchIT).getActionView();
        searchView.setMaxWidth(Integer.MAX_VALUE);
        searchView.setIconified(false);
        searchView.setFocusable(true);
        searchView.requestFocusFromTouch();
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return false;
            }

            @Override
            public boolean onQueryTextChange(String query) {
                if (!TextUtils.isEmpty(query)) {
                    if (currentFrag == FRAG_USERS) {
                        Bundle bundle = new Bundle();
                        bundle.putString(Constants.BUNDLE_SEARCH, query);
                        new SearchUserFragment().setArguments(bundle);
                        //SearchUserFragment.newInstance(query);
                    } else {
                        SearchMessageFragment.newInstance(query);
                    }
                }
                return true;
            }
        });
        return true;
    }

    @Override
    public boolean onSupportNavigateUp() {
        onBackPressed();
        return true;
    }
}

SearchUserFragment.java (message fragment is the same in this regard)

public class SearchUserFragment extends Fragment {

    private TextView notFoundTV;
    private RecyclerView searchUserRV;
    private MaterialCardView searchTipCV;
    private Map<String, User> userMap;

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_search_message, container, false);
        notFoundTV = view.findViewById(R.id.notFoundTV);
        searchTipCV = view.findViewById(R.id.searchTipCV);
        refreshRV(view);
        return view;
    }

    private void refreshRV(View view) {
        userMap = new HashMap<>();
        searchUserRV = view.findViewById(R.id.searchMessageRV);
        searchUserRV.setHasFixedSize(true);
        searchUserRV.setLayoutManager(new LinearLayoutManager(getContext()));
    }

    public void searchUser(String query) {
        userMap.clear();
        boolean isUserNameValid = true;

        String finalQuery = query.trim();
        if (finalQuery.isEmpty()) {
            setViewsVisibility(View.GONE, View.VISIBLE, View.GONE);
            isUserNameValid = false;
        } else if (finalQuery.length() < 4 || !finalQuery.matches("^[a-zA-Z0-9]+$")) {
            setViewsVisibility(View.GONE, View.VISIBLE, View.GONE);
            isUserNameValid = false;
        }

        if (isUserNameValid) {
            FirebaseDatabase.getInstance().getReference()
                    .child(KEY_COLLECTION_USER)
                    .child(finalQuery)
                    .addListenerForSingleValueEvent(new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                    for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                        User user = snapshot.getValue(User.class);
                        if (user.getUserName().equals(CURRENT_USER.getUserName())) continue;
                        if (user.getUserName().toLowerCase().startsWith(finalQuery.toLowerCase())) {
                            userMap.put(user.getId(), user);
                        }
                        checkList();
                    }
                }

                @Override
                public void onCancelled(@NonNull DatabaseError databaseError) { }
            });
        }
    }

    private void setViewsVisibility(int searchVis, int searchTipVis, int notFoundVis) {
        searchUserRV.setVisibility(searchVis);
        searchTipCV.setVisibility(searchTipVis);
        notFoundTV.setVisibility(notFoundVis);
    }

    private void checkList() {
        if (userMap.size() > 0) {
            refreshRV(userMap);
            setViewsVisibility(View.VISIBLE, View.GONE, View.GONE);
        } else {
            setViewsVisibility(View.GONE, View.GONE, View.VISIBLE);
        }
    }

    private void refreshRV(@NotNull Map<String, User> userMap) {
        SearchUserAdapter searchUserAdapter = new SearchUserAdapter(
                getContext(),
                userMap
        );
        searchUserRV.setAdapter(searchUserAdapter);
    }

    public static void newInstance(String query) {
        SearchUserFragment searchUserFragment = new SearchUserFragment();
        searchUserFragment.searchUser(query);
    }
}

SearchPagerAdapter.java

public class SearchPagerAdapter extends FragmentStateAdapter {

    public SearchPagerAdapter(@NonNull FragmentActivity fragmentActivity) {
        super(fragmentActivity);
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        if (position == 0) {
            return new SearchUserFragment();
        } else {
            return new SearchMessageFragment();
        }
    }

    @Override
    public int getItemCount() {
        return 2;
    }
}

I don't understand why some newInstance() methods that I have found during my research returns the Fragment itself. I have already tried the following approach inside the SearchUserFragment:

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null && getArguments().containsKey(BUNDLE_SEARCH)) {
            searchUser(savedInstanceState.getString(BUNDLE_SEARCH));
        }
    }

    public static SearchUserFragment newInstance(String query) {
        SearchUserFragment searchUserFragment = new SearchUserFragment();

        Bundle args = new Bundle();
        args.putString(BUNDLE_SEARCH, query);
        searchUserFragment.setArguments(args);

        return searchUserFragment;
    }

But it didn't work out, it's like if newInstance() doesn't instantiate another instance of the fragment. The app doesn't crash, but nothing will happen when I type something into the SearchView.

I have tried to do this as well: SearchActivity.java

            @Override
            public boolean onQueryTextChange(String query) {
                if (!TextUtils.isEmpty(query)) {
                    if (currentFrag == FRAG_USERS) {
                        Bundle bundle = new Bundle();
                        bundle.putString(Constants.BUNDLE_SEARCH, query);
                        new SearchUserFragment().setArguments(bundle);
                    } else {
                        SearchMessageFragment.newInstance(query);
                    }
                }
                return true;
            }

SearchUserFragment.java

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_search_message, container, false);
        notFoundTV = view.findViewById(R.id.notFoundTV);
        searchTipCV = view.findViewById(R.id.searchTipCV);
        refreshRV(view);
        Bundle bundle = this.getArguments();
        if (bundle != null) {
            searchUser(bundle.getString(BUNDLE_SEARCH));
        }
        return view;
    }

It didn't work out neither. Same behaviour as stated above.

In the current state of the code, I get the NullPointerException (rightfully so). The current code makes all my lists and views become null because onCreateView() is not being triggered due to being already created.

I just want to be able to get the query from the SearchActivity in order to execute searchUser()/searchMessage() from the fragments flawlessly.

Thanks to the last link posted by @DanielNugent, I have been able to fix this issue.

SearchUserFragment.java

public class SearchActivity extends AppCompatActivity {

    private ViewPager2 searchVP2;
    private String globalQuery;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);
        setupActionBar();
        setupViewPager();
    }

    private void setupActionBar() {
        ActionBar actionBar = this.getSupportActionBar();
        actionBar.setTitle("");
        actionBar.setDisplayHomeAsUpEnabled(true);
    }

    private void setupViewPager() {
        searchVP2 = findViewById(R.id.searchVP2);
        searchVP2.setAdapter(new SearchPagerAdapter(this));

        TabLayout searchTL = findViewById(R.id.searchTL);
        TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(searchTL, searchVP2, (tab, position) -> {
            switch (position) {
                case 0: {
                    tab.setText(R.string.users);
                    break;
                }
                case 1: {
                    tab.setText(R.string.messages);
                    break;
                }
            }
        });
        tabLayoutMediator.attach();

        searchTL.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                searchInCurrentFrag(globalQuery, tab.getPosition());
            }
            @Override
            public void onTabUnselected(TabLayout.Tab tab) { }
            @Override
            public void onTabReselected(TabLayout.Tab tab) { }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_searchable, menu);
        SearchView searchView = (SearchView) menu.findItem(R.id.searchIT).getActionView();
        searchView.setMaxWidth(Integer.MAX_VALUE);
        searchView.setIconified(false);
        searchView.setFocusable(true);
        searchView.requestFocusFromTouch();
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return false;
            }

            @Override
            public boolean onQueryTextChange(String query) {
                globalQuery = query;
                if (!TextUtils.isEmpty(query)) {
                    searchInCurrentFrag(query, searchVP2.getCurrentItem());
                }
                return true;
            }
        });
        return true;
    }

    private void searchInCurrentFrag(String query, int position) {
        if (query != null) {
            Fragment currentFragment = getSupportFragmentManager().findFragmentByTag("f" + position);
            if (currentFragment instanceof SearchUserFragment) {
                ((SearchUserFragment) currentFragment).searchUser(query);
            } else {
                ((SearchMessageFragment) currentFragment).searchMessage(query);
            }
        }
    }

    @Override
    public boolean onSupportNavigateUp() {
        onBackPressed();
        return true;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM