Max*_*m G 8 android asynchronous android-handler android-bundle
我正在使用遗留代码,我在此函数中发现了一个不一致的行为:
@Override
public void openFragment(final Class<? extends BaseFragment> fragmentClass,
final boolean addToBackStack,
final Bundle args)
{
long delay = 0;
if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
delay = getResources().getInteger(android.R.integer.config_shortAnimTime) * 2;
}
// FIXME: quick fix, but not all cases
final Bundle args666 = args != null ? (Bundle) args.clone() : null;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
doOpenFragment(fragmentClass, addToBackStack, args666);
}
}, delay);
closeDrawer();
}
protected void doOpenFragment(final Class<? extends BaseFragment> fragmentClass,
final boolean addToBackStack,
final Bundle args)
{
try {
if (getSupportFragmentManager().getBackStackEntryCount() >= 1) {
showNavigationIcon();
}
hideKeyboard();
BaseFragment fragment = createFragment(fragmentClass, args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
fragment.initTransactionAnimation(transaction);
String tag = getTag(fragment);
transaction.add(R.id.container, fragment, tag);
if (addToBackStack) {
transaction.addToBackStack(tag);
}
transaction.commitAllowingStateLoss();
hideLastFragment(0);
} catch (Exception e) {
Sentry.captureException(e, "Error opening fragment");
}
}
Run Code Online (Sandbox Code Playgroud)
openFragment得到非空的Bundle args,但doOpenFragment会得到空的Bundle.片段通过调用来实现commitAllowingStateLoss()
快速修复可以使用Bundle.clone():
final Bundle args666 = (Bundle) args.clone();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
doOpenFragment(fragmentClass, addToBackStack, args666);
}
}, delay);
Run Code Online (Sandbox Code Playgroud)
它不会处理所有情况,deepCopy仅在api26中可用.
[ 更新 ]
我玩@ Pavel的解决方案,事情变得更加怪异
final Bundle args666 = args != null ? cloneThroughSerialization(args) : args;
final Bundle args777 = args != null ? (Bundle) args.clone() : args;
Run Code Online (Sandbox Code Playgroud)
[UPDATE2]
实际上,问题不在于postDelayed通话.我们来看看调用堆栈:
在goRightToTheCollectionScreenBundle中创建并打包(没有任何可疑,之后没有变异).
我猜,内部两个调用的问题来源openFragmentsChain:
public void openRootFragmentsChain(Class<? extends BaseFragment> fragmentClass,
List<Class<? extends BaseFragment>> fragmentClasses,
boolean addToBackStack,
Bundle args)
{
openFragmentsChain(fragmentClasses, addToBackStack, args);
openFragment(fragmentClass, true, args);
}
public void openFragmentsChain(List<Class<? extends BaseFragment>> fragmentClasses,
boolean addToBackStack,
Bundle args)
{
try {
for (int i = 0; i < fragmentClasses.size(); i++) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
BaseFragment fragment = createFragment(fragmentClasses.get(i), args);
String tag = getTag(fragment);
transaction.add(R.id.container, fragment, tag);
if (addToBackStack) {
transaction.addToBackStack(tag);
}
if (i != fragmentClasses.size() - 1) {
transaction.hide(fragment);
}
transaction.commitAllowingStateLoss();
}
if (fragmentClasses.size() >= 1) {
updateDrawer();
}
} catch (Exception e) {
Sentry.captureException(e, "Error opening fragment chain");
}
}
protected void doOpenFragment(final Class<? extends BaseFragment> fragmentClass,
final boolean addToBackStack,
final Bundle args)
{
try {
if (getSupportFragmentManager().getBackStackEntryCount() >= 1) {
showNavigationIcon();
}
hideKeyboard();
BaseFragment fragment = createFragment(fragmentClass, args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
fragment.initTransactionAnimation(transaction);
String tag = getTag(fragment);
transaction.add(R.id.container, fragment, tag);
if (addToBackStack) {
transaction.addToBackStack(tag);
}
transaction.commitAllowingStateLoss();
hideLastFragment(0);
} catch (Exception e) {
Sentry.captureException(e, "Error opening fragment");
}
}
protected BaseFragment createFragment(Class<? extends BaseFragment> fragmentClass, Bundle args) throws Exception {
BaseFragment fragment = fragmentClass.newInstance();
fragment.setHasOptionsMenu(true);
fragment.setArguments(args);
fragment.setNavigationHandler(BaseFragmentNavigatorActivity.this);
fragment.setToolbar(mToolbar);
fragment.setMenuLoadService(mMenuLoaderService);
return fragment;
}
Run Code Online (Sandbox Code Playgroud)
小智 3
您可以通过序列化进行深度克隆。
public static Bundle cloneThroughSerialization(@NonNull Bundle bundle) {
Parcel parcel = Parcel.obtain();
bundle.writeToParcel(parcel, 0);
Bundle clonedBundle = new Bundle();
clonedBundle.readFromParcel(parcel);
parcel.recycle();
return clonedBundle;
}
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
200 次 |
| 最近记录: |