访问从另一个片段中的一个片段创建一个Loader [英] Accessing a Loader created in one fragment from another fragment

查看:326
本文介绍了访问从另一个片段中的一个片段创建一个Loader的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个相当标准的片段布局的应用程序。在左侧的可膨胀列表视图片段和一个面板上的右侧是用于根据用户选择做与左边的列表什么不同的事情(显示数据,增加新的数据,等等)。

我使用LoaderManager(第一次使用装载机)与CommonWare的 loaderex 库,因为我没有必要或意欲打造一个内容提供商我的数​​据库,这样我可使用标准CursorLoader。这种设置用于显示我的名单上的伟大工程。

我遇到的问题是,当我使用第二个片段将数据添加到数据库中。我无法弄清楚如何触发重新加载列表中的第一个片段。对于我的生活中,我无法弄清楚如何抓住从第二到第一片段加载器,这样它会意识到,需要对数据进行再拉,我也似乎可以推测如何手动触发重新加载。

由于这是我在使用装载机第一次尝试,如果我做一些不当我很高兴(轻轻)重新定向下一个更好的路径。

片段1

 公共类StudentListFragment扩展ListFragment工具
        LoaderManager.LoaderCallbacks<光标> {

    私人TAOpenHelper mDbHelper = NULL;
    私人MyExpandableListAdapter mAdapter = NULL;
    私人ExpandableListView LV = NULL;
    私人按钮addStudentButton;
    公共静态长mRowId = 0;
    公共SQLiteCursorLoader studentLoader = NULL;

    @覆盖
    公共查看onCreateView(LayoutInflater充气,容器的ViewGroup,
            捆绑savedInstanceState){
        视图V = inflater.inflate(R.layout.leftlistfragment_entry,集装箱,
                假);
        返回伏;
    }

    @覆盖
    公共无效onActivityCreated(包savedInstanceState){
        super.onActivityCreated(savedInstanceState);

        addStudentButton =(按钮)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);
        如果(studentLoader =空&安培;!&安培;!studentLoader.isReset()){
            getLoaderManager()restartLoader(-1,空,这一点)。
        } 其他 {
            getLoaderManager()initLoader(-1,空,这一点)。
        }
    }

    私人无效fillData(){
        mAdapter =新MyExpandableListAdapter(getActivity(),这一点,
                R.layout.listlayout_exp_double_group,
                R.layout.listlayout_exp_double_child,
                新的String [] {TeacherAidDB.S​​TUDENT_FIRST,
                        TeacherAidDB.S​​TUDENT_LAST},新的INT [] {
                        R.id.ListItem1,R.id.ListItem2},新的String [] {
                        TeacherAidDB.CLASS_NAME,TeacherAidDB.CLASS_LEVEL},
                新的INT [] {R.id.ListItem1,R.id.ListItem2});
        lv.setAdapter(mAdapter);
    }

    公共类MyExpandableListAdapter扩展SimpleCursorTreeAdapter {
        受保护的最终SparseIntArray mGroupMap;
        私人StudentListFragment mFragment;

        公共MyExpandableListAdapter(上下文的背景下,
                StudentListFragment CLF,诠释的GroupLayout,INT childLayout,
                的String [] groupFrom,INT [] groupTo,字符串[] childrenFrom,
                INT [] childrenTo){
            超(背景下,空,GroupLayout的,groupFrom,groupTo,childLayout,
                    childrenFrom,childrenTo);
            mFragment = CLF;
            mGroupMap =新SparseIntArray();
        }

        @覆盖
        受保护的光标getChildrenCursor(光标groupCursor){
            INT groupPos = groupCursor.getPosition();
            INT的groupId = groupCursor.getInt(groupCursor
                    .getColumnIndex(TeacherAidDB.CLASS_ROWID));
            mGroupMap.put(的groupId,groupPos);
            装载机<光标>装载机= getActivity()。getLoaderManager()。getLoader(
                    的groupId);
            如果(装载机= NULL和放大器;!&安培;!loader.isReset()){
                getActivity()。getLoaderManager()。restartLoader(的groupId,空,
                        mFragment);
            } 其他 {
                getActivity()。getLoaderManager()。initLoader(的groupId,空,
                        mFragment);
            }
            返回null;
        }

        公共SparseIntArray getGroupMap(){
            返回mGroupMap;
        }
    }

    公共装载机<光标> onCreateLoader(INT ID,捆绑参数){
        如果(ID!=  -  1){//子游标
            studentLoader =新SQLiteCursorLoader(getActivity(),mDbHelper,
                    TeacherAidDB.S​​TUDENT_LIST_CLASS_QUERY + ID,NULL);
        }其他{//集团光标
            studentLoader =新SQLiteCursorLoader(getActivity(),mDbHelper,
                    TeacherAidDB.S​​TUDENT_LIST_QUERY,NULL);
        }
        返回studentLoader;
    }

    公共无效onLoadFinished(装载机<光标>装载机,光标数据){
        INT的id = loader.getId();
        如果(ID!=  -  1){//子光标
            如果(!data.isClosed()){
                SparseIntArray的groupMap = mAdapter.getGroupMap();
                INT groupPos = groupMap.get(ID);
                mAdapter.setChildrenCursor(groupPos,数据);
            }
        }其他{//组光标
            mAdapter.setGroupCursor(数据);
        }
    }

    @覆盖
    公共无效onLoaderReset(装载机<光标>为arg0){
        mAdapter.changeCursor(空);
    }

    View.OnClickListener addStudentButtonHandler =新View.OnClickListener(){
        公共无效的onClick(视图v){
            AddPerson personadd = AddPerson.newInstance(AddPerson.STUDENT,AddPerson.CREATE,mRowId);
            getFragmentManager()的BeginTransaction()
                    .replace(R.id.rightpane,personadd).commit();
        }
    };
}
 

