1

私のアプリでは、フラグメントがアンロードされ続け、Web から情報を再度取得する必要がある場合、ユーザーが大量のデータを使用することに気付きました。アプリに 3 つのアクション バー タブがあり、中央 (2 番目) のタブに移動すると、最初のフラグメントはアンロードされませんが、3 番目のフラグメントに移動して最初に戻ると、最初のフラグメントがアンロードされているため、アプリAsyncTask をやり直し、情報を再度ダウンロードします。

できればコードを変更して、アプリが以前にダウンロードされた内部ストレージのファイルから情報をロードし、ユーザーが Pulltorefresh などで必要なときにいつでもこの情報を更新できるようにしたいと考えています。コードをこのように変換する方法がわかりません。次の質問につながるように、あなたが私のために時間を費やしたいとは思わないでしょう。

フラグメントの状態を保存して、2 番目ではなく 3 番目のタブまでアプリに状態を保存させることはできますか。タブは 3 つしかないので、その量に設定する必要があります。いくつかのドキュメントを調べましたが、自分に合った答えをまだ見つけていません。以下は、あなたに役立つかもしれない私のアプリファイルのいくつかです。

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

Kenny Cの回答は、フラグメントが範囲外になるのに役立ちます。

インターネット データの場合、キャッシュが必要になる場合があります。申し訳ありませんが、コードを提供することはできませんが、非常に簡単です: すべてのデータを取得するために使用するクラスを作成します。結果をローカルに保存します。おそらく、URL の md5 ハッシュから名前が付けられたファイルに保存します。次回データをフェッチするときは、まずファイルが存在するかどうかを確認します。存在する場合はファイルからデータを取得し、存在しない場合は元のソース (インターネット) から取得します。ファイルの日付スタンプを確認することもできます。古い場合は使用しないでください。大量のファイル/データがある場合は、Android キャッシュ ディレクトリを使用して、メモリを使いすぎないようにします。

これがあなたが探しているものかどうかはわかりませんが、正しい方向に向けられることを願っています.

于 2013-08-03T00:55:04.593 に答える
1

まだ行っていない場合は、タブでビューページャーを使用してください http://developer.android.com/training/implementing-navigation/lateral.html

次に、ビューページャーで行います

viewPager.setOffscreenPageLimit(2);

これにより、切り替え時にタブがアンロードされることはありません。

于 2013-08-03T00:11:08.483 に答える
0

これに対する簡単なアプローチを見つけようとするのは正しいと思います。

ケース 1: TabListener コードを投稿していないため、まず onTabSelected にフラグメントを追加し、onTabUnselected にフラグメントを削除していると仮定します。この場合は、代わりにアタッチとデタッチの使用を検討する必要があります。違いは、タブ 1 を押すたびにフラグメントの同じインスタンスが使用されることです。

ケース 2: あなたが言ったこと (フラグメント 1 がすぐに破棄されない) に基づいて、既にアタッチ/デタッチを使用している可能性があります。この場合、システムはハウスキーピングの一部としてフラグメント 1 を破棄する責任がある可能性があります。この場合、フラグメント 1 に setRetainInstance(true) を使用する方法を見てください。このアプローチに関する私の懸念は、このフラグメントで UI を更新していることです。そのため、フラグメントを 2 つの別々のフラグメントに分割する必要がある場合があります。

どちらの場合でも、オリエンテーションの変更のために何をしようとしているのかを検討する必要があります。最初に向きをロックしても問題ない場合は、これを非常に簡単に機能させることができることに気付くかもしれません。ただし、ご存知のように、方向の変更を許可し、saveInstanceState を使用することをお勧めします。

この回答が役立つ場合は、さらに情報を投稿してください。

于 2013-08-02T23:17:57.430 に答える
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

Data classすべての変数で実装する を作成し、Serializableそのオブジェクトを保存してロードできます。データを変更できるようにする場合は、バージョン int または文字列を使用して、変数の新しいバージョンを取得する必要があるかどうかを確認します。

于 2013-08-08T09:56:01.357 に答える