How to update a Fragment that has a Gridview popul

2019-01-12 12:40发布

问题:

I have a ViewPager with two tabs which holds fragment. Inside the first fragment, I have a Gridview which is being populated with Sqlite Db.

I have an custom alertdialog in my Activity, which is the parent of the Fragments.

When the alertdialog closes, it either adds/removes/updates the Sqlite Db:

DataBaseHelper dbh = DataBaseHelper(this);
...
positiveButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        dbh.addVal(new TheData(editName.getText().toString(), editAge.getText().toString())); //adds a row to the Sqlite Db
        dialog.dismiss();
        //on dismiss, refresh the Fragment, which in turn will display the updated GridView.
    }
});
...

How can I update complete the following:

//on dismiss, refresh the Fragment, which in turn will display the updated GridView.

回答1:

You could use Intents and Intent Filters with a Broadcast Receiver for this.

  1. Create a BroadcastReceiver instance in the fragment where you want to update the data.
  2. Create an IntentFilter and set an action string (maybe 'db.update') to it and register it with your application context (you could do this via your fragment by calling getActivity().getApplicationContext().registerReceiver(receiver, filter).
  3. In your AlertDialog, after you update your database, create an Intent with the same action string you set above (in our case, 'db.update') and use context to send it out (getActivity().getApplicationContext().sendBroadcast(intent)). Your BroadcastReceiver's onReceive() method would be called in your fragment and you can call the method to refresh or reload your data there. See sample code below:

Say this is your fragment

public class YourFragment extends Fragment {

private GridView mGridView;
private BaseAdapter mAdapter;
private BroadcastReceiver mReceiver;

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    //inflate view as usual
    View view = inflater.inflate(R.layout.yourlayour, container, false);
    ...

    //create instance of broadcast receiver
    mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) { //when intent is receiver, this method is called
            if(intent.getAction().contentEquals("db.update")){
                //update intent received, call method to refresh your content loader
                refreshFragment();
            }
        }
    };

    //create a new intent filter
    IntentFilter mDataUpdateFilter = new IntentFilter("db.update");

    //register our broadcast receiver and intent filter
    getActivity().getApplicationContext().registerReceiver(mReceiver, mDataUpdateFilter);
    return view;
}

@Override
public void onDestroy() {
    super.onDestroy();
    //never forget to unregister the receiver when you're done, it could cause your app to crash
    //if it receives an intent and calls null pointing methods in your code
    getActivity().getApplicationContext().unregisterReceiver(mReceiver);
}  }

Then in your AlertDialog as you did above, send the intent to this receiver by:

DataBaseHelper dbh = DataBaseHelper(this);
        ...
        positiveButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dbh.addVal(new TheData(editName.getText().toString(), editAge.getText().toString())); //adds a row to the Sqlite Db


                //Create an intent with our action
                Intent updateIntent = new Intent("db.update");

                //send the intent by
                getContext().getApplicationContext().sendBroadcast(updateIntent);
                dialog.dismiss();
            }
        });
        ...

Don't forget to unregister your broadcast receiver when your fragment is destroyed. Call getActivity().getApplicationContext().unregisterReceiver(receiver); in your onDestroy() method.

I should also point out that the onReceive() method of your broadcast receiver would always be called on the main thread, even if you send your intent from a background thread.



回答2:

Here is a trick that i use to access Fragments inside a ViewPager in my custom viewPagerAdapter, i add two methods

public class CustomViewPagerAdapter extends FragmentPagerAdapter {
    .....
    private String getFragmentTag(int viewId, int index) {
            return "android:switcher:" + viewId + ":" + index;
    }

    //mFragManager is a reference to FragmentManager
    public Fragment getFragmentByTag(int containerId, int position) {
        return mFragManager.findFragmentByTag(getFragmentTag(containerId, position));
    }
}

then in your activity or wherever you can access the customViewPager

YourFragment frag = (YourFragment) customViewPager
                            .getFragmentByTag(YouViewPager.getId(), position);

after that, add a method in YourFragment refreshData (if you like the name!) and in it refresh the grid Hope this help



回答3:

FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.detach(frag).attach(frag).commit(); //frag is my Fragment instance...

Each time the dialog closed and it did the trick... simple and easy!