1

在我的应用程序中,我注意到如果片段不断卸载并且不得不再次从网络获取信息,用户将使用大量数据。我的应用程序中有三个操作栏选项卡,当您转到中间(第二个)选项卡时,第一个片段不会卸载,但是当您转到第三个片段并返回第一个片段时,第一个片段已卸载,因此应用程序重做 AsyncTask 使其再次下载信息。

最好我想更改我的代码,以便应用程序从内部存储中的文件加载信息,该文件已在先前日期下载,因此用户可以在 Pulltorefresh 或其他东西需要时更新此信息。我不确定如何将我的代码变成这种方式,我非常怀疑你们中的任何人都愿意花时间为我做这件事,从而引出我的下一个问题。

您可以保存片段的状态以使应用程序将状态保存到第三个选项卡而不是第二个选项卡。我将永远只有三个选项卡,因此只需将其设置为该数量,并且我查看了一些文档,但尚未找到适合我的答案。以下是我的一些应用程序文件,可能对您有用。

List.class(不断卸载的片段)

public class List extends Fragment {

    // All static variables
    static final String URL = "http://aspecficwebsite.com/appinfo.xml";
    // XML node keys
    static final String KEY_GAME = "game"; // parent node
    static final String KEY_ID = "id";
    static final String KEY_TITLE = "title";
    static final String KEY_DATES = "dates";
    static final String KEY_PLATFORMS = "platforms";
    static final String KEY_THUMB_URL = "thumb_url";


    ListView list;
    ArrayList<HashMap<String, String>> songsList;
    View view;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        new TheTask().execute();

            /*
        // Click event for single list row
        list.setOnItemClickListener(new OnItemClickListener() {


        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                long arg3) {
                    // TODO Auto-generated method stub

                }
        }); */
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
        view = inflater.inflate(R.layout.main, container, false);
        //list = (ListView) view.findViewById(R.id.game_list);
        return view;
    }

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

    class TheTask extends AsyncTask<Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            // TODO Auto-generated method stub
            super.onPreExecute();

        }

        @Override
        protected Void doInBackground(Void... params) {
            XMLParser parser = new XMLParser();
            String xml = parser.getXmlFromUrl(URL); // getting XML from URL
            songsList = new ArrayList<HashMap<String, String>>();
            Document doc = parser.getDomElement(xml); // getting DOM element
            NodeList nl = doc.getElementsByTagName(KEY_GAME);
            // looping through all song nodes <song>
            for (int i = 0; i < nl.getLength(); i++) {
                // creating new HashMap
                HashMap<String, String> map = new HashMap<String, String>();
                Element e = (Element) nl.item(i);
                // adding each child node to HashMap key => value
                map.put(KEY_ID, parser.getValue(e, KEY_ID));
                map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
                map.put(KEY_DATES, parser.getValue(e, KEY_DATES));
                map.put(KEY_PLATFORMS, parser.getValue(e, KEY_PLATFORMS));
                map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL));

                // adding HashList to ArrayList
                songsList.add(map);
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            // Getting adapter by passing xml data ArrayList
            LazyAdapter adapter = new LazyAdapter(getActivity(), songsList);
            view = getView();
            ListView mlist = (ListView) view.findViewById(R.id.game_list);
            mlist.setAdapter(adapter);
            super.onPostExecute(result);
        }
    }
}
4

5 回答 5

1

如果您还没有,请使用带有标签的 viewpager 如果您需要帮助,请查看此链接 http://developer.android.com/training/implementing-navigation/lateral.html

然后用你的viewpager做

viewPager.setOffscreenPageLimit(2);

这样,切换时您的任何选项卡都不会卸载。

于 2013-08-03T00:11:08.483 回答
1

肯尼 C 的回答将有助于碎片超出范围。

对于 Internet 数据,您可能需要缓存。抱歉,我无法提供代码,但它非常简单:编写一个用于获取所有数据的类。将结果存储在本地,可能存储在以 URL 的 md5 哈希命名的文件中。下次获取数据时,首先检查文件是否存在:如果存在,则从文件中获取数据,否则从原始来源(互联网)获取。您还可以检查文件的日期戳,如果它是旧的,请不要再使用它。如果您有很多文件/数据,请使用 Android 缓存目录,这样您就不会使用太多内存。

我不确定这是您正在寻找的东西,但我希望它为您指明了正确的方向。

于 2013-08-03T00:55:04.593 回答
0

您可以使用所有变量创建一个Data class实现Serializable,然后保存并加载该对象。如果您希望能够更改数据,请使用版本 int 或字符串来检查是否需要获取新版本的变量。

于 2013-08-08T09:56:01.357 回答
0

我有一个类似的问题。我通过实现 FragmentPagerAdapter 来保留片段的缓存来解决它:

SparseArray<Fragment> fragment_cache = new SparseArray<Fragment>();

然后当系统请求一个片段时,我检查它是否在缓存中:

    @Override
public Fragment getItem(final int item) {
    // If it's in the cache, give it up.
    final Fragment frag = fragment_cache.get(item);
    if (frag != null) {
        return frag;
    }

    // It needs to be created.
    switch (item) {
    case 0:
        fragment_cache.put(
                0,
                Fragment.instantiate(activity,
                        Page1.class.getName()));
        break;

    case 1:
        fragment_cache.put(1,
                Fragment.instantiate(activity, Page2.class.getName()));
        break;

    default: {
        final Bundle b = new Bundle();
        b.putInt("toc_child", item - 2);
        fragment_cache.put(item, Fragment.instantiate(activity,
                Page3.class.getName(), b));
    }
        break;
    }

    // The item is definitely in the cache now.
    return fragment_cache.get(item);
}

这让我可以避免一直重建一些非常大的页面。

另一方面,如果您必须删除片段所在的活动(或者如果您必须删除 ViewPager 所在的片段),那么您可能需要考虑构建一个服务。这将使您可以从 UI 中抽象出数据加载。您的服务不会像 UI 一样消失,因此这可能是您最好的选择。

   [1] http://developer.android.com/reference/android/app/Service.html
于 2013-08-07T17:28:35.057 回答
0

我认为您尝试找到一种简单的方法是正确的。

案例 1:您尚未发布 TabListener 代码,因此首先我将假设您在 onTabSelected 中添加片段并在 onTabUnselected 中删除它们。如果是这种情况,那么您应该考虑使用附加和分离。不同之处在于每次按 tab 1 时都会使用相同的片段实例。

案例 2:根据您所说的(片段 1 不会立即销毁),您可能已经在使用附加/分离。如果是这种情况,那么系统可能负责销毁片段 1 作为其内部管理的一部分。在这种情况下,请查看对片段 1 使用 setRetainInstance(true)。我对这种方法的担忧是您正在更新此片段中的 UI,因此您可能需要将其拆分为两个单独的片段。

在任何一种情况下,您都应该考虑要为方向改变做什么。如果您很乐意最初锁定方向,您可能会发现您可以很容易地完成这项工作。但是,如您所知,更好的方法是允许方向更改并使用 saveInstanceState。

如果这个答案对您有帮助,请发布更多信息,我会充实一下。

于 2013-08-02T23:17:57.430 回答