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

问题描述

我一直在研究这个问题,尽管我找到了信息,但似乎有些细节我没有掌握。我想将信息从 Activity 传递到已经附加的 Fragment。这是当前代码:

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

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.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.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;
    }
}

我不明白为什么我在研究过程中发现的一些 newInstance() 方法会返回 Fragment 本身。我已经在 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;
    }

但它没有成功,就像 newInstance() 没有实例化片段的另一个实例一样。应用不会崩溃,但当我在 SearchView 中输入内容时不会发生任何事情。

我也尝试过这样做: 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,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;
    }

也没有用。与上述相同的行为。

在代码的当前状态下,我得到 NullPointerException(理所当然)。当前代码使我所有的列表和视图都变为空,因为 onCreateView() 由于已经创建而没有被触发。

我只是希望能够从 SearchActivity 获取查询,以便完美地从片段中执行 searchUser()/searchMessage()。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)