GVKun编程网logo

SupportMapFragment不支持AndroidX Fragment(安卓不支持support)

16

针对SupportMapFragment不支持AndroidXFragment和安卓不支持support这两个问题,本篇文章进行了详细的解答,同时本文还将给你拓展android3.0中的getSupp

针对SupportMapFragment不支持AndroidX Fragment安卓不支持support这两个问题,本篇文章进行了详细的解答,同时本文还将给你拓展android 3.0中的getSupportFragmentManager()与getFragmentManager()、Android Fragment 和 FragmentManager 的代码分析、Android FragmentManage FragmentTransaction 介绍、android – AppCompat v7:我应该使用Framework FragmentManager还是SupportFragmentManager?等相关知识,希望可以帮助到你。

本文目录一览:

SupportMapFragment不支持AndroidX Fragment(安卓不支持support)

SupportMapFragment不支持AndroidX Fragment(安卓不支持support)

import com.google.android.gms.maps.SupportMapFragment;
import androidx.fragment.Fragment;
...
private SupportMapFragment mMapFragment;
...
mMapFragment = (SupportMapFragment) form.getSupportFragmentManager().findFragmentByTag(MAP_FRAGMENT_TAG);

这里,IDE显示androidx.fragment.Fragment无法强制转换为SupportMapFragment(扩展android.support.v4.app.Fragment)的错误

我使用的是play-services-maps的15.0.1版和AndroidX库的1.0.0-beta01版.

在发布说明:https://developers.google.com/maps/documentation/android-sdk/releases中,我没有在AndroidX之后找到SupportMapFragment的任何更新

编辑:在有人问之前,form是一个Form类的实例,它扩展了AppCompatActivity(来自AndroidX)

解决方法:

Google已在公共问题跟踪器中报告此问题:

https://issuetracker.google.com/issues/110573930

我建议在公共问题跟踪器中主演功能请求,以添加您的投票并订阅来自Google的进一步通知.希望Google能够在下一版Android Maps SDK中实现它.

更新

Google在公共问题跟踪器中提供了以下答案

Hi all,

As noted the Google Maps API is currently based off the support libraries and not AndroidX. Future versions of Google Maps API will certainly support AndroidX, but in the meantime, the following workaround will resolve the issue for you:

  • Use Android Studio 3.2 (currently preview) or higher
  • Ensure your build.gradle contains ‘compileSdkVersion 28’ (default for new AS 3.2 projects)
  • Include the following in your gradle.properties file (default for new AS 3.2 projects)

    android.useandroidX=true

    android.enableJetifier=true

Finally, for existing code referencing the support libraries, you can use the “Refactor -> Refactor to AndroidX” tool in Android Studio 3.2+ to automatically convert your code to use the new AndroidX packages.

android 3.0中的getSupportFragmentManager()与getFragmentManager()

android 3.0中的getSupportFragmentManager()与getFragmentManager()

在 android.support.v4.app.FragmentManager的文档中:

“框架的FragmentManager的静态库支持版本.用于编写在Android 3.0之前的平台上运行的应用程序.在Android 3.0或更高版本上运行时,仍然使用此实现;它不会尝试切换到框架的实现.请参阅用于类概述的框架SDK文档.“

那么,我是否需要在运行时进行检查并使用适当的FragmentManager来运行应用程序的Android版本?即如果在android 3.0而不是getSupportFragmentManager()上调用getFragmentManager()

解决方法

只要您导入了支持库,在Android 3.0上使用getSupportFragmentManager()就没有错.如果你想对SDKs 11使用getFragmentManager(),那就去吧;请记住,如果使用版本检查,您可能会使用大量代码.

Android Fragment 和 FragmentManager 的代码分析

Android Fragment 和 FragmentManager 的代码分析

这两天在研究插件化编程,在使用 Fragment 碰到了一些问题,于是查看源码,顺便分析了一下 Fragment 和 FragmentManager 以及其他几个 API 的原代码,看看他们是怎么工作的。

