【问题标题】:Only load ListFragment once via AsyncTask仅通过 AsyncTask 加载一次 ListFragment
【发布时间】:2013-04-09 13:26:27
【问题描述】:

我正在努力学习 Android 开发,并且仍在努力思考框架的工作原理以及如何正确扩展所有这些类。

我的目标是:一个Activity 有一个ViewPager 循环通过五个ListFragments。绑定到每个ListFragment 的数据来自一个使用AsyncTask 调用的Web API。

我的问题是,每当我切换到新片段时,都会再次调用 MyListFragment.newInstance(),它每次都会调用 AsyncTask。我试图在第一次加载ListFragment 时调用一次AsyncTask,以减少网络调用并保存页面状态。最终我想做一个“下拉刷新”类型的事情,这意味着当我切换页面时不会重新加载数据。

我一直在关注 Android 开发者的 this 指南,试图实现这一目标。我最终得到的是这样的:

public class MainActivity extends FragmentActivity {

    MyPagerAdapter mMyPagerAdapter;
    ViewPager mViewPager;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mMyPagerAdapter = new MyPagerAdapter(getSupportFragmentManager());

        mViewPager = (ViewPager) findViewById(R.id.pager);
        mViewPager.setAdapter(mMyPagerAdapter);
    }


    public class MyPagerAdapter extends FragmentPagerAdapter {
        public static final int NUM_PAGES = 5;

        public MyPagerAdapter(FragmentManager fm) {
            super(fm);
        }   

        @Override
        public Fragment getItem(int i) {
            return MyListFragment.newInstance(getPageTitle(i).toString());
        }

        @Override
        public int getCount() {
            return NUM_PAGES;
        }

        @Override
        public CharSequence getPageTitle(int position) { 
            String[] titles = getResources().getStringArray(R.array.thing_sort_titles);
            return titles[position];
        }

    }


    public static class MyListFragment extends ListFragment {
        public static final String ARG_CATEGORY = "category_title";
        ArrayList<HashMap<String, String>> mylist;

        public MyListFragment() {
            mylist = new ArrayList<HashMap<String, String>>();
        }

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

            Bundle args = getArguments();
            URI url = new URI("http://api.remotesite.com/" + args.getString(ARG_CATEGORY));
            new MyListAsyncTask().execute(url);
        }

        static MyListFragment newInstance(String category) {
            MyListFragment f = new MyListFragment();

            Bundle args = new Bundle();
            args.putString(ARG_CATEGORY, category);
            f.setArguments(args);

            return f;
        }

        private class MyListAsyncTask extends AsyncTask<URI, Integer, ArrayList<HashMap<String, String>>> {

            protected ArrayList<HashMap<String, String>> doInBackground(URI... uris) {
                try {
                    JSONArray json = JSON.getJSONfromURL(uris[0]);
                    for (int i = 0; i < json.length(); i++) {
                        HashMap<String, String> map = new HashMap<String, String>();
                        JSONObject obj = json.getJSONObject(i)
                        map.put("title", obj.getString("title"));
                        map.put("author", obj.getString("author"));
                        map.put("id", obj.getString("id"));
                        mylist.add(map);
                    }
                } catch (Exception ex) {
                }
                return mylist;
            }

            protected void onPostExecute(ArrayList<HashMap<String, String>> list) {
                ListAdapter adapter = new SimpleAdapter(
                    getActivity(), 
                    mylist,
                    R.layout.list_item, 
                    new String[] { "title", "author" }, 
                    new int[] { R.id.text_title, R.id.text_author }
                );
                MyListFragment.this.setListAdapter(adapter);
            }
        }
    }
}

我尝试在FragmentPagerAdapter 中创建一个ListFragments 数组,并且仅在该索引为空时调用MyListFragment.newInstance,但它最终没有改变任何东西。

【问题讨论】:

    标签: android android-asynctask android-fragments android-listfragment


    【解决方案1】:

    请尝试使用setOffscreenPageLimit 解决您的问题。 如果您使用它,它将缓存您的片段并且不会再次调用它。

    【讨论】:

    • 谢谢,这解决了我的问题。我用mViewPager.setOffscreenPageLimit(NUM_PAGES)。该应用程序在开始时加载了所有 5 个页面,之后没有加载它们。现在刷新单个Fragment...
    • 请记住,虽然它是您的方案的有效解决方案,但如果 NUM_PAGES 是一个更大的数字,您可能会遇到内存和启动时间问题。
    • 同意。该文档说对于“少量”页面(3-4)是安全的。我将永远有 5 页(对于这个应用程序),所以我认为它会没事的。
    【解决方案2】:

    我建议您使用装载程序 (http://developer.android.com/guide/components/loaders.html) 来处理您的情况。

    加载器在这方面非常聪明,如果您使用相同的 ID,它会自动将与以前相同的数据返回给调用组件。

    例如:

    片段位置 0 调用 initLoader(0, null, this); 然后片段位置 1 调用 initLoader(1, null, this); 等等......

    这样,每当initLoader(1

    【讨论】:

    • 感谢您的回答。我会研究一下装载机,看看它们是否也适合。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-05
    相关资源
    最近更新 更多