質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Q&A

解決済

2回答

6239閲覧

getViewLifecycleOwner()でLifecycleOwnerオブジェクトが取得できない

I_LIKE_EGGS

総合スコア11

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

0グッド

0クリップ

投稿2020/05/05 10:11

前提・実現したいこと

Androidアプリを開発しています。
ViewModelとLiveDataを実装してデータ共有したいです。

発生している問題・エラーメッセージ

LiveDataのObserverの設定が上手くいきません。
具体的にはMutableLiveDataのobseveメソッドの第一引数にLifecycleOwnerオブジェクトを入れるため
getViewLifecycleOwner()にて取得を試みているのですがNullが返ってくるのっだと思います。(CenterFragment.javaのコメント行の箇所)
なぜNullが返ってくるのでしょうか?
ライフサイクル的にNullが返る状況ではないと思いますが、、、

エラーメッセージ 2020-05-05 17:33:21.125 10181-10181/? E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.myapplication_ver2, PID: 10181 java.lang.IllegalStateException: Can't access the Fragment View's LifecycleOwner when getView() is null i.e., before onCreateView() or after onDestroyView() at androidx.fragment.app.Fragment.getViewLifecycleOwner(Fragment.java:328) at com.example.myapplication_ver2.CenterFragment.onCreate(CenterFragment.java:25) at androidx.fragment.app.Fragment.performCreate(Fragment.java:2684) at androidx.fragment.app.FragmentStateManager.create(FragmentStateManager.java:270) at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1173) at androidx.fragment.app.FragmentTransition.addToFirstInLastOut(FragmentTransition.java:1255) at androidx.fragment.app.FragmentTransition.calculateFragments(FragmentTransition.java:1138) at androidx.fragment.app.FragmentTransition.startTransitions(FragmentTransition.java:136) at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1987) at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1945) at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1847) at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2621) at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2569) at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:247) at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:541) at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:201) at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1391) at android.app.Activity.performStart(Activity.java:7157) at android.app.ActivityThread.handleStartActivity(ActivityThread.java:2937) at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:180) at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:165) at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:142) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:6669) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

該当のソースコード

CenterFragment.java

java

