Accessing a Loader created in one fragment from another fragment

大城市里の小女人 提交于 2019-12-06 11:09:02

问题


I have an app with a fairly standard fragment layout. An expandable listview fragment on the left and a panel on the right that is used for different things depending on what the user chooses to do with the list on the left (displaying data, adding new data, etc).

I'm using the LoaderManager (first time using loaders) with CommonWare's loaderex library as I have no need or desire to create a Content Provider for my database just so I can use a standard CursorLoader. This setup works great for displaying my list.

The issue I am having is when I use the second fragment to add data to the database. I cannot figure out how to trigger a re-load of the list in the first fragment. For the life of me I cannot figure out how to grab the loader from the first fragment in the second so that it will be aware that the data needs to be pulled again, nor can I seem to figure how to manually trigger a re-load.

As this is my first attempt at using Loaders, if I'm doing something improperly I'd be happy to be (gently) re-directed down a better path.

Fragment 1

public class StudentListFragment extends ListFragment implements
        LoaderManager.LoaderCallbacks<Cursor> {

    private TAOpenHelper mDbHelper = null;
    private MyExpandableListAdapter mAdapter = null;
    private ExpandableListView lv = null;
    private Button addStudentButton;
    public static long mRowId = 0;
    public SQLiteCursorLoader studentLoader=null;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.leftlistfragment_entry, container,
                false);
        return v;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        addStudentButton = (Button) getActivity().findViewById(R.id.AddButton);
        addStudentButton.setText(getResources().getString(
                R.string.button_add_student));
        addStudentButton.setOnClickListener(addStudentButtonHandler);

        lv = (ExpandableListView) getListView();

        mDbHelper = TAOpenHelper.getInstance(getActivity());

        fillData();
        getLoaderManager().getLoader(-1);
        if (studentLoader != null && !studentLoader.isReset()) {
            getLoaderManager().restartLoader(-1, null, this);
        } else {
            getLoaderManager().initLoader(-1, null, this);
        }
    }

    private void fillData() {
        mAdapter = new MyExpandableListAdapter(getActivity(), this,
                R.layout.listlayout_exp_double_group,
                R.layout.listlayout_exp_double_child,
                new String[] { TeacherAidDB.STUDENT_FIRST,
                        TeacherAidDB.STUDENT_LAST }, new int[] {
                        R.id.ListItem1, R.id.ListItem2 }, new String[] {
                        TeacherAidDB.CLASS_NAME, TeacherAidDB.CLASS_LEVEL },
                new int[] { R.id.ListItem1, R.id.ListItem2 });
        lv.setAdapter(mAdapter);
    }

    public class MyExpandableListAdapter extends SimpleCursorTreeAdapter {
        protected final SparseIntArray mGroupMap;
        private StudentListFragment mFragment;

        public MyExpandableListAdapter(Context context,
                StudentListFragment clf, int groupLayout, int childLayout,
                String[] groupFrom, int[] groupTo, String[] childrenFrom,
                int[] childrenTo) {
            super(context, null, groupLayout, groupFrom, groupTo, childLayout,
                    childrenFrom, childrenTo);
            mFragment = clf;
            mGroupMap = new SparseIntArray();
        }

        @Override
        protected Cursor getChildrenCursor(Cursor groupCursor) {
            int groupPos = groupCursor.getPosition();
            int groupId = groupCursor.getInt(groupCursor
                    .getColumnIndex(TeacherAidDB.CLASS_ROWID));
            mGroupMap.put(groupId, groupPos);
            Loader<Cursor> loader = getActivity().getLoaderManager().getLoader(
                    groupId);
            if (loader != null && !loader.isReset()) {
                getActivity().getLoaderManager().restartLoader(groupId, null,
                        mFragment);
            } else {
                getActivity().getLoaderManager().initLoader(groupId, null,
                        mFragment);
            }
            return null;
        }

        public SparseIntArray getGroupMap() {
            return mGroupMap;
        }
    }

    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        if (id != -1) { // Child Cursor
            studentLoader = new SQLiteCursorLoader(getActivity(), mDbHelper,
                    TeacherAidDB.STUDENT_LIST_CLASS_QUERY + id, null);
        } else { // Group Cursor
            studentLoader = new SQLiteCursorLoader(getActivity(), mDbHelper,
                    TeacherAidDB.STUDENT_LIST_QUERY, null);
        }
        return studentLoader;
    }

    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        int id = loader.getId();
        if (id != -1) { // Child cursor
            if (!data.isClosed()) {
                SparseIntArray groupMap = mAdapter.getGroupMap();
                int groupPos = groupMap.get(id);
                mAdapter.setChildrenCursor(groupPos, data);
            }
        } else { // Groups cursor
            mAdapter.setGroupCursor(data);
        }
    }

    @Override
    public void onLoaderReset(Loader<Cursor> arg0) {
        mAdapter.changeCursor(null);
    }

    View.OnClickListener addStudentButtonHandler = new View.OnClickListener() {
        public void onClick(View v) {
            AddPerson personadd = AddPerson.newInstance(AddPerson.STUDENT, AddPerson.CREATE, mRowId);
            getFragmentManager().beginTransaction()
                    .replace(R.id.rightpane, personadd).commit();
        }
    };
}