我们知道 Fragment 有个 onCreateView() 方法,这个方法在 Fragment 创建 View 的时候被调用,并且返回一个 View 对象。那么 onCreateView 在什么时候被调用呢,咱们在 Fragment 这个类里找到了一个方法,performCreateView() 方法。

Fragment.java
public View onCreateView(LayoutInflater inflater,@Nullable ViewGroup container,@Nullable Bundle savedInstanceState) {
 return null;
}

performCreateView 这个方法在什么时候会被调用呢,在 Fragment 里找不到调用它的代码。咱们可以猜测一下,大概会在 FragmentManager 里。

View performCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
 if (mChildFragmentManager != null) {
  mChildFragmentManager.noteStateNotSaved();
 }
 return onCreateView(inflater,container,savedInstanceState);
}

在 FragmentManager 里,咱们找到了调用 Fragment.performCreateView 的代码,在 movetoState() 方法里,这个方法有点大,我只粘贴了部分代码。可以看到,它会在 Fragment 初始化或者创建的时候被调用。并且我们知道,创建的View 被赋值给 Fragment 的 mView 成员变量了。

FragmentManager.java
void movetoState(Fragment f,int newState,int transit,int transitionStyle,boolean keepActive) {
 switch (f.mState) {
 case Fragment.INITIALIZING:
  if (f.mFromLayout) {
   f.mView = f.performCreateView(f.getLayoutInflater(
   f.mSavedFragmentState),null,f.mSavedFragmentState);
 }
 break;
case Fragment.CREATED:
 if (!f.mFromLayout) {
  f.mView = f.performCreateView(f.getLayoutInflater(
   f.mSavedFragmentState),f.mSavedFragmentState);
 }
break;
} 
}

接下来,咱们要看什么时候会调用 movetoState() 这个方法。找了一下,发现很 N 多的地方调用了这个方法。这样给咱们逆推找代码造成了一定的难度。于是咱们换个思路,正推来分析。怎么正推了,看咱们怎么使用 Fragment 和 FragmentManager 来分析。

一般咱们都是 getFragmentManager() 或者 getSupportFragmentManager() 的方法来获取 FragmentManager.以 FragmentActivity 为例,一般情况下,咱们在这个类的子类里调用这两个方法之一。

咱们在 FragmentActivity 里找到了相应的代码。FragmentManager 是一个抽象类,FragmentManagerImpl 是 FragmentManager 的子类,在 FragmentManager 同一个 java 文件内,是一个内部类。它是 FragmentManager 的实现。

FragmentActivity.java
//FragmentManagerImpl is subclass of FragmentManager
final FragmentManagerImpl mFragments = new FragmentManagerImpl();
public FragmentManager getSupportFragmentManager() {
 return mFragments;
}

获取到 FragmentManager 后,咱们一般就会调用 beginTransaction() 方法,返回一个 FragmentTransaction 。咱们看代码去。

FragmentManager.java
public abstract FragmentTransaction beginTransaction();
FragmentManagerImpl extends FragmentManager
@Override
public FragmentTransaction beginTransaction() {
 return new BackStackRecord(this);
}
/**
* Static library support version of the framework's {@link android.app.FragmentTransaction}.
* Used to write apps that run on platforms prior to Android 3.0. When running
* on Android 3.0 or above,this implementation is still used; it does not try
* to switch to the framework's implementation. See the framework SDK
* documentation for a class overview.
*/
public abstract class FragmentTransaction

我们发现 FragmentManager 是一个抽象方法,实现在 FragmentManagerImpl。FragmentManagerImpl.beginTransaction() 返回的是一个BackStackRecord,而 FragmentTransaction 是一个抽象类。那么 BackStackRecord 是个什么鬼。

我们找到了 BackStackRecord 这个类。我们注意到,它继承于 FragmentTransaction,并且实现了 Runable 接口。它的方法有很多,咱们就分析一个咱们比较常用的,比如 add() 方法。

BackStackRecord.java
final class BackStackRecord extends FragmentTransaction implements FragmentManager.BackStackEntry,Runnable 
final FragmentManagerImpl mManager;
public BackStackRecord(FragmentManagerImpl manager) {
 mManager = manager;
}