片段2

 公共类AddPerson扩展片段{

    公共静态INT学生= 0;
    公共静态INT教师= 1;
    公共静态INT CREATE = 0;
    公共静态INT EDIT = 1;
    私人诠释mRowId;
    私人TAOpenHelper mDbHelper;
    私人光标personedit;
    私人按钮提交;
    私人按钮来取消;

    诠释谁;
    诠释了什么;
    长ROWID;

    静态AddPerson的newInstance(int型的,INT动作,长ROWID){
        AddPerson F =新AddPerson();
        捆绑的args =新包();
        args.putInt(类,类型);
        args.putInt(行动,行动);
        args.putLong(ROWID,ROWID);
        f.setArguments(参数);
        返回F;
    }

    @覆盖
    公共无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);
        谁= getArguments()调用getInt(类型)。
        什么= getArguments()调用getInt(行动)。
        ROWID = getArguments()调用getInt(ROWID)。
    }

    @覆盖
    公共查看onCreateView(LayoutInflater充气,容器的ViewGroup,
            捆绑savedInstanceState){
        视图V = inflater.inflate(R.layout.dialog_person_add,集装箱,假);

        mDbHelper = TAOpenHelper.getInstance(getActivity());

        如果(什么==编辑){
            如果(谁==学生){
                //学生编辑这里的东西
            } 其他 {
                //教师编辑这里的东西
            }
        } 其他 {
            如果(谁==学生){
                //学生创建的东西在这里
            } 其他 {
                //教师创建的东西在这里
            }
        }

        // code收集数据从用户到这里

        提交=(按钮)v.findViewById(R.id.commitbutton);
        commit.setOnClickListener(新OnClickListener(){
            公共无效的onClick(视图v){

                首先= firstTxt.getText()的toString();
                最后= lastTxt.getText()的toString();
                街道= streetTxt.getText()的toString()。
                。城市= cityTxt.getText()的toString();
                。邮编= zipTxt.getText()的toString();
                。手机= phoneTxt.getText()的toString();
                。电子邮件= emailTxt.getText()的toString();
                如果(什么== CREATE){
                    processAdd(谁);
                } 其他 {
                    processUpdate(谁);
                }
            }
        });

        取消=(按钮)v.findViewById(R.id.cancelbutton);
        cancel.setOnClickListener(新OnClickListener(){
            公共无效的onClick(视图v){
                片段检查= getFragmentManager()。findFragmentById(
                        R.id.rightpane);
                。getFragmentManager()的BeginTransaction()删除(检查).commit()。
            }
        });
        返回伏;
    }

    私人无效processAdd(INT谁){
        ContentValues​​ initialValues​​ =新ContentValues​​();
        如果(谁==学生){
            initialValues​​.put(TeacherAidDB.S​​TUDENT_FIRST,第一);
            initialValues​​.put(TeacherAidDB.S​​TUDENT_LAST,最后一个);
            initialValues​​.put(TeacherAidDB.S​​TUDENT_STREET,街道);
            initialValues​​.put(TeacherAidDB.S​​TUDENT_CITY,市);
            initialValues​​.put(TeacherAidDB.S​​TUDENT_STATE,状态);
            initialValues​​.put(TeacherAidDB.S​​TUDENT_ZIP,ZIP);
            initialValues​​.put(TeacherAidDB.S​​TUDENT_PHONE,电话);
            initialValues​​.put(TeacherAidDB.S​​TUDENT_EMAIL,电子邮件);
            initialValues​​.put(TeacherAidDB.S​​TUDENT_BDAY,生日);

            //如何从片段1获得studentLoader?
            //studentLoader.insert(TeacherAidDB.S​​TUDENT_TABLE,空,initialValues​​);
        }
    }
}
 

解决方案

通过普通的 CursorLoader ,这将自动地通过发生ContentObserver 框架,最终归结为一堆的静态数据成员。

使用 SQLiteCursorLoader ContentObserver 不可用,与最接近的仿过被路由的CRUD操作的装载机所以它知道要刷新光标。而的是真的只适用于在一个活动中使用。

所以,作为Luksprog建议,你最好的选择是CRUD工作委托给包含的活动。

如果这些碎片可能是由不同的活动(例如,对于小/正常与大/ XLARGE屏幕尺寸)主办,定义一个通用的接口来处理这项工作,并有碎片委托给该接口。

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

解决方案

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.

这篇关于访问从另一个片段中的一个片段创建一个Loader的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