简体   繁体   English

将数据从 Activity 传递到已附加的 Fragment 的方法

[英]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.我想将信息从 Activity 传递到已附加的 Fragment。 This is the current code:这是当前代码:

SearchActivity.java 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) SearchUserFragment.java (消息片段在这方面是一样的)

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搜索PagerAdapter.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.我不明白为什么我在研究期间发现的一些 newInstance() 方法会返回 Fragment 本身。 I have already tried the following approach inside the SearchUserFragment:我已经在 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.但它没有成功,就像 newInstance() 没有实例化片段的另一个实例一样。 The app doesn't crash, but nothing will happen when I type something into the SearchView.该应用程序不会崩溃,但是当我在 SearchView 中输入内容时不会发生任何事情。

I have tried to do this as well: SearchActivity.java我也尝试过这样做: 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搜索UserFragment.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).在当前的 state 代码中,我得到了 NullPointerException (理所当然)。 The current code makes all my lists and views become null because onCreateView() is not being triggered due to being already created.当前代码使我的所有列表和视图都变为 null 因为 onCreateView() 由于已经创建而没有被触发。

I just want to be able to get the query from the SearchActivity in order to execute searchUser()/searchMessage() from the fragments flawlessly.我只想能够从 SearchActivity 中获取查询,以便完美地从片段中执行 searchUser()/searchMessage()。

Thanks to the last link posted by @DanielNugent, I have been able to fix this issue.感谢@DanielNugent 发布的最后一个链接,我已经能够解决这个问题。

SearchUserFragment.java搜索UserFragment.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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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