将数据从 Activity 传递到已附加的 Fragment 的方法
Posted
技术标签:
【中文标题】将数据从 Activity 传递到已附加的 Fragment 的方法【英文标题】:Passing data from Activity to a method of a Fragment already attached 【发布时间】: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()。
【问题讨论】:
这可能会有所帮助,您基本上需要对现有片段的引用,您可以直接调用该方法,无需捆绑:***.com/questions/36503779/… @DanielNugent 我需要为 ViewPager2 设置一个适配器吗?我已经更改了 SearchPagerAdapter 的代码,但我不确定如何处理 SearchActivity 上的 setupViewPager()。当我尝试设置它时,它给了我一个错误,因为 SearchPager 类是从 FragmentPagerAdapter 而不是从 FragmentStateAdapter 扩展的。 看看这里的答案:***.com/questions/55728719/… @DanielNugent 最后一个链接有我想要的。非常感谢:) 【参考方案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;
【讨论】:
以上是关于将数据从 Activity 传递到已附加的 Fragment 的方法的主要内容,如果未能解决你的问题,请参考以下文章
将 PendingIntent 中小部件的附加信息传递给 Activity
Android - 将数据从 AsyncTask 传递到 Activity