add() 方法其实没干啥,咱们一路追下去看。

public FragmentTransaction add(Fragment fragment,String tag) {
 doAddOp(0,fragment,tag,OP_ADD);
 return this;
}
private void doAddOp(int containerViewId,Fragment fragment,String tag,int opcmd) {
 fragment.mFragmentManager = mManager;
 if (tag != null) {
  if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
   throw new IllegalStateException("Can't change tag of fragment "
     + fragment + ": was " + fragment.mTag
     + " Now " + tag);
  }
  fragment.mTag = tag;
 }
 if (containerViewId != 0) {
  if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
   throw new IllegalStateException("Can't change container ID of fragment "
     + fragment + ": was " + fragment.mFragmentId
     + " Now " + containerViewId);
  }
  fragment.mContainerId = fragment.mFragmentId = containerViewId;
 }
 Op op = new Op();
 op.cmd = opcmd;
 op.fragment = fragment;
 addOp(op);
}
void addOp(Op op) {
 if (mHead == null) {
  mHead = mTail = op;
 } else {
  op.prev = mTail;
  mTail.next = op;
  mTail = op;
 }
 op.enteranim = mEnteranim;
 op.exitAnim = mExitAnim;
 op.popEnteranim = mPopEnteranim;
 op.popExitAnim = mPopExitAnim;
 mNumOp++;
}

一直追到 addOp() 就断了,好像啥事也没干。不过它大概是在一个 add 操作添加到一个链表上了。那咱们怎么办呢?一般咱们add 完后会 commit 一下,咱们看看 commit 都干了啥。

public int commit() {
 return commitInternal(false);
}
int commitInternal(boolean allowStateLoss) {
 if (mCommitted) throw new IllegalStateException("commit already called");
 mCommitted = true;
 if (mAddToBackStack) {
  mIndex = mManager.allocBackStackIndex(this);
 } else {
  mIndex = -1;
 }
 mManager.enqueueAction(this,allowStateLoss);
 return mIndex;
}

commit 好像也没干啥特殊的事情,不过可以看到这么一行代码 mManager.enqueueAction(this,allowStateLoss); 看 enqueueAction 这个方法名,应该会做点事情的。

同样,咱们在 FragmentManagerImpl 里找到了这个方法。

public void enqueueAction(Runnable action,boolean allowStateLoss) {
  if (!allowStateLoss) {
    checkStateLoss();
  }
  synchronized (this) {
    if (mDestroyed || mActivity == null) {
      throw new IllegalStateException("Activity has been destroyed");
    }
    if (mPendingActions == null) {
      mPendingActions = new ArrayList<Runnable>();
    }
    mPendingActions.add(action);
    if (mPendingActions.size() == 1) {
      mActivity.mHandler.removeCallbacks(mExecCommit);
      mActivity.mHandler.post(mExecCommit);
    }
  }
}

这个方法把咱们的 BackStackRecord -- 其实是 FragmentTransaction,也是 Runnable -- 添加到一个 mPendingActions 的 ArrayList 里了。然后调用 mActivity.mHandler.post(mExecCommit); mExecCommit 又是什么鬼?