1package com.example.myapplication_ver2; 2 3import android.graphics.Color; 4import android.os.Bundle; 5import android.util.Log; 6import android.view.LayoutInflater; 7import android.view.View; 8import android.view.ViewGroup; 9import android.widget.Button; 10import android.widget.LinearLayout; 11import androidx.annotation.NonNull; 12import androidx.annotation.Nullable; 13import androidx.fragment.app.Fragment; 14import androidx.lifecycle.LifecycleOwner; 15import androidx.lifecycle.MutableLiveData; 16import androidx.lifecycle.Observer; 17import androidx.lifecycle.ViewModelProviders; 18 19public class CenterFragment extends Fragment { 20 21 @Nullable 22 @Override 23 public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 24 25 LinearLayout linearLayout = new LinearLayout(getContext()); 26 linearLayout.setBackgroundColor(Color.BLUE); 27 container.addView(linearLayout); 28 29 Button button = new Button(getContext()); 30 linearLayout.addView(button); 31 return super.onCreateView(inflater, container, savedInstanceState); 32 } 33 34 @Override 35 public void onActivityCreated(@Nullable Bundle savedInstanceState) { 36 37 super.onActivityCreated(savedInstanceState); 38 ViewModelA viewModelA = ViewModelProviders.of(this).get(ViewModelA.class); 39 viewModelA.getList().observe(getViewLifecycleOwner(), new Observer<Integer>() { //恐らくgetViewLifecycleOwner()でnullが返ってくる事によるエラー 40 @Override 41 public void onChanged(Integer s) { 42 } 43 }); 44 45 } 46} 47

MainActivity.java

java

1package com.example.myapplication_ver2; 2 3import androidx.appcompat.app.AppCompatActivity; 4import androidx.constraintlayout.widget.ConstraintLayout; 5import androidx.fragment.app.Fragment; 6import androidx.fragment.app.FragmentManager; 7import androidx.fragment.app.FragmentTransaction; 8 9import android.os.Bundle; 10import android.widget.LinearLayout; 11 12public class MainActivity extends AppCompatActivity { 13 14 @Override 15 protected void onCreate(Bundle savedInstanceState) { 16 super.onCreate(savedInstanceState); 17 setContentView(R.layout.activity_main); 18 19 FragmentManager fragmentManager = getSupportFragmentManager(); 20 FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 21 fragmentTransaction.add(R.id.layout,new CenterFragment()); 22 fragmentTransaction.commit(); 23 } 24} 25

ViewModelA.java

java

1package com.example.myapplication_ver2; 2 3import androidx.lifecycle.LiveData; 4import androidx.lifecycle.MutableLiveData; 5import androidx.lifecycle.ViewModel; 6 7public class ViewModelA extends ViewModel { 8 private MutableLiveData<Integer> liveData; 9 10 public MutableLiveData<Integer> getList(){ 11 if(liveData==null){ 12 liveData = new MutableLiveData(); 13 } 14 return liveData; 15 } 16 17} 18

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nakasho_dev

2020/05/05 11:49

FragmentのViewがnullだからエラーになっていると思われます。エラーが発生しているタイミングが分かりませんが、起動時ならばonCreateViewの結果がnullの可能性もありそうです。デバッグ実行で確認してみてはいかがでしょうか?そもそも@Nullableって必要でしたっけ?
I_LIKE_EGGS

2020/05/05 12:07 編集

問題点は私もそこだと思ってます。 観察すると FragmentのgetViewLifecycleOwner()で最初のif (mViewLifecycleOwner == null)でtrueの為IllegalStateExceptionを吐いているようでした。 mViewLifecycleOwner がnullという事はViewが作成されていないのだと思います。 ---Fragment.java---326行目 public LifecycleOwner getViewLifecycleOwner() { if (mViewLifecycleOwner == null) { throw new IllegalStateException("Can't access the Fragment View's LifecycleOwner when " + "getView() is null i.e., before onCreateView() or after onDestroyView()"); } return mViewLifecycleOwner; } ------ @NullableはonActivityCreatedをoverrideする際、Androidstudioが勝手につけるのでいつもそのまま使っています。ここに問題がありますかね、、?
nakasho_dev

2020/05/05 12:43

@Nullableは問題なかったようです。すいません。 デバッグ実行してonCreateViewの最終行の実行がnullになるのであればContainerに格納しているViewに問題がありそうですね。
I_LIKE_EGGS

2020/05/05 12:56

デバックで追ってみたら super.onCreateView(inflater, container, savedInstanceState)でnullが返っている事によりonCreateViewの返り値がnullになり、その後mViewLifecycleOwner = nullが挿入され問題を引き起こしていました>< nullを返らせない為にはFragment作成時(つまりnew Fragment())引数を与えなければならないようです。 いつもFragment作成時引数なしでやっていた為、何を与えたらいいのかわかりません。 もしわかればよろしくお願いいたしますm(__)m
nakasho_dev

2020/05/05 13:06

根本的な解決になるか分かりませんがレイアウトXMLファイルをinflaterで読み込む方式だとどうですか?
I_LIKE_EGGS

2020/05/05 13:28

すみません。今androidデベロッパーViewModelのサンプルを見ていたら ViewModelA viewModelA = ViewModelProviders.of(this).get(ViewModelA.class); のof(this)の部分がof(getActivity())になっており、 observe()の第一引数もgetActivity()になっておりました。 最初個人ブログのサンプルで ViewModelA viewModelA = ViewModelProviders.of(this).get(ViewModelA.class);となっており、 そちらを入れたら、その事が原因かわかりませんが、 observe()の第一引数にthisが入らず、AndroidstudioにgetViewLifecycleOwner()に置き換えろと怒られた為、getViewLifecycleOwner()を挿入し、今回のエラーにぶち当たり、質問しました。 もしかしたら根本的違うかもしれません。 質問はまだ閉じませんが、色々試行錯誤してみます。
I_LIKE_EGGS

2020/05/05 13:42

すみません、自己解決しました為解決方法を自己解決欄に記載しておきます。 ありがとうございます。
nakasho_dev

2020/05/05 14:22

自己解決したようで良かったです。ちなみにViewModelProviders.ofはDeprecatedになっているので気をつけてください。
I_LIKE_EGGS

2020/05/05 15:36

ですねf^^いつかここの部分でエラーを起こすかもしれないので気を付けるようにしますf^^
guest

回答2

0

すでに解決済みにされていますが、気になったので回答します。

Fragment::getViewLifecycleOwnerがnullを返す場合、2通りの理由が考えられます。

  1. onCreateViewでnullを返している(UIを持たないFragment)
  2. onCreateViewの前、もしくはonDestroyView後にgetViewLifecycleOwnerを呼び出している

ご提示のコードの場合は、1.のパターンになっています。

java

1public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 2 ... 3 container.addView(linearLayout); 4 ... 5 return super.onCreateView(inflater, container, savedInstanceState); 6}

上記のコードはFragmentの使い方として不適切ですので、container.addView(linearLayout)は削除して、linearLayoutをreturnするように変更してください。そうすればlinearLayoutがFragmentのViewとして設定され、getViewLifecycleOwnerが利用できるようになるはずです。

また、Fragment内でobserveの第1引数にgetActivity()を渡すのはメモリリークの原因となるのでご注意ください。基本的には自身のライフサイクルに基づくLifecycleOwnerを渡すべきです。

投稿2020/05/08 22:31

kakajika

総合スコア3131

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

I_LIKE_EGGS

2020/05/08 23:30

container.addView(linewarLayout)は不適切な使い方なんですね!参考になりました。ありがとうございます。 LinearLayoutをreturnする方法もあるんですね(っていうかそれが本来の使い方か…) observeの第1引数の件も参考にさせて頂きます。ありがとうございます!
guest

0

自己解決

そもそも今回FragmentAとFragmentBとFragmentが二つありFragment間でデータを連動させていました。
そもそもFragment間でデータをやり取りする際ViewModel取得の設定でof(this)ではなくof(getActivity())としなければならなかったようです。

of(this)としてその後、observe()の第一引数をgetActivity()としていた為、エラーを吐かずデータが連動しなかった為はまってしまいました。

そしてgetActivity()の部分が違うのかと思い込みgetViewLifecycleOwner()にしたところエラーを吐き今回の質問させて頂きました。

そもそも問題点がobserve()の設定ではあらず、ViewModel取得の設定でof()部分だった為、みるところを根本的に間違えてしまいました。
以上のような経緯により問題の解決にいたりました。

ちなみに
of(this)でもof(getActivity())でもその後observeメソッドの第一引数にgetViewLifecycleOwner()を入れてしまうとエラーを吐きます。

public LifecycleOwner getViewLifecycleOwner() {
if (mViewLifecycleOwner == null) {
throw new IllegalStateException("Can't access the Fragment View's LifecycleOwner when "
+ "getView() is null i.e., before onCreateView() or after onDestroyView()");
}
return mViewLifecycleOwner;
}
でmViewLifecycleOwner が nullになっている事によりif文に捕まってしまうためです。

第一引数にgetActivity()を入れるとエラーは吐きませんが、Fragment間のデータの連動が上手くいきません。
ActivityとViewModelの連携の場合of(this)にするのだと思います。

投稿2020/05/05 15:26

I_LIKE_EGGS

総合スコア11

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問