1. 程式人生 > >Fragment記憶體回收後重疊及恢復資料問題

Fragment記憶體回收後重疊及恢復資料問題

package com.mine.fragmentdemo;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import
android.widget.TextView; import static com.mine.fragmentdemo.FragmentFactory.F1; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private TextView tv1; private TextView tv2; private TextView tv3; private FragmentManager mFragmentManager; private
Fragment mFragment1; private Fragment mFragment2; private Fragment mFragment3; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv1 = (TextView) findViewById(R.id.tv1); tv2 = (TextView) findViewById(R.id.tv2); tv3 = (TextView) findViewById(R.id.tv3); tv1.setOnClickListener(this
); tv2.setOnClickListener(this); tv3.setOnClickListener(this); /* * Fragment重疊原因一 * 1.Activity橫豎屏切換(或者後臺的Activity由於記憶體不足,被回收),導致Activity重走生命週期 * 2.但是FragmentManager會儲存之前的Fragment,當頁面恢復時,會把這些Fragment都顯示出來 * 3.此時,在Activity的onCreate裡面你再次new Fragment時並且add了一次,會導致Fragment的重疊 * 4.解決方法是第一次時直接new,第二次頁面恢復後,要使用mFragmentManager通過Tag來取得, * 第一次和第二次的判斷標誌就是savedInstanceState是否為null(記憶體回收Activity時,會把資料儲存在savedInstanceState裡) * */ // ★全域性用一個mFragmentManager mFragmentManager = getSupportFragmentManager(); if (savedInstanceState == null) { mFragment1 = FragmentFactory.createFragment(F1); // ★ 為什麼第一個fragment在新增的時候用的是replace而不是add? // 防止回退到首頁的時候顯示Activity的空的FrameLayout(這是指有回退棧情況,沒回退棧用add也不會出現空白,因為已經直接退出了)(★★★其實最還是,直接在預設第一個載入的Fragment不要加入回退棧就好了) selectFragment1(mFragment1); } else { // 先使用mFragmentManager通過Tag來取得,只要他add過,就給他添加了Tag // 否則直接重寫建立一個Fragment的話,會導致重疊 mFragment1 = mFragmentManager.findFragmentByTag(Fragment1.class.getName()); if (mFragment1 == null) { mFragment1 = FragmentFactory.createFragment(FragmentFactory.F1); } mFragment2 = mFragmentManager.findFragmentByTag(Fragment2.class.getName()); if (mFragment2 == null) { // 有可能獲得為空,因為你還沒與把mFragment2新增,還沒有給其設定Tag,所以這裡為空 mFragment2 = FragmentFactory.createFragment(FragmentFactory.F2); } mFragment3 = mFragmentManager.findFragmentByTag(Fragment3.class.getName()); if (mFragment3 == null) { mFragment3 = FragmentFactory.createFragment(FragmentFactory.F3); } position = savedInstanceState.getInt("position"); switch (position) { case 1: selectFragment(mFragment1); break; case 2: selectFragment(mFragment2); break; case 3: selectFragment(mFragment3); break; } } } //記錄Fragment的位置 private int position = 1; @Override protected void onSaveInstanceState(Bundle outState) { //記錄當前的position outState.putInt("position", position); Log.e("Ccc", position + "dfssf"); // ★★★★★★★★別忘了下下面的super.onSave,否則會報錯 super.onSaveInstanceState(outState); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.tv1: if (mFragment1 == null) { mFragment1 = FragmentFactory.createFragment(FragmentFactory.F1); } selectFragment(mFragment1); // 記錄下當前是哪一個Fragment, // 方便重新走Activity生命週期時,獲取其死亡時的位置 position = 1; break; case R.id.tv2: if (mFragment2 == null) { mFragment2 = FragmentFactory.createFragment(FragmentFactory.F2); } selectFragment(mFragment2); position = 2; break; case R.id.tv3: if (mFragment3 == null) { mFragment3 = FragmentFactory.createFragment(FragmentFactory.F3); } selectFragment(mFragment3); position = 3; break; } } private void selectFragment(Fragment fragment) { FragmentTransaction transaction = mFragmentManager.beginTransaction(); hideAll(transaction); if (!fragment.isAdded()) { transaction.add(R.id.fl, fragment, fragment.getClass().getName()); // transaction.addToBackStack(null); } Log.e("qqq",mFragmentManager.getBackStackEntryCount()+"qqq"); transaction.show(fragment).commit(); Log.e("qqq",mFragmentManager.getBackStackEntryCount()+"hoe"); } private void selectFragment1(Fragment fragment) { FragmentTransaction transaction = mFragmentManager.beginTransaction(); transaction.replace(R.id.fl, fragment, fragment.getClass().getName()).commit(); } private void hideAll(FragmentTransaction transaction) { if (mFragment1 != null) { // 必須使用同一個transaction,跟add/show時候一樣 // 同一個事物進行了所有的add/hide/show,之後統一commit就行了 // 中間不能commit事物,因為一個事物只能是提交一次,重複提交會報錯 // 即:每一次點選,生成一個事物,操作完後,提交這個事物 transaction.hide(mFragment1); } if (mFragment2 != null) { transaction.hide(mFragment2); } if (mFragment3 != null) { transaction.hide(mFragment3); } } /** * 手動回退 */ public void popBackStack(){ if (mFragmentManager.getBackStackEntryCount()>0){ mFragmentManager.popBackStack(); }else { finish(); } } @Override public void onBackPressed() { // super.onBackPressed();遮蔽掉系統的返回事件 popBackStack(); } }

