LoginSignup
3
1

More than 5 years have passed since last update.

Support Library 25.1 から Fragment#onCreateAnimation のタイミングが変わっている話

Last updated at Posted at 2017-08-13

TL;DR

最近、手元のプログラムの Support Library のバージョンを 25.0.1 から最新版に上げたところ、画面遷移のアニメーションが発生しなくなりました。調べてみると、 Support Library のバージョン 25.1.0 から、Fragment 表示時に onCreateAnimation が呼び出されるタイミングが変わっていました。

Support Library onCreateAnimation が呼ばれるタイミング
25.0.1 onCreateView の後、onViewCreated の前
25.1.0以降 onResume の後

どんな問題が起こるか

Fragment#onResume より前に onCreateAnimation が呼び出されることを仮定したようなコードを書いていると1、アニメーションが正常に動作しない可能性があります。

この挙動の変化は、Support Library の 25.1.0 で FragmentTransaction の最適化機能が追加された影響ではないかと思います。最適化はFragmentTransaction.setAllowOptimization(false) を設定するとオフにすることができ、また (25.1.0 でユーザーから悲鳴が上がったためか) 25.1.1 からはデフォルトでオフです。しかし、 onCreateAnimation の呼び出しタイミングについては、最適化がオンでもオフでも変化しません。

調査

テスト用フラグメントを作って確認してみました。ソースコード全体は GitHub においてあります

コード抜粋

TestFragment.java
public class TestFragment extends Fragment {

    public TestFragment() {
    }

    private void trace(String method) {
        Log.i("LifeCycle", Integer.toHexString(this.hashCode()) + "#" + method);
    }

    @Override
    public void onAttach(Context context) {
        trace("onAttach");
        super.onAttach(context);
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        trace("onCreate");
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        trace("onCreateView");
        return inflater.inflate(R.layout.fr_test, container, false);
    }
(以下略)

フラグメントの表示は次のように行います。

FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.setAllowOptimization(false); // 25.0.1 以前でビルドする時はコメントアウト
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
Fragment fragment = new TestFragment();
ft.replace(R.id.content_main, fragment);
ft.addToBackStack(null);
ft.commit();

実行結果

SDK 25.0.1 でビルドして実行すると、次のようになります。

25.0.1
I/LifeCycle: 869229f#onAttach
I/LifeCycle: 869229f#onCreate
I/LifeCycle: 869229f#onCreateView
I/LifeCycle: 869229f#onCreateAnimation
I/LifeCycle: 869229f#onViewCreated
I/LifeCycle: 869229f#onStart
I/LifeCycle: 869229f#onResume

SDK 25.1.0 以降でビルドして実行すると、次のようになります。

25.1.0以降
I/LifeCycle: c6cefb5#onAttach
I/LifeCycle: c6cefb5#onCreate
I/LifeCycle: c6cefb5#onCreateView
I/LifeCycle: c6cefb5#onViewCreated
I/LifeCycle: c6cefb5#onStart
I/LifeCycle: c6cefb5#onResume
I/LifeCycle: c6cefb5#onCreateAnimation

上記の実行結果は、 次の組み合わせで確認しています。

Compile SDK Build Tool Support Library
25 25.0.3 25.1.0
25 25.0.3 25.1.1
25 25.0.3 25.4.0
26 26.0.0 26.0.0

おわりに

onCreateAnimation の実行タイミングはドキュメントに明確な記載がなかったとはいえ、アニメーションのようにオブジェクトの生存タイミングに敏感な処理について、突然このような仕様変更を入れるのはひどいなかなかの大変更と思います。なお setAllowOptimization メソッドは API レベル 26 から setReorderingAllowed というメソッド名にすぐ変更になるなど、落ち着きがありません。この周辺の仕様はまた変化する可能性を踏まえて、ウォッチしておいた方が良さそうです。


  1. 本来 onCreateAnimation に Fragment の状態に依存するコードは書かないべきですが。 

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1