Runnable mExecCommit = new Runnable() {
  @Override
  public void run() {
    execPendingActions();
  }
};
mActivity.mHandler.post(mExecCommit); 说明它在主线程里执行了 mExecCommit 的 run 方法。别问我咋知道的。
execPendingActions() 方法稍微比较大,我把注释写在代码里。
public boolean execPendingActions() {
  if (mExecutingActions) {
    throw new IllegalStateException("Recursive entry to executePendingTransactions");
  }
  //如果不是在主线程,抛出一个异常。
  if (Looper.myLooper() != mActivity.mHandler.getLooper()) {
    throw new IllegalStateException("Must be called from main thread of process");
  }
  boolean didSomething = false;
  // 这里有一个 while true 循环。
  while (true) {
    int numActions;
    // 这里在一个同步语句块里,把上次 mPendingActions 里的元素转移到 mTmpActions 数组里。并且执行 run方法。执行谁的 run 方法呢?!就是 BackStackRecord , 也就是 FragmentTransaction 。我在最后面贴了 BackStackRecord 的 run 方法。
    synchronized (this) {
      if (mPendingActions == null || mPendingActions.size() == 0) {
        break;
      }
      numActions = mPendingActions.size();
      if (mTmpActions == null || mTmpActions.length < numActions) {
        mTmpActions = new Runnable[numActions];
      }
      mPendingActions.toArray(mTmpActions);
      mPendingActions.clear();
      mActivity.mHandler.removeCallbacks(mExecCommit);
    }
    mExecutingActions = true;
    for (int i=0; i<numActions; i++) {
      mTmpActions[i].run();
      mTmpActions[i] = null;
    }
    mExecutingActions = false;
    didSomething = true;
  }
  // 这里有好几行代码,不知道干啥的,反正就是做了一些判断,最后可能会调用 startPendingDeferredFragments() 方法。
  if (mHavePendingDeferredStart) {
    boolean loadersRunning = false;
    for (int i=0; i<mActive.size(); i++) {
      Fragment f = mActive.get(i);
      if (f != null && f.mloaderManager != null) {
        loadersRunning |= f.mloaderManager.hasRunningLoaders();
      }
    }
    if (!loadersRunning) {
      mHavePendingDeferredStart = false;
      startPendingDeferredFragments();
    }
  }
  return didSomething;
}

startPendingDeferredFragments 方法又是一坨不知道啥意思的代码。最后可能调用了 performPendingDeferredStart()

void startPendingDeferredFragments() {
  if (mActive == null) return;
  for (int i=0; i<mActive.size(); i++) {
    Fragment f = mActive.get(i);
    if (f != null) {
      performPendingDeferredStart(f);
    }
  }
}

在 这个方法里,咱们看到了很熟悉的 movetoState() 方法。接着就是上面的分析,Fragment 的 onCreateView 会被调用。

public void performPendingDeferredStart(Fragment f) {
  if (f.mDeferStart) {
    if (mExecutingActions) {
      // Wait until we're done executing our pending transactions
      mHavePendingDeferredStart = true;
      return;
    }
    f.mDeferStart = false;
    movetoState(f,mCurState,false);
  }
}

咱们在回来看 BackStackRecord 的 run 方法。这坨代码有点大,我还是写注释在代码里。

