Android Fragment切換解決方案之FragmentTransaction
阿新 • • 發佈:2019-02-06
fragment切換?不就是Viewpager+fragment嗎?是的這是很大多數App採用的切換的組合方式。但是Viewpager+fragment切換的的生命週期十分混亂,這就是會引發很多的坑!如果在一些不需要切換的動畫的情況下,採用FragmentTransaction動態切換是一個不錯的選擇
先來看看有哪些切換的方案吧。又有哪些問題:
(一)預先寫在佈局裡面
佈局檔案
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/activity_bg"
android:orientation="vertical" >
<fragment
android:id="@+id/fragement_main"
android:name="net.loonggg.fragment.FragmentMain"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="10" />
<fragment
android:id="@+id/fragement_search"
android:name="net.loonggg.fragment.FragmentSearch"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="10" />
<fragment
android:id="@+id/fragement_setting"
android:name="net.loonggg.fragment.FragmentSetting"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="10" />
java檔案:
mFragments[0] = fragmentManager.findFragmentById(R.id.fragement_main);
mFragments[1] = fragmentManager.findFragmentById(R.id.fragement_search);
mFragments[2] = fragmentManager
.findFragmentById(R.id.fragement_setting);
fragmentTransaction = fragmentManager.beginTransaction()
.hide(mFragments[0]).hide(mFragments[1]).hide(mFragments[2]);
fragmentTransaction.show(mFragments[0]).commit();
這種方案的問題就是在如果我的某個Fragment更換了,改動的涉及到兩個檔案,而且也不能進行動態載入,侷限性比較大。
(二)Replace替換
private void replaceFragment(Fragment newFragment) {
FragmentTransaction trasection = getFragmentManager().beginTransaction();
try {
//FragmentTransaction trasection =
getFragmentManager().beginTransaction();
trasection.replace(R.id.linearLayout2, newFragment);
trasection.addToBackStack(null);
trasection.commit();
} catch (Exception e) {
// TODO: handle exception
}
}
這樣總沒問題了吧?這種方案的問題在於每次呼叫replace方法時Fragment的生命週期會重走。這在現實開發中是不允許的。
解決方案:
Activity
以下采用的方式是預先將Fragment加入集合中,切換時從集合取出Fragment新增到FragmentTransaction事物中,每次加入的時候判斷是否已經新增到FragmentTransaction中,存在則呼叫show,並將上一個fragment隱藏。
public class MainActivity extends FragmentActivity implements View.OnClickListener {
private LinearLayout tab1, tab2, tab3;
private int currentIndex = 0;
private ArrayList<Fragment> fragmentArrayList;
private Fragment mCurrentFrgment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initFragment();
}
private void initView() {
tab1 = (LinearLayout) findViewById(R.id.tab1);
tab1.setOnClickListener(this);
tab1.setTag(0);
tab2 = (LinearLayout) findViewById(R.id.tab2);
tab2.setOnClickListener(this);
tab2.setTag(1);
tab3 = (LinearLayout) findViewById(R.id.tab3);
tab3.setOnClickListener(this);
tab3.setTag(2);
}
private void initFragment() {
fragmentArrayList = new ArrayList<Fragment>(3);
fragmentArrayList.add(new Tab1Fragment());
fragmentArrayList.add(new Tab2Fragment());
fragmentArrayList.add(new Tab3Fragment());
tab1.setSelected(true);
changeTab(0);
}
@Override
public void onClick(View v) {
changeTab((Integer) v.getTag());
}
private void changeTab(int index) {
currentIndex = index;
tab1.setSelected(index == 0);
tab2.setSelected(index == 1);
tab3.setSelected(index == 2);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
//判斷當前的Fragment是否為空,不為空則隱藏
if (null != mCurrentFrgment) {
ft.hide(mCurrentFrgment);
}
//先根據Tag從FragmentTransaction事物獲取之前新增的Fragment
Fragment fragment = getSupportFragmentManager().findFragmentByTag(fragmentArrayList.get(currentIndex).getClass().getName());
if (null == fragment) {
//如fragment為空,則之前未新增此Fragment。便從集合中取出
fragment = fragmentArrayList.get(index);
}
mCurrentFrgment = fragment;
//判斷此Fragment是否已經新增到FragmentTransaction事物中
if (!fragment.isAdded()) {
ft.add(R.id.fragment, fragment, fragment.getClass().getName());
} else {
ft.show(fragment);
}
ft.commit();
}
}
fragment
public class Tab1Fragment extends Fragment {
public Tab1Fragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_tab1, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
final ProgressBar progressBar = (ProgressBar) view.findViewById(R.id.progressbar);
final TextView tv = (TextView) view.findViewById(R.id.tv);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
progressBar.setVisibility(View.GONE);
tv.setVisibility(View.VISIBLE);
}
}, 2000);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
@Override
public void onDetach() {
super.onDetach();
}
}
這樣做的好處是,每個Fragment切換隻進行一次初始化。