在新項目的開發過程中,無意間點了幾下首頁的底部導航 發現fragment 竟然空白不展示了,what!!
這個新項目我首頁導航用的是 ViewPager+Fragment+BottomNavigationView
ViewPager進行了自定義,保證它不能滑動和間隔頁面(比如 目前在1 點擊到4的時候)的時候不會有滑動的動畫
代碼貼出來
import android.content.Context;
import android.content.res.TypedArray;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import com.cmcm.teacherconsumers.R;
/**
* @author wavewave
* @CreateDate: 2019/3/20 7:04 PM
* @Description:
* @Version: 1.0
*/
public class MyViewPager extends ViewPager {
private boolean isCanScroll = false;
public MyViewPager(@NonNull Context context) {
super(context);
}
public MyViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LazyViewPager);
setInitLazyItemOffset(a.getFloat(R.styleable.LazyViewPager_init_lazy_item_offset, DEFAULT_OFFSET));
a.recycle();
}
/**
* 設置其是否能滑動換頁
*
* @param isCanScroll false 不能換頁, true 可以滑動換頁
*/
public void setScanScroll(boolean isCanScroll) {
this.isCanScroll = isCanScroll;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return isCanScroll && super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
return isCanScroll && super.onTouchEvent(ev);
}
@Override
public void setCurrentItem(int item, boolean smoothScroll) {
super.setCurrentItem(item, false);
}
@Override
public void setCurrentItem(int item) {
super.setCurrentItem(item, false);
}
}
然後在做到接口的時候發現一個問題就是fragment 切換後會一直重新創建,想起ViewPager有個
setOffscreenPageLimit(); 方法 可以設置緩存數量
這個設置後 它會提前加載的。。。根據情況使用
對於我來說,這種一打開就請求所有接口的,,,我怕老大打死我。
於是想起了好久之前的開源項目 懶加載 LazyFragmentPagerAdapter
導入進去使用。不錯不錯確實是懶加載 生命週期都不一樣。
但是今天點出bug了,操作流程是
我的標籤一共是四個,打開頁面
點擊第四個標籤,然後再點擊第二個標籤,空白了。。。。
生命週期都沒有走,debug找找 好像是懶加載機制裏面的問題,
因爲我比較懶,所以就換最古老的寫法了。
Fragment add(), show(),hide()
因爲之前也寫過好多次,這次變抽出方法來
加入的方法
private void showFragment(Fragment fragment, String tag) {
if (TextUtils.isEmpty(tag)) return;
hideFragment();
if (fragment == null) {
if (tag.equals(fragmentTag[1])) {
chatFragment = ChatFragment.newInstance("", "");
getSupportFragmentManager().beginTransaction().add(R.id.main_ll, chatFragment, fragmentTag[1]).commit();
} else if (tag.equals(fragmentTag[2])) {
studentFragment = StudentFragment.newInstance("", "");
getSupportFragmentManager().beginTransaction().add(R.id.main_ll, studentFragment, fragmentTag[2]).commit();
} else if (tag.equals(fragmentTag[3])) {
myFragment = MyFragment.newInstance("", "");
getSupportFragmentManager().beginTransaction().add(R.id.main_ll, myFragment, fragmentTag[3]).commit();
} else {
homeFragment = HomeFragment.newInstance("", "");
getSupportFragmentManager().beginTransaction().add(R.id.main_ll, homeFragment, fragmentTag[0]).commit();
}
} else {
getSupportFragmentManager().beginTransaction().show(fragment).commit();
}
}
隱藏的方法
private void hideFragment() {
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
if (homeFragment != null) fragmentTransaction.hide(homeFragment);
if (chatFragment != null) fragmentTransaction.hide(chatFragment);
if (studentFragment != null) fragmentTransaction.hide(studentFragment);
if (myFragment != null) fragmentTransaction.hide(myFragment);
fragmentTransaction.commit();
}
寫這個要注意一下,如果當前activity 被異常銷燬重建的時候,會有重疊問題
打開手機的開發者選項,往下拉 找到 應用下面的 不保留活的 開關打開就可以測試拉(我的手機是華爲,其他也會有這個選項)
於是動手解決一下,思路很簡單
就是在它重建的時候,在FragmentManager通過Tag重新把 fragment對象找回來就好了
我們還要保證銷燬前的樣子 所以還要手動去保存一個 索引
重寫 onSaveInstanceState(Bundle outState)
//記錄當前選中的 fragment 索引用於異常銷燬 恢復
private int selectPosition = -1;
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(SELECT_FRAGMENT, selectPosition);
}
然後在 oncreate的時候恢復 我封裝的Base 所以自己寫的方法 叫做 afterCreate
@Override
protected void afterCreate(Bundle savedInstanceState) {
if (savedInstanceState != null) {//處理activity 異常銷燬恢復 fragment
selectPosition = savedInstanceState.getInt(SELECT_FRAGMENT, -1);
saveFragment(selectPosition);
} else {
showFragment(homeFragment, fragmentTag[0]);
}
mainBnv.setOnNavigationItemSelectedListener(this);
}
/**
* 用於恢復 activity 異常銷燬的fragment
*
* @param anInt
*/
private void saveFragment(int anInt) {
homeFragment = (HomeFragment) getSupportFragmentManager().findFragmentByTag(fragmentTag[0]);
chatFragment = (ChatFragment) getSupportFragmentManager().findFragmentByTag(fragmentTag[1]);
studentFragment = (StudentFragment) getSupportFragmentManager().findFragmentByTag(fragmentTag[2]);
myFragment = (MyFragment) getSupportFragmentManager().findFragmentByTag(fragmentTag[3]);
switch (anInt) {
case 0:
default:
showFragment(homeFragment, fragmentTag[0]);
break;
case 1:
showFragment(chatFragment, fragmentTag[1]);
break;
case 2:
showFragment(studentFragment, fragmentTag[2]);
break;
case 3:
showFragment(myFragment, fragmentTag[3]);
break;
}
}
當然可能 有些不好上手 於是我寫個demo放到github 上