You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Activity的onOptionsItemSelected中刷新ViewPager内的Fragment?

Hey there! Let's figure out why your app is crashing when you tap the refresh icon and fix it step by step.

What's Causing the Crash?

Your code has two critical issues that lead to the crash:

  1. Null Fragments from Wrong Tag Lookup
    You're trying to find Fragments using tags like "fragmentSentMsg", but that's the tag you set on the Fragment's root View (Page2_sent_msg.setTag("sentMsg");), not the tag the FragmentManager uses to track the Fragment itself. ViewPager generates its own system tags for Fragments, so findFragmentByTag() returns null here — leading to a NullPointerException when you try to detach() these null references.

  2. Reusing the Same FragmentTransaction Multiple Times
    You create one FragmentTransaction, add multiple detach/attach operations, then call commit() three times. A single transaction can only be committed once, so this will throw an exception.


This is a cleaner, more flexible approach than detaching/attaching, as you have direct control over what gets refreshed.

Step 1: Update Fragments with a Refresh Method

Modify your Page2_sent_msg Fragment (and the other two) to move data loading into a reusable method:

public class Page2_sent_msg extends Fragment {
    private ListView sentMsgListView;
    private ArrayAdapter<String> sentMsgAdapter;
    private ArrayList<String> sentMsgArrayList;

    // Default constructor
    public Page2_sent_msg(){}

    @SuppressLint("ResourceType")
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
        final View rootView = inflater.inflate(R.layout.page2_sent_msg, container, false);
        sentMsgListView = rootView.findViewById(R.id.sentMsgListview);
        sentMsgArrayList = new ArrayList<>();
        sentMsgAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, sentMsgArrayList);
        sentMsgListView.setAdapter(sentMsgAdapter);

        // Keep your existing item click logic
        sentMsgListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                // Your existing click handler
            }
        });

        // Load initial data
        loadSentMessages();
        return rootView;
    }

    // Public method to trigger refresh
    public void refresh() {
        loadSentMessages();
    }

    private void loadSentMessages() {
        sentMsgArrayList.clear(); // Clear old data first
        SQLite_database_helper_class myDb = new SQLite_database_helper_class(getContext());
        Cursor result = myDb.getting_sms_from_db();
        
        if (result.moveToFirst()) {
            do {
                if (!result.getString(3).equals("Sent message")) {
                    continue;
                }
                sentMsgArrayList.add(
                    "SMS No : "+result.getString(0)+"\n" +
                    "Address : "+result.getString(1)+"\n" +
                    "Date : "+result.getString(2)+"\n" +
                    "Type : "+result.getString(3)+"\n" +
                    "Content : " +"\n________\n\n"+result.getString(4)+"\n"
                );
            } while (result.moveToNext());
        }
        sentMsgAdapter.notifyDataSetChanged(); // Tell adapter data has updated
        result.close(); // Avoid cursor leaks!
    }
}

Repeat this pattern for your receivedMsg and allMsg Fragments, adding their own refresh() and data loading methods.

Step 2: Call Refresh from the Activity

In your Activity's onOptionsItemSelected, get the Fragments from the ViewPager's adapter and call their refresh methods:

@Override 
public boolean onOptionsItemSelected(MenuItem item){
    switch (item.getItemId()){
        case R.id.refresher_id:
            // Get your ViewPager instance (replace with your ViewPager's ID)
            ViewPager viewPager = findViewById(R.id.your_viewpager_id);
            FragmentPagerAdapter adapter = (FragmentPagerAdapter) viewPager.getAdapter();
            
            // Get Fragments by position (adjust positions to match your ViewPager order)
            Page2_sent_msg sentMsgFragment = (Page2_sent_msg) adapter.getItem(0);
            PageReceivedMsg receivedMsgFragment = (PageReceivedMsg) adapter.getItem(1);
            PageAllMsg allMsgFragment = (PageAllMsg) adapter.getItem(2);
            
            sentMsgFragment.refresh();
            receivedMsgFragment.refresh();
            allMsgFragment.refresh();
            break;
    }
    return super.onOptionsItemSelected(item);
}

Solution 2: Fix the Detach/Attach Approach

If you prefer to use detach/attach to refresh, fix the Fragment lookup and transaction handling:

@Override 
public boolean onOptionsItemSelected(MenuItem item){
    switch (item.getItemId()){
        case R.id.refresher_id:
            FragmentManager fm = getSupportFragmentManager();
            // ViewPager's system tag format: "android:switcher:" + viewPagerId + ":" + position
            int viewPagerId = R.id.your_viewpager_id; // Replace with your ViewPager's ID
            Fragment sentMsg = fm.findFragmentByTag("android:switcher:" + viewPagerId + ":0");
            Fragment receivedMsg = fm.findFragmentByTag("android:switcher:" + viewPagerId + ":1");
            Fragment allMsg = fm.findFragmentByTag("android:switcher:" + viewPagerId + ":2");
            
            // Use separate transactions for each Fragment (or add all ops to one transaction)
            if (sentMsg != null) {
                fm.beginTransaction().detach(sentMsg).attach(sentMsg).commit();
            }
            if (receivedMsg != null) {
                fm.beginTransaction().detach(receivedMsg).attach(receivedMsg).commit();
            }
            if (allMsg != null) {
                fm.beginTransaction().detach(allMsg).attach(allMsg).commit();
            }
            break;
    }
    return super.onOptionsItemSelected(item);
}

Note: This will re-run the Fragment's onCreateView method, so ensure your data loading logic clears old data before adding new items.


Extra Tips

  • Always check if Fragments are not null before performing operations to avoid NullPointerException.
  • Close database cursors after use to prevent memory leaks.
  • If using FragmentStatePagerAdapter, getItem() may create new Fragment instances — use the tag-based lookup from Solution 2 to get existing Fragments.

内容的提问来源于stack exchange,提问作者Mugirase Emmanuel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:08:53