===

package com.mine.fragmentdemo;

import android.support.v4.app.Fragment;

import java.util.HashMap;

/**
 * Created by a on 2017/4/5.
 */
public class FragmentFactory {
    public final static int F1 = 1;
    public final static int F2 = 2;
    public final static int F3 = 3;

    private static HashMap<Integer, Fragment> mFragments = new HashMap<>();


    public static Fragment createFragment(int fragmentName) {
        // 從快取中取出
        Fragment fragment = mFragments.get(fragmentName);
        if (fragment == null) {
            switch (fragmentName) {

                case F1:
                    fragment = new Fragment1();
                    break;

                case F2:
                    fragment = new Fragment2();

                    break;

                case F3:
                    fragment = new Fragment3();

                    break;
            }
            // 把frament加入到快取中
            mFragments.put(fragmentName,fragment);
        }

        return fragment;
    }
}

相關推薦

Fragment記憶體回收重疊恢復資料問題

package com.mine.fragmentdemo; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.F

oracle flashback——oracle資料閃回實戰,恢復資料到指定的時間戳——timestamp

Microsoft Windows [版本 6.1.7601] 版權所有 (c) 2009 Microsoft Corporation。保留所有權利。 C:\Users\ckz>sqlplus

MySQL誤操作如何快速恢復資料

基本上每個跟資料庫打交道的程式設計師(當然也可能是你同事)都會碰一個問題,MySQL誤操作後如何快速回滾?比如,delete一張表,忘加限制條件,整張表都沒了。假如這還是線上環境核心業務資料,那這事就鬧大了。誤操作後,能快速回滾資料是非常重要的。 傳統解法 用全量備份

Mysql binlog備份資料恢復資料,學會這個,我在也不怕刪庫跑路啦~

導讀   我一直都主張,技多不壓身(沒有學不會的技術,只有不學習的人),多學一項技能,未來就少求人一次。網上經常聽到xxx刪庫跑路,萬一真的遇到了,相信通過今天的學習,也能將資料再恢復回來~~~   當然啦,備份資料/還原資料也是挺重要的,可以看我另一篇:點我直達   如果感覺這樣還不安全,可以考慮授予使用者

關於應用記憶體資料回收,重新啟動

情景: 小米手機在執行中更改許可權後,再次進入應用後,位於前臺的activity還是之前開啟的那個,但是會重新從onCreate開始載入,有時會出現不可預料之錯。 於是,找原因,發現application也重新進入onCreate了。 最後,在application中o

【JVM之記憶體與垃圾回收篇】執行時資料區概述執行緒

# 執行時資料區概述及執行緒 ## 前言 本節主要講的是執行時資料區,也就是下圖這部分,它是在類載入完成後的階段 ![](https://img2020.cnblogs.com/blog/1542615/202007/1542615-20200713210432252-2095338296.png)

小甲魚零基礎入門python第005講課測試題答案:閒聊之python的資料型別

0.在 Python 中, int 表示整型, 那你還記得 bool 、 float 和 str 分別表示什麼嗎? bool :布林型,ture代表1,false代表0;float:浮點型;str:字串 1. 你知道為什麼布林型別 (bool) 的 True 和 False 分別用 1 和 0

Update誤操作如何恢復資料

問題 今天在公司操作使用者表,要求更新某個使用者的密碼欄位,結果在寫更新語句的時候忘記加條件了,導致所有使用者資料都被更新了,瞬間慌神了,表中可有幾十條資料,而且密碼都是MD5加密的,於是趕緊查資料,使用了資料恢復方法,目前資料已成功恢復,所以在這裡總結一下,希望以後在遇到同樣問題的時候能夠快速的解

