私のAndroidアプリでは、セットアップと読み込みを行うスプラッシュ画面があります。私のアプリはwindowEnterTransition
ととwindowSharedElementExitTransition
としてとchangeImageTransform
とchangeBounds
の遷移を設定してデフォルトのexplode
を使用しています。便宜上、私は次のActivity
を静的メソッドを使って開始します。ここではActivity
をContext
と共有要素として渡します。コードはこのポストの第2部で提供されています。ViewRootImpl.setPausedForTransition(boolean)他のアクティビティへの遷移が早すぎるとActivityTransitionCoordinatorのNullPointerExceptionが発生しました
シナリオの1つは、ロードするものがないということです。そのため、アプリケーションはすぐ次のActivity
を起動します。問題は、この場合、アプリはActivityTransitionCoordinator
の中で何とか謎めいてクラッシュし、このポストの次の部分で与えられたスタックであるということです。内部のデバッグは、そこに達成されたViewRootImpl
がヌルでヌルチェックがないことを示しているので、viewRoot.setPausedForTransition(false)
を呼び出すとNullPointerException
がスローされます。あなたは、この不都合な点を以下のコードで見つけることができます。
この失敗シナリオに焦点を当てて、ロードするものがないと判断し、次のActivity
をすぐに開始するロジックを単純化して、前述のアクティビティを開始するだけで簡単に行うことができると仮定しましょう。
第Activity
の開始がonCreate()
、onResume()
、又はonEnterAnimationComplete()
方法で呼び出された場合には違いはありません。私は、遷移が終了したときにとgetWindow().getEnterTransition()
を呼び出すことによって取得された遷移でリスナーを追加して、次のActivity
の開始を許可しようとしました。与えられたTransitions
はnullではありませんが、appは接続されたリスナーのメソッドに決して行きません。
私が今使用している回避策は、次のActivity
の呼び出しを遅らせるようにRunnable
をスケジュールすることです。
これがAndroid
(具体的にはSupportLibrary
)の問題であるかどうか、私は何か迷っています。誰も似たような問題に遭遇しましたか?
スタックトレース:
08-12 00:35:32.550 26453-26453/com.faver.mkoslacz.faverdemo E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.faver.mkoslacz.faverdemo, PID: 26453
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.ViewRootImpl.setPausedForTransition(boolean)' on a null object reference
at android.app.ActivityTransitionCoordinator.startInputWhenTransitionsComplete(ActivityTransitionCoordinator.java:897)
at android.app.ActivityTransitionCoordinator.viewsTransitionComplete(ActivityTransitionCoordinator.java:885)
at android.app.ExitTransitionCoordinator.getExitTransition(ExitTransitionCoordinator.java:318)
at android.app.ExitTransitionCoordinator.beginTransitions(ExitTransitionCoordinator.java:365)
at android.app.ExitTransitionCoordinator.-wrap0(ExitTransitionCoordinator.java)
at android.app.ExitTransitionCoordinator$4.run(ExitTransitionCoordinator.java:216)
at android.app.ActivityTransitionCoordinator.startTransition(ActivityTransitionCoordinator.java:773)
at android.app.ExitTransitionCoordinator.startExit(ExitTransitionCoordinator.java:213)
at android.app.ActivityTransitionState.startExitOutTransition(ActivityTransitionState.java:317)
at android.app.Activity.cancelInputsAndStartExitTransition(Activity.java:3960)
at android.app.Activity.startActivityForResult(Activity.java:3936)
at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:48)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:75)
at android.app.Activity.startActivity(Activity.java:4196)
at com.faver.mkoslacz.faverdemo.activity.AuthorizationActivity.startWithTransiton(AuthorizationActivity.java:45)
at com.faver.mkoslacz.faverdemo.activity.SplashActivity.onEnterAnimationComplete(SplashActivity.java:27)
at android.app.Activity.dispatchEnterAnimationComplete(Activity.java:5852)
at android.app.ActivityThread.handleEnterAnimationComplete(ActivityThread.java:2668)
at android.app.ActivityThread.-wrap10(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1558)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
ActivityTransitionAnimator
に失敗コード:
private void startInputWhenTransitionsComplete() {
if (mViewsTransitionComplete && mSharedElementTransitionComplete) {
final View decor = getDecor();
if (decor != null) {
final ViewRootImpl viewRoot = decor.getViewRootImpl(); // it's null
viewRoot.setPausedForTransition(false); // crashes here
}
onTransitionsComplete();
}
}
次Activity
を開始する方法:
public static void startWithTransiton(Activity activity, android.view.View logo) {
Intent intent = new Intent(activity, AuthorizationActivity.class);
ActivityOptionsCompat options = ActivityOptionsCompat
.makeSceneTransitionAnimation(
activity,
logo,
activity.getString(R.string.logoTransfer));
activity.startActivity(intent, options.toBundle());
}
スプラッシュActivity
内容(簡体字):
public class SplashActivity extends AppCompatActivity {
private static final String TAG = "SplashActivity";
private View logo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
logo = findViewById(R.id.logo);
// AuthorizationActivity.startWithTransiton(this, logo); // will fail
new Handler().postDelayed(() -> {
AuthorizationActivity.startWithTransiton(this, logo); // executes flawlessly
}, 300);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
Transition sharedElementEnterTransition = getWindow().getSharedElementEnterTransition();
if (sharedElementEnterTransition != null) {
sharedElementEnterTransition.addListener(new Transition.TransitionListener() {
@Override
public void onTransitionStart(Transition transition) {
Log.d(TAG, "onTransitionStart: never executes");
}
@Override
public void onTransitionEnd(Transition transition) {
Log.d(TAG, "onTransitionEnd: never executes");
}
@Override
public void onTransitionCancel(Transition transition) {
Log.d(TAG, "onTransitionCancel: never executes");
}
@Override
public void onTransitionPause(Transition transition) {
Log.d(TAG, "onTransitionPause: never executes");
}
@Override
public void onTransitionResume(Transition transition) {
Log.d(TAG, "onTransitionResume: never executes");
}
});
}
Transition enterTransition = getWindow().getEnterTransition();
if (enterTransition != null) {
enterTransition.addListener(new Transition.TransitionListener() {
@Override
public void onTransitionStart(Transition transition) {
Log.d(TAG, "onTransitionStart: never executes");
}
@Override
public void onTransitionEnd(Transition transition) {
Log.d(TAG, "onTransitionEnd: never executes");
}
@Override
public void onTransitionCancel(Transition transition) {
Log.d(TAG, "onTransitionCancel: never executes");
}
@Override
public void onTransitionPause(Transition transition) {
Log.d(TAG, "onTransitionPause: never executes");
}
@Override
public void onTransitionResume(Transition transition) {
Log.d(TAG, "onTransitionResume: never executes");
}
});
}
}
}
@Override
protected void onResume() {
super.onResume();
// AuthorizationActivity.startWithTransiton(this, logo); // will fail
}
@Override
public void onEnterAnimationComplete() {
super.onEnterAnimationComplete();
// AuthorizationActivity.startWithTransiton(this, logo); // will fail
}
}
同様の質問に対する私のコメントを参照してください[http://stackoverflow.com/questions/36557479/...](http://stackoverflow.com/questions/36557479/conent-transition-npe-with-empty-共有要素#comment66253761_36557479) – Olumide
@Olumide実際には、あなたの提案を適用すると私のアニメーションは動作しません。私の回避策はそれらを延期するが、少なくとも彼らは働く。申し訳ありません:( – mkoslacz
それは私のために働くのでidk – Olumide