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例項仍然存在