用python批量獲取某路徑資料資料夾下的指定型別檔案,並按原資料夾結構批量儲存處理的檔案

因為是把自己成功執行的整個程式碼按幾部分截取出來的,所以每一小節程式碼不一定能單獨執行,特此說明。 1.獲取某路徑資料夾及子資料夾下的指定pcm型別檔案的全部路徑 import os def eachfile(filepath):     pathdi

redis 系列15 資料物件的(型別檢查,記憶體回收,物件共享)和資料庫切換

redis 系列15 資料物件的(型別檢查,記憶體回收,物件共享)和資料庫切換 一.  概述   對於前面的五章中,已清楚了資料物件的型別以及命令實現,其實還有一種資料物件為HyperLogLog,以後需要用到再瞭解。下面再瞭解型別檢查,記憶體回收,物件共享,物件的空轉時長。

胡八一Java(五):java記憶體回收

當一個物件在堆記憶體中執行時,有以下三種狀態: 可達狀態:當一個物件有一個以上的引用變數引用它,程式可以通過引用變數來呼叫物件的屬性和方法。在有向圖中,這就屬於可達。 可恢復狀態:如果一個物件沒有任何變數再引用它,那麼它將先進入可恢復狀態。系統的垃圾回收機制準備回收該

activity被回收,點選Tab無法切換fragment

1、原因:當activity在後臺並且記憶體不足時,系統會把activity給回收掉,但也會儲存部分(不是全部)資訊用於下次頁面恢復。這樣會導致下次進入頁面後佈局或資料錯亂,並且點選底部Tab無法切換fragment。 2、解決方法: (1)方法一:註釋掉sup

redis 系列15 資料物件的(型別檢查,記憶體回收,物件共享)和資料庫切換

一.  概述   對於前面的五章中,已清楚了資料物件的型別以及命令實現,其實還有一種資料物件為HyperLogLog,以後需要用到再瞭解。下面再瞭解型別檢查,記憶體回收,物件共享,物件的空轉時長。   1.1   型別檢查與命令多型     redis中用於操作鍵的命令基本上可以分為兩種型別,一種是可以對任何

安卓APP實戰(二):Activity管理,記憶體回收LeakCanary監測

每一個Activity元件都是一個單獨的介面,承載著與使用者互動的任務。也是應用最基本的功能之一,在不同介面之間切換,並實現不同的功能。 每一個程式必須要有一個Activity作為入口(Manifest檔案中將其<category>標籤設定為LAUNCHER),然後通過介面控制到

5. C語言基本資料型別構造資料型別,浮點型儲存規則記憶體模型

  其實學習C語言的時候有一件很頭疼的事就是各種各樣的資料型別,不同的場合不同的用途不同的資料要使用不同的資料型別,那又為什麼要分出這麼多種型別呢,因為型別決定了開闢空間的大小,開闢空間的大小又決定了儲存的範圍。今天,就資料型別這個問題我們來掰扯掰扯。   C

強引用、軟引用、弱引用、虛引用 例項 gc回收的自救

package com.sgcc.test; import java.lang.ref.PhantomReference; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lan

windows下mysql開啟binlog日誌利用binlog日誌恢復資料筆記

1、開啟binlog日誌。 找到mysql安裝目錄,開啟配置檔案my.ini 在[mysqld]下新增: bin-log=mysql-bin 儲存後重啟mysql。此時在data目錄會生成mysql-bin.000001和mysql-bin.index。 注意:My

圖片轉成base64格式上傳OSS-Java建立資料

@Test public void testAddUploadFileInfo() throws Exception{ String str = "/9j/4AAQSkZJRgABAQEAeA

FFMPEG記憶體操作(二)從記憶體中讀取數資料格式的轉換

   相關部落格列表:     在雷神的《最簡單的基於FFmpeg的記憶體讀寫例子(記憶體播放器)》中,它是設計回撥函式從輸入檔案中讀取資料。與FFMPEG 官方給出的avio_reading.c不同的是,雷神給的例子是當需要資料的時候,回撥函式才去從輸入檔案讀取資料,而av

後臺的activity被系統自動回收的話,怎麼在回到介面的時候恢復資料

 Activity的狀態通常情況下系統會自動儲存的,只有當我們需要儲存額外的資料時才需要使用到這樣的功能。 通常情況:  呼叫onPause()和onStop()方法後的activity例項仍然存在