Skip to content

Commit

Permalink
Android:解决切换横竖屏等导致崩溃或者重复叠加显示 Fragment
Browse files Browse the repository at this point in the history
  • Loading branch information
TommyLemon committed May 5, 2023
1 parent 4eac93e commit d9240ef
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 109 deletions.
158 changes: 110 additions & 48 deletions ZBLibrary/src/main/java/zuo/biao/library/base/BaseBottomTabActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

package zuo.biao.library.base;

import zuo.biao.library.R;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import android.view.View;
Expand All @@ -30,15 +31,15 @@ public abstract class BaseBottomTabActivity extends BaseActivity {



//UI显示区(操作UI,但不存在数据获取或处理代码,也不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// UI显示区(操作UI,但不存在数据获取或处理代码,也不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<


protected static int[] tabClickIds;

protected View[] vTabClickViews;
protected View[][] vTabSelectViews;
@Override
public void initView() {//必须调用
public void initView() {// 必须调用

tabClickIds = getTabClickIds();

Expand Down Expand Up @@ -67,7 +68,7 @@ public void initView() {//必须调用
protected abstract void selectTab(int position);

/**设置选中状态
* @param position
* @param position
*/
protected void setTabSelection(int position) {
if (vTabSelectViews == null) {
Expand All @@ -87,57 +88,122 @@ protected void setTabSelection(int position) {

/**
* == true >> 每次点击相应tab都加载,调用getFragment方法重新对点击的tab对应的fragment赋值。
* 如果不希望重载,可以重写selectFragment
* 如果不希望重载,可以setOnTabSelectedListener,然后在onTabSelected内重写点击tab事件
*/
protected boolean needReload = false;
/**
* 当前显示的tab所在位置,对应fragment所在位置
*/
protected int currentPosition = 0;

/**选择并显示fragment
* @param position
*/
public void selectFragment(int position) {
//tab,资源消耗很小<<<<<<
setTabSelection(position);
selectTab(position);
//tab,资源消耗很小>>>>>>
if (fragments == null || fragments.length != getCount()) {
if (fragments != null) {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
for (int i = 0; i < fragments.length; i++) {
fragmentTransaction.remove(fragments[i]);
}
fragmentTransaction.commit();
}

fragments = new Fragment[getCount()];
}

Fragment fragment = fragments[position];
String tag = TAG + "-fragment-" + position;
if (fragment == null) {
fragment = fragmentManager.findFragmentByTag(tag);
}

if (currentPosition == position) {
if (needReload) {
if (fragments[position] != null && fragments[position].isAdded()) {
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.remove(fragments[position]).commit();
fragments[position] = null;
}
} else {
if (fragments[position] != null && fragments[position].isVisible()) {
Log.w(TAG, "selectFragment currentPosition == position" +
" >> fragments[position] != null && fragments[position].isVisible()" +
" >> return; ");
return;
}
if (needReload == false && fragment != null && fragment.isVisible()) {
android.util.Log.w(TAG, "selectFragment currentPosition == position" +
" >> fragment != null && fragment.isVisible()" +
" >> return; ");
return;
}
}

FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if (needReload) {
fragmentTransaction.remove(fragment);
fragment = null;
}

if (fragment == null) {
fragment = fragments[position] = getFragment(position);
}

if (fragments[position] == null) {
fragments[position] = getFragment(position);
// 用全局的fragmentTransaction因为already committed 崩溃
for (Fragment f : fragmentManager.getFragments()) {
if (f != null) {
fragmentTransaction.hide(f);
}
}

//全局的fragmentTransaction因为already committed 崩溃
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.hide(fragments[currentPosition]);
if (fragments[position].isAdded() == false) {
ft.add(getFragmentContainerResId(), fragments[position]);
if (fragment.isAdded() == false) {
fragmentTransaction.add(R.id.flBaseTabFragmentContainer, fragment, tag);
}
FragmentTransaction ft = fragmentTransaction.show(fragment);
try { // cannot perform this action after savedInstance
ft.commit();
} catch (Throwable e) {
e.printStackTrace();
}
ft.show(fragments[position]).commit();

this.currentPosition = position;
}


//UI显示区(操作UI,但不存在数据获取或处理代码,也不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
protected void reload(int position) {
remove(position);
if (position == currentPosition) {
selectFragment(position);
}
}
protected void reloadAll() {
runUiThread(new Runnable() {

@Override
public void run() {
removeAll(true);
selectFragment(currentPosition);
}
});
}
protected void remove(int position) {
remove(position, false);
}
protected void remove(int position, boolean destroy) {
if (fragments != null && position >= 0 && position < fragments.length && fragments[position] != null) {
try {
fragmentManager.beginTransaction().remove(fragments[position]).commit();
} catch (Exception e) {
Log.e(TAG, "remove try { fragmentManager.beginTransaction().remove(fragments[position]).commit();" +
" } catch (Exception e) {\n" + e.getMessage());
destroy = true;
}
if (destroy) {
fragments[position].onDestroy();
fragments[position] = null;
}
}
}
protected void removeAll() {
removeAll(false);
}
protected void removeAll(boolean destroy) {
if (fragments != null) {
for (int i = 0; i < fragments.length; i++) {
remove(i, destroy);
}
}
}

// UI显示区(操作UI,但不存在数据获取或处理代码,也不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>



Expand All @@ -148,19 +214,18 @@ public void selectFragment(int position) {



//Data数据区(存在数据获取或处理代码,但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// Data数据区(存在数据获取或处理代码,但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<


protected Fragment[] fragments;
@Override
public void initData() {//必须调用
public void initData() {// 必须调用

//fragmentActivity子界面初始化<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// fragmentActivity子界面初始化<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

fragments = new Fragment[getCount()];
selectFragment(currentPosition);

//fragmentActivity子界面初始化>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// fragmentActivity子界面初始化>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

}

Expand Down Expand Up @@ -194,7 +259,7 @@ public int getCount() {
return tabClickIds == null ? 0 :tabClickIds.length;
}

//Data数据区(存在数据获取或处理代码,但不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Data数据区(存在数据获取或处理代码,但不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>



Expand All @@ -205,10 +270,10 @@ public int getCount() {



//Event事件区(只要存在事件监听代码就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// Event事件区(只要存在事件监听代码就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

@Override
public void initEvent() {//必须调用
public void initEvent() {// 必须调用

for (int i = 0; i < vTabClickViews.length; i++) {
final int which = i;
Expand All @@ -222,26 +287,23 @@ public void onClick(View v) {
}
}

//生命周期、onActivityResult<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<



//生命周期、onActivityResult>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


//Event事件区(只要存在事件监听代码就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 系统自带监听方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<


// 类相关监听<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<


// 类相关监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

// 系统自带监听方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


// Event事件区(只要存在事件监听代码就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//内部类,尽量少用<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<


// 内部类,尽量少用<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

//内部类,尽量少用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// 内部类,尽量少用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

}
48 changes: 29 additions & 19 deletions ZBLibrary/src/main/java/zuo/biao/library/base/BaseFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
public abstract class BaseFragment extends Fragment implements FragmentPresenter {
private static final String TAG = "BaseFragment";

public static final String ARGUMENT_POSITION = "ARGUMENT_POSITION";

/**
* 添加该Fragment的Activity
* @warn 不能在子类中创建
Expand Down Expand Up @@ -79,6 +81,12 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
this.inflater = inflater;
this.container = container;

if (view != null) {
if (container == null || container.indexOfChild(view) < 0) {
container = (ViewGroup) view.getParent();
}
container.removeView(view);
}
return view;
}

Expand Down Expand Up @@ -109,6 +117,23 @@ public void setContentView(View v, ViewGroup.LayoutParams params) {
}


/**
* 该Fragment在Activity添加的所有Fragment中的位置,通过ARGUMENT_POSITION设置
* @must 只使用getPosition方法来获取position,保证position正确
*/
private int position = -1;
/**获取该Fragment在Activity添加的所有Fragment中的位置
*/
public int getPosition() {
if (position < 0) {
argument = getArguments();
if (argument != null) {
position = argument.getInt(ARGUMENT_POSITION, position);
}
}
return position;
}

/**
* 可用于 打开activity与fragment,fragment与fragment之间的通讯(传值)等
*/
Expand All @@ -118,9 +143,11 @@ public void setContentView(View v, ViewGroup.LayoutParams params) {
*/
protected Intent intent = null;


/**通过id查找并获取控件,使用时不需要强转
* @warn 调用前必须调用setContentView
* @param id
* @return
* @return
*/
@SuppressWarnings("unchecked")
public <V extends View> V findView(int id) {
Expand All @@ -136,23 +163,6 @@ public <V extends View> V findView(int id, OnClickListener l) {
v.setOnClickListener(l);
return v;
}
/**通过id查找并获取控件,使用时不需要强转
* @warn 调用前必须调用setContentView
* @param id
* @return
*/
public <V extends View> V findViewById(int id) {
return findView(id);
}
/**通过id查找并获取控件,并setOnClickListener
* @param id
* @param l
* @return
*/
public <V extends View> V findViewById(int id, OnClickListener l) {
return findView(id, l);
}


public Intent getIntent() {
return context.getIntent();
Expand Down Expand Up @@ -180,7 +190,7 @@ public final Handler runThread(String name, Runnable runnable) {
Log.w(TAG, "runThread isAlive() == false >> return null;");
return null;
}
return context.runThread(name + hashCode(), runnable);//name, runnable);同一Activity出现多个同名Fragment可能会出错
return context.runThread(name + getPosition(), runnable);//name, runnable);同一Activity出现多个同名Fragment可能会出错
}

//运行线程>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Expand Down
Loading

0 comments on commit d9240ef

Please sign in to comment.