public void run() {
  if (FragmentManagerImpl.DEBUG) Log.v(TAG,"Run: " + this);
  if (mAddToBackStack) {
    if (mIndex < 0) {
      throw new IllegalStateException("addToBackStack() called after commit()");
    }
  }
  bumpBackStacknesting(1);
  TransitionState state = null;
  SparseArray<Fragment> firstOutFragments = null;
  SparseArray<Fragment> lastInFragments = null;
  if (SUPPORTS_TRANSITIONS) {
    firstOutFragments = new SparseArray<Fragment>();
    lastInFragments = new SparseArray<Fragment>();
    calculateFragments(firstOutFragments,lastInFragments);
    state = beginTransition(firstOutFragments,lastInFragments,false);
  }
  int transitionStyle = state != null ? 0 : mTransitionStyle;
  int transition = state != null ? 0 : mTransition;
  // 注意这里要开始 while 循环了,要遍历刚才咱们说的链表了。
  Op op = mHead;
  while (op != null) {
    int enteranim = state != null ? 0 : op.enteranim;
    int exitAnim = state != null ? 0 : op.exitAnim;
    switch (op.cmd) {
      // OP_ADD 很简单,mManager.addFragment(f,false); 其他的几个也类似,调用 mManager 相应的方法。
      case OP_ADD: {
        Fragment f = op.fragment;
        f.mNextAnim = enteranim;
        mManager.addFragment(f,false);
      } break;
      case OP_REPLACE: {
        Fragment f = op.fragment;
        if (mManager.mAdded != null) {
          for (int i=0; i<mManager.mAdded.size(); i++) {
            Fragment old = mManager.mAdded.get(i);
            if (FragmentManagerImpl.DEBUG) Log.v(TAG,"OP_REPLACE: adding=" + f + " old=" + old);
            if (f == null || old.mContainerId == f.mContainerId) {
              if (old == f) {
                op.fragment = f = null;
              } else {
                if (op.removed == null) {
                  op.removed = new ArrayList<Fragment>();
                }
                op.removed.add(old);
                old.mNextAnim = exitAnim;
                if (mAddToBackStack) {
                  old.mBackStacknesting += 1;
                  if (FragmentManagerImpl.DEBUG) Log.v(TAG,"Bump nesting of "
                      + old + " to " + old.mBackStacknesting);
                }
                mManager.removeFragment(old,transition,transitionStyle);
              }
            }
          }
        }
        if (f != null) {
          f.mNextAnim = enteranim;
          mManager.addFragment(f,false);
        }
      } break;
      case OP_REMOVE: {
        Fragment f = op.fragment;
        f.mNextAnim = exitAnim;
        mManager.removeFragment(f,transitionStyle);
      } break;
      case OP_HIDE: {
        Fragment f = op.fragment;
        f.mNextAnim = exitAnim;
        mManager.hideFragment(f,transitionStyle);
      } break;
      case OP_SHOW: {
        Fragment f = op.fragment;
        f.mNextAnim = enteranim;
        mManager.showFragment(f,transitionStyle);
      } break;
      case OP_DETACH: {
        Fragment f = op.fragment;
        f.mNextAnim = exitAnim;
        mManager.detachFragment(f,transitionStyle);
      } break;
      case OP_ATTACH: {
        Fragment f = op.fragment;
        f.mNextAnim = enteranim;
        mManager.attachFragment(f,transitionStyle);
      } break;
      default: {
        throw new IllegalArgumentException("UnkNown cmd: " + op.cmd);
      }
    }
    op = op.next;
  }
  // 最后还调用了movetoState() 这个方法。跟刚才的区别,看最后一个参数,一个true,一个false。
  // 而且注意,这行代码在 while 循环之后。
  mManager.movetoState(mManager.mCurState,transitionStyle,true);
  if (mAddToBackStack) {
    mManager.addBackStackState(this);
  }
}

以上所述是小编给大家介绍的Android Fragment 和 FragmentManager 的代码分析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程小技巧网站的支持!

Android FragmentManage FragmentTransaction 介绍

Android FragmentManage FragmentTransaction 介绍

OSC 请你来轰趴啦!1028 苏州源创会,一起寻宝 AI 时代

FragmentManage:

FragmentManager 能够实现管理 activity 中 fragment. 通过调用 activity 的 getFragmentManager () 取得它的实例.

FragmentManager 可以做如下一些事情:
1、使用 findFragmentById () (用于在 activity layout 中提供一个 UI 的 fragment) 或 findFragmentByTag ()
   (适用于有或没有 UI 的 fragment) 获取 activity 中存在的 fragment
2、将 fragment 从后台堆栈中弹出,使用 popBackStack () (模拟用户按下 BACK 命令).
3、使用 addOnBackStackChangeListener () 注册一个监听后台堆栈变化的 listener.
 

FragmentTransaction:

      FragmentTransaction 对 fragment 进行添加,移除,替换,以及执行其他动作。
从 FragmentManager 获得一个 FragmentTransaction 的实例 :

FragmentManager fragmentManager = getFragmentManager(); 
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

每一个事务都是同时要执行的一套变化。可以在一个给定的事务中设置你想执行的所有变化,使用诸如 add (), remove (), 和 replace (). 然后,要给 activity 应用事务,必须调用 commit ().

在调用 commit () 之前,你可能想调用 addToBackStack (), 将事务添加到一个 fragment 事务的 back stack.  这个 back stack 由 activity 管理,并允许用户通过按下 BACK 按键返回到前一个 fragment 状态.

举个例子,这里是如何将一个 fragment 替换为另一个,并在后台堆栈中保留之前的状态:
 // Create new fragment and transaction  Fragment newFragment = new ExampleFragment();  FragmentTransaction transaction = getFragmentManager().beginTransaction();  // Replace whatever is in the fragment_container view with this fragment,  // and add the transaction to the back stack  transaction.replace(R.id.fragment_container, newFragment);  transaction.addToBackStack(null);  // Commit the transaction  transaction.commit();