Fragment 2

public class AddPerson extends Fragment {

    public static int STUDENT = 0;
    public static int TEACHER = 1;
    public static int CREATE = 0;
    public static int EDIT = 1;
    private int mRowId;
    private TAOpenHelper mDbHelper;
    private Cursor personedit;
    private Button commit;
    private Button cancel;

    int who;
    int what;
    long rowId;

    static AddPerson newInstance(int type, int action, long rowid) {
        AddPerson f = new AddPerson();
        Bundle args = new Bundle();
        args.putInt("type", type);
        args.putInt("action", action);
        args.putLong("rowid", rowid);
        f.setArguments(args);
        return f;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        who = getArguments().getInt("type");
        what = getArguments().getInt("action");
        rowId = getArguments().getInt("rowid");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.dialog_person_add, container, false);

        mDbHelper = TAOpenHelper.getInstance(getActivity());

        if (what == EDIT) {
            if (who == STUDENT) {
                // Student Edit stuff here
            } else {
                // Teacher Edit stuff here 
            }
        } else { 
            if (who == STUDENT) { 
                // Student Create stuff here
            } else {
                // Teacher Create stuff here 
            }
        }

        // Code to gather data from user goes here

        commit = (Button) v.findViewById(R.id.commitbutton);
        commit.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {

                first = firstTxt.getText().toString();
                last = lastTxt.getText().toString();
                street = streetTxt.getText().toString();
                city = cityTxt.getText().toString();
                zip = zipTxt.getText().toString();
                phone = phoneTxt.getText().toString();
                email = emailTxt.getText().toString();
                if (what == CREATE) {
                    processAdd(who);
                } else {
                    processUpdate(who);
                }
            }
        });

        cancel = (Button) v.findViewById(R.id.cancelbutton);
        cancel.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                Fragment check = getFragmentManager().findFragmentById(
                        R.id.rightpane);
                getFragmentManager().beginTransaction().remove(check).commit();
            }
        });
        return v;
    }

    private void processAdd(int who) {
        ContentValues initialValues = new ContentValues();
        if (who == STUDENT) {
            initialValues.put(TeacherAidDB.STUDENT_FIRST, first);
            initialValues.put(TeacherAidDB.STUDENT_LAST, last);
            initialValues.put(TeacherAidDB.STUDENT_STREET, street);
            initialValues.put(TeacherAidDB.STUDENT_CITY, city);
            initialValues.put(TeacherAidDB.STUDENT_STATE, state);
            initialValues.put(TeacherAidDB.STUDENT_ZIP, zip);
            initialValues.put(TeacherAidDB.STUDENT_PHONE, phone);
            initialValues.put(TeacherAidDB.STUDENT_EMAIL, email);
            initialValues.put(TeacherAidDB.STUDENT_BDAY, birthday);

            // How to get studentLoader from fragment 1?
            //studentLoader.insert(TeacherAidDB.STUDENT_TABLE, null, initialValues);
        }
    }
}

回答1:


With a regular CursorLoader, this would happen automagically via the ContentObserver framework, which eventually boils down to a bunch of static data members.

With SQLiteCursorLoader, ContentObserver is not available, with the closest simulacrum being to route your CRUD operations through the Loader so it knows to reload the Cursor. And that is really only designed for use within a single activity.

So, as Luksprog suggested, your best option is to delegate CRUD work to the containing activity.

If these fragments might be hosted by disparate activities (e.g., for small/normal vs. large/xlarge screen sizes), define a common interface for handling this work, and have the fragments delegate to the interface.



来源:https://stackoverflow.com/questions/13304484/accessing-a-loader-created-in-one-fragment-from-another-fragment

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!