Add support for AndroidX fragments (#957)
Summary: Fix https://github.com/facebook/flipper/issues/931 This is not how I would *like* to fix this, but it should do the job. When the switch over to AndroidX was made, the overall abstraction started to leak and we really need to remodel this in its entirety. There's also the question of whether we want to support both support fragments and AndroidX fragments or not. Right now it's kinda-sorta supported but only under some circumstances, which is not great. I also added some more defensive try/catches as there's some unsafe casting involved and future changes may break this causing the entire layout to disappear. Change Log: Fix support for AndroidX fragments in Layout Inspector. Pull Request resolved: https://github.com/facebook/flipper/pull/957 Test Plan: Changed the sample app to include some AndroidX fragments and they now show up (again) in the view hierarchy:  Tested internally that FB4A fragments show up again, too: {F233098198} Reviewed By: mweststrate Differential Revision: D20792503 Pulled By: passy fbshipit-source-id: 7030b897ab547d1e8803b7f0d7aaa34263cfaed2
This commit is contained in:
committed by
Facebook GitHub Bot
parent
492b1076d2
commit
4be1b4d491
@@ -8,6 +8,7 @@
|
||||
package com.facebook.flipper.plugins.inspector.descriptors;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.util.Log;
|
||||
import android.view.Window;
|
||||
import com.facebook.flipper.core.FlipperDynamic;
|
||||
import com.facebook.flipper.core.FlipperObject;
|
||||
@@ -25,6 +26,8 @@ import javax.annotation.Nullable;
|
||||
|
||||
public class ActivityDescriptor extends NodeDescriptor<Activity> {
|
||||
|
||||
private static final String TAG = "ActivityDescriptor";
|
||||
|
||||
@Override
|
||||
public void init(Activity node) {}
|
||||
|
||||
@@ -112,9 +115,14 @@ public class ActivityDescriptor extends NodeDescriptor<Activity> {
|
||||
}
|
||||
|
||||
FragmentManagerAccessor fragmentManagerAccessor = compat.forFragmentManager();
|
||||
List<Object> addedFragments = fragmentManagerAccessor.getAddedFragments(fragmentManager);
|
||||
List<Object> addedFragments = null;
|
||||
try {
|
||||
addedFragments = fragmentManagerAccessor.getAddedFragments(fragmentManager);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failed to obtain list of fragments.", e);
|
||||
}
|
||||
if (addedFragments == null) {
|
||||
return Collections.EMPTY_LIST;
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final List<Object> dialogFragments = new ArrayList<>();
|
||||
|
||||
@@ -9,7 +9,9 @@ package com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Build;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
@@ -37,7 +39,7 @@ public abstract class FragmentCompat<
|
||||
|
||||
static {
|
||||
sHasSupportFragment =
|
||||
ReflectionUtil.tryGetClassForName("android.support.v4.app.Fragment") != null;
|
||||
ReflectionUtil.tryGetClassForName("androidx.fragment.app.Fragment") != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -82,20 +84,22 @@ public abstract class FragmentCompat<
|
||||
@Nullable
|
||||
@Override
|
||||
public List<FRAGMENT> getAddedFragments(FRAGMENT_MANAGER fragmentManager) {
|
||||
// This field is actually sitting on FragmentManagerImpl, which derives from FragmentManager.
|
||||
if (mFieldMAdded == null) {
|
||||
Field fieldMAdded =
|
||||
ReflectionUtil.tryGetDeclaredField(fragmentManager.getClass(), "mAdded");
|
||||
if (fragmentManager instanceof android.app.FragmentManager) {
|
||||
// This field is actually sitting on FragmentManagerImpl, which derives from
|
||||
// FragmentManager.
|
||||
if (mFieldMAdded == null) {
|
||||
Field fieldMAdded =
|
||||
ReflectionUtil.tryGetDeclaredField(fragmentManager.getClass(), "mAdded");
|
||||
|
||||
if (fieldMAdded != null) {
|
||||
fieldMAdded.setAccessible(true);
|
||||
mFieldMAdded = fieldMAdded;
|
||||
if (fieldMAdded != null) {
|
||||
fieldMAdded.setAccessible(true);
|
||||
mFieldMAdded = fieldMAdded;
|
||||
}
|
||||
}
|
||||
} else if (fragmentManager instanceof androidx.fragment.app.FragmentManager) {
|
||||
return (List<FRAGMENT>) ((FragmentManager) fragmentManager).getFragments();
|
||||
}
|
||||
|
||||
return (mFieldMAdded != null)
|
||||
? (List<FRAGMENT>) ReflectionUtil.getFieldValue(mFieldMAdded, fragmentManager)
|
||||
: null;
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,11 +8,15 @@
|
||||
package com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public final class FragmentCompatUtil {
|
||||
private static final String TAG = "FragmentCompatUtil";
|
||||
|
||||
private FragmentCompatUtil() {}
|
||||
|
||||
public static boolean isDialogFragment(Object fragment) {
|
||||
@@ -79,7 +83,13 @@ public final class FragmentCompatUtil {
|
||||
@Nullable
|
||||
private static Object findFragmentForViewInFragmentManager(
|
||||
FragmentCompat compat, Object fragmentManager, View view) {
|
||||
List<?> fragments = compat.forFragmentManager().getAddedFragments(fragmentManager);
|
||||
List<?> fragments;
|
||||
try {
|
||||
fragments = compat.forFragmentManager().getAddedFragments(fragmentManager);
|
||||
} catch (Exception e) {
|
||||
fragments = Collections.emptyList();
|
||||
Log.e(TAG, "Failed to obtain list of fragments.", e);
|
||||
}
|
||||
|
||||
if (fragments != null) {
|
||||
for (int i = 0, N = fragments.size(); i < N; ++i) {
|
||||
|
||||
Reference in New Issue
Block a user