在这个例子中,newFragment 替换了当前 layout 容器中的由 R.id.fragment_container 标识的 fragment. 通过调用 addToBackStack (), replace 事务被保存到 back stack, 因此用户可以回退事务,并通过按下 BACK 按键带回前一个 fragment.

如果添加多个变化到事务 (例如 add () 或 remove ()) 并调用 addToBackStack (), 然后在你调用 commit () 之前的所有应用的变化会被作为一个单个事务添加到后台堆栈,BACK 按键会将它们一起回退.

添加变化到 FragmentTransaction 的顺序不重要,除以下例外:
  • 必须最后调用 commit ().
  • 如果添加多个 fragment 到同一个容器,那么添加的顺序决定了它们在 view hierarchy 中显示的顺序.
当执行一个移除 fragment 的事务时,如果没有调用 addToBackStack (), 那么当事务提交后,那个 fragment 会被销毁,并且用户不能导航回到它。有鉴于此,当移除一个 fragment 时,如果调用了 addToBackStack (), 那么 fragment 会被停止,如果用户导航回来,它将会被恢复.

提示:对于每一个 fragment 事务,你可以应用一个事务动画,通过在提交事务之前调用 setTransition () 实现.

调用 commit () 并不立即执行事务。恰恰相反,它将事务安排排期,一旦准备好,就在 activity 的 UI 线程上运行 (主线程). 如果有必要,无论如何,你可以从你的 UI 线程调用 executePendingTransactio ns () 来立即执行由 commit () 提交的事务.  但这么做通常不必要,除非事务是其他线程中的 job 的一个从属.

警告: 你只能在 activity 保存它的状态 (当用户离开 activity) 之前使用 commit () 提交事务.

如果你试图在那个点之后提交,会抛出一个异常。这是因为如果 activity 需要被恢复,提交之后的状态可能会丢失。对于你觉得可以丢失提交的状况,使用 commitAllowingStateLoss ().

 

 

 

 

 

 

/**
* @author 张兴业
* 邮箱: xy-zhang#163.com
* android 开发进阶群: 278401545
*
*/

android – AppCompat v7:我应该使用Framework FragmentManager还是SupportFragmentManager?

android – AppCompat v7:我应该使用Framework FragmentManager还是SupportFragmentManager?

我正在创建一个应该有minSdk = 15和targetSdk = 21的应用程序,因此我想使用appcompat-v7库提供的功能.

我总是想知道在使用supportlibrary-v7时是否应该使用getFragmentManager或getSupportFragmentManager.

我现在遇到一个小问题:当使用getFragmentManager(因此使用框架片段和fragmenttransaction)时,我无法通过简单地按下后退按钮来弹出backstack – 我不得不做一个backStackCount> 0检查并手动popBackStack,否则我的活动就完成了.当我将我的小应用程序切换为使用v4类(getSupportFragmentManager等)时,此问题得以解决.我觉得这很好,但我想有一个指导方针/最佳实践,以了解哪条路走,为什么

所以,我的Activity继承自ActionBaractivity(根据AppCompat-Blog-Entry),我使用的是新工具栏,我应该只使用v4-Fragments(-Manager,-Transactions)吗?

我没有找到任何最佳实践或指导.我不确定在决定这两者时要考虑什么: – /

解决方法:

如果从ActionBaractivity继承活动,则应始终使用getSupportFragmentManager().如果手机支持它(运行Honeycomb或更高版本),它会自动将您的调用转发到getFragmentManager(),否则它会使用其兼容性实现.

我们今天的关于SupportMapFragment不支持AndroidX Fragment安卓不支持support的分享已经告一段落,感谢您的关注,如果您想了解更多关于android 3.0中的getSupportFragmentManager()与getFragmentManager()、Android Fragment 和 FragmentManager 的代码分析、Android FragmentManage FragmentTransaction 介绍、android – AppCompat v7:我应该使用Framework FragmentManager还是SupportFragmentManager?的相关信息,请在本站查询。

本文标签: