【问题标题】:Passing data from Activity to a method of a Fragment already attached将数据从 Activity 传递到已附加的 Fragment 的方法
【发布时间】:2021-08-16 22:10:46
【问题描述】:

我一直在研究这个问题,尽管我找到了信息,但似乎有些细节我没有掌握。我想将信息从 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.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;
    }
}

我不明白为什么我在研究期间发现的一些 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, @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;
    }

它也没有成功。与上述行为相同。

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

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

【问题讨论】:

  • 这可能会有所帮助,您基本上需要对现有片段的引用,您可以直接调用该方法,无需捆绑:stackoverflow.com/questions/36503779/…
  • @DanielNugent 我需要为 ViewPager2 设置一个适配器吗?我已经更改了 SearchPagerAdapter 的代码,但我不确定如何处理 SearchActivity 上的 setupViewPager()。当我尝试设置它时,它给了我一个错误,因为 SearchPager 类是从 FragmentPagerAdapter 而不是从 FragmentStateAdapter 扩展的。
  • @DanielNugent 最后一个链接有我想要的。非常感谢:)

标签: android android-fragments android-activity android-bundle


【解决方案1】:

感谢@DanielNugent 发布的最后一个链接,我已经能够解决这个问题。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-23
    • 1970-01-01
    • 2018-01-07
    • 1970-01-01
    • 1970-01-01
    • 2013-07-26
    • 2018-02-13
    • 2021-01-07
    相关资源
    最近更新 更多