2013-07-26 34 views
1

在我的应用程序中,我注意到如果片段继续卸载并且必须从Web再次获取信息,用户将拥有大量的数据使用情况。我在我的应用程序中有三个Action Bar Tabs,当你到中间(第二个)选项卡时,第一个片段不会卸载,但是当您转到第三个片段并返回第一个片段时,第一个片段已经卸载,因此应用程序重做AsyncTask,使其再次下载信息。保存片段的状态或保存文件并从中更新 - Android

最好我想更改我的代码,以便应用程序从内部存储器中的文件中加载信息,该信息已在之前的日期下载过,因此用户可以随时通过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); 
     } 
    } 
} 

回答

0

我认为你是正确的,试图找到一个简单的方法来此。

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

案例2: 根据您所说的(片段1未被立即销毁),您可能已经在使用attach/detach。如果是这种情况,则系统可能负责销毁片段1作为其内务处理的一部分。在这种情况下,请查看片段1的setRetainInstance(true)。我对此方法的担心是您正在更新此片段中的UI,因此您可能需要将其分成两个单独的片段。

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

发布一些更多的信息,我会充实一点,如果这个答案对你有帮助。

1

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

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

我不确定这是你在找什么,但我希望它指出你在正确的方向。

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所在的片段),那么您可能需要考虑构建service。这会让你从你的UI中抽象你的数据加载。你的服务不会像UI一样消失,所以这可能是你最好的选择。

[1] http://developer.android.com/reference/android/app/Service.html